123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- (defcustom org-export-blocks
- '(( org-export-blocks-format-comment)
- (ditaa org-export-blocks-format-ditaa)
- (dot org-export-blocks-format-dot)
- (r org-export-blocks-format-R)
- (R org-export-blocks-format-R))
- "Use this a-list to associate block types with block exporting
- functions. The type of a block is determined by the text
- immediately following the '#+BEGIN_' portion of the block header.
- Each block export function should accept three argumets..."
- :group 'org-export-general
- :type 'alist)
- (defcustom org-export-interblocks
- '((r org-export-interblocks-format-R)
- (R org-export-interblocks-format-R))
- "Use this a-list to associate block types with block exporting
- functions. The type of a block is determined by the text
- immediately following the '#+BEGIN_' portion of the block header.
- Each block export function should accept three argumets..."
- :group 'org-export-general
- :type 'alist)
- (defcustom org-export-blocks-witheld
- '(hidden)
- "List of block types (see `org-export-blocks') which should not
- be exported."
- :group 'org-export-general
- :type 'list)
- (defvar org-export-blocks-postblock-hooks nil "")
- (defun org-export-blocks-html-quote (body &optional open close)
- "Protext BODY from org html export. The optional OPEN and
- CLOSE tags will be inserted around BODY."
- (concat
- "\n#+BEGIN_HTML\n"
- (or open "")
- body (if (string-match "\n$" body) "" "\n")
- (or close "")
- "#+END_HTML\n"))
- (defun org-export-blocks-latex-quote (body &optional open close)
- "Protext BODY from org latex export. The optional OPEN and
- CLOSE tags will be inserted around BODY."
- (concat
- "\n#+BEGIN_LaTeX\n"
- (or open "")
- body (if (string-match "\n$" body) "" "\n")
- (or close "")
- "#+END_LaTeX\n"))
- (defun org-export-blocks-preprocess ()
- "Export all blocks acording to the `org-export-blocks' block
- exportation alist. Does not export block types specified in
- specified in BLOCKS which default to the value of
- `org-export-blocks-witheld'."
- (interactive)
- (save-window-excursion
- (let ((count 0)
- (blocks org-export-blocks-witheld)
- (case-fold-search t)
- (types '())
- type func start end)
- (flet ((interblock (start end type)
- (save-match-data
- (when (setf func (cadr (assoc type org-export-interblocks)))
- (funcall func start end)))))
- (goto-char (point-min))
- (setf start (point))
- (while (re-search-forward
- "^#\\+begin_\\(\\S-+\\)[ \t]*\\(.*\\)?[\r\n]\\([^\000]*?\\)#\\+end_\\S-*[\r\n]" nil t)
- (save-match-data (setf type (intern (match-string 1))))
- (unless (memq type types) (setf types (cons type types)))
- (setf end (save-match-data (match-beginning 0)))
- (interblock start end type)
- (if (setf func (cadr (assoc type org-export-blocks)))
- (replace-match (save-match-data
- (if (memq type blocks)
- ""
- (apply func (match-string 3) (split-string (match-string 2) " ")))) t t))
- (setf start (save-match-data (match-end 0))))
- (mapcar (lambda (type)
- (interblock start (point-max) type))
- types)))))
- (add-hook 'org-export-preprocess-hook 'org-export-blocks-preprocess)
- (defvar org-ditaa-jar-path (expand-file-name
- "ditaa.jar"
- (file-name-as-directory
- (expand-file-name
- "scripts"
- (file-name-as-directory
- (expand-file-name
- ".."
- (file-name-directory (or load-file-name buffer-file-name)))))))
- "Path to the ditaa jar executable")
- (defun org-export-blocks-format-ditaa (body &rest headers)
- "Pass block BODY to the ditaa utility creating an image.
- Specify the path at which the image should be saved as the first
- element of headers, any additional elements of headers will be
- passed to the ditaa utility as command line arguments."
- (message "ditaa-formatting...")
- (let ((out-file (if headers (car headers)))
- (args (if (cdr headers) (mapconcat 'identity (cdr headers) " ")))
- (data-file (make-temp-file "org-ditaa")))
- (unless (file-exists-p org-ditaa-jar-path)
- (error (format "Could not find ditaa.jar at %s" org-ditaa-jar-path)))
- (setq body (if (string-match "^\\([^:\\|:[^ ]\\)" body)
- body
- (mapconcat (lambda (x) (substring x (if (> (length x) 1) 2 1)))
- (org-split-string body "\n")
- "\n")))
- (cond
- ((or htmlp latexp)
- (with-temp-file data-file (insert body))
- (message (concat "java -jar " org-ditaa-jar-path " " args " " data-file " " out-file))
- (shell-command (concat "java -jar " org-ditaa-jar-path " " args " " data-file " " out-file))
- (format "\n[[file:%s]]\n" out-file))
- (t (concat
- "\n#+BEGIN_EXAMPLE\n"
- body (if (string-match "\n$" body) "" "\n")
- "#+END_EXAMPLE\n")))))
- (defun org-export-blocks-format-dot (body &rest headers)
- "Pass block BODY to the dot graphing utility creating an image.
- Specify the path at which the image should be saved as the first
- element of headers, any additional elements of headers will be
- passed to the dot utility as command line arguments. Don't
- forget to specify the output type for the dot command, so if you
- are exporting to a file with a name like 'image.png' you should
- include a '-Tpng' argument, and your block should look like the
- following.
- #+begin_dot models.png -Tpng
- digraph data_relationships {
- \"data_requirement\" [shape=Mrecord, label=\"{DataRequirement|description\lformat\l}\"]
- \"data_product\" [shape=Mrecord, label=\"{DataProduct|name\lversion\lpoc\lformat\l}\"]
- \"data_requirement\" -> \"data_product\"
- }
- #+end_dot"
- (message "dot-formatting...")
- (let ((out-file (if headers (car headers)))
- (args (if (cdr headers) (mapconcat 'identity (cdr headers) " ")))
- (data-file (make-temp-file "org-ditaa")))
- (cond
- ((or htmlp latexp)
- (with-temp-file data-file (insert body))
- (message (concat "dot " data-file " " args " -o " out-file))
- (shell-command (concat "dot " data-file " " args " -o " out-file))
- (format "\n[[file:%s]]\n" out-file))
- (t (concat
- "\n#+BEGIN_EXAMPLE\n"
- body (if (string-match "\n$" body) "" "\n")
- "#+END_EXAMPLE\n")))))
- (defun org-export-blocks-format-comment (body &rest headers)
- "Format comment BODY by OWNER and return it formatted for export.
- Currently, this only does something for HTML export, for all
- other backends, it converts the comment into an EXAMPLE segment."
- (let ((owner (if headers (car headers)))
- (title (if (cdr headers) (mapconcat 'identity (cdr headers) " "))))
- (cond
- (htmlp
- (concat "#+BEGIN_HTML\n"
- "<div class=\"org-comment\""
- (if owner (format " id=\"org-comment-%s\" " owner))
- ">\n"
- (if owner (concat "<b>" owner "</b> ") "")
- (if (and title (> (length title) 0)) (concat " -- " title "</br>\n") "</br>\n")
- "<p>\n"
- "#+END_HTML\n"
- body
- "#+BEGIN_HTML\n"
- "</p>\n"
- "</div>\n"
- "#+END_HTML\n"))
- (t
- (concat "#+BEGIN_EXAMPLE\n"
- (if title (concat "Title:" title "\n") "")
- (if owner (concat "By:" owner "\n") "")
- body
- (if (string-match "\n\\'" body) "" "\n")
- "#+END_EXAMPLE\n")))))
- (defvar interblock-R-buffer nil
- "Holds the buffer for the current R process")
- (defun org-export-blocks-format-R (body &rest headers)
- "Process R blocks and replace \R{} forms outside the blocks
- with their values as determined by R."
- (interactive)
- (message "R processing...")
- (let ((image-path (or (and (car headers)
- (string-match "\\(.?\\)\.\\(EPS\\|eps\\)" (car headers))
- (match-string 1 (car headers)))
- (and (> (length (car headers)) 0)
- (car headers))
-
- (format "Rplot-%03d" count)))
- (plot (string-match "plot" body))
- R-proc)
- (setf count (+ count 1))
- (interblock-initiate-R-buffer)
- (setf R-proc (get-buffer-process interblock-R-buffer))
-
- (setf body (mapconcat (lambda (line)
- (interblock-R-input-command line) (concat "> " line))
- (butlast (split-string body "[\r\n]"))
- "\n"))
-
- (when plot
- (interblock-R-input-command (format "dev.copy2eps(file=\"%s.eps\")" image-path)))
- (concat (cond
- (htmlp (org-export-blocks-html-quote body
- (format "<div id=\"R-%d\">\n<pre>\n" count)
- "</pre>\n</div>\n"))
- (latexp (org-export-blocks-latex-quote body
- "\\begin{Schunk}\n\\begin{Sinput}\n"
- "\\end{Sinput}\n\\end{Schunk}\n"))
- (t (insert
- "#+begin_R " (mapconcat 'identity headers " ") "\n"
- body (if (string-match "\n$" body) "" "\n")
- "#+end_R\n")))
- (if plot
- (format "[[file:%s.eps]]\n" image-path)
- ""))))
- (defun org-export-interblocks-format-R (start end)
- "This is run over parts of the org-file which are between R
- blocks. It's main use is to expand the \R{stuff} chunks for
- export."
- (save-excursion
- (goto-char start)
- (interblock-initiate-R-buffer)
- (let (code replacement)
- (while (and (< (point) end) (re-search-forward "\\\\R{\\(.*\\)}" end t))
- (save-match-data (setf code (match-string 1)))
- (setf replacement (interblock-R-command-to-string code))
- (setf replacement (cond
- (htmlp replacement)
- (latexp replacement)
- (t replacement)))
- (setf end (+ end (- (length replacement) (length code))))
- (replace-match replacement t t)))))
- (defun interblock-initiate-R-buffer ()
- "If there is not a current R process then create one."
- (unless (and (buffer-live-p interblock-R-buffer) (get-buffer interblock-R-buffer))
- (save-excursion
- (R)
- (setf interblock-R-buffer (current-buffer))
- (interblock-R-wait-for-output)
- (interblock-R-input-command ""))))
- (defun interblock-R-command-to-string (command)
- "Send a command to R, and return the results as a string."
- (interblock-R-input-command command)
- (interblock-R-last-output))
- (defun interblock-R-input-command (command)
- "Pass COMMAND to the R process running in `interblock-R-buffer'."
- (save-excursion
- (save-match-data
- (set-buffer interblock-R-buffer)
- (goto-char (process-mark (get-buffer-process (current-buffer))))
- (insert command)
- (comint-send-input)
- (interblock-R-wait-for-output))))
- (defun interblock-R-wait-for-output ()
- "Wait until output arrives"
- (save-excursion
- (save-match-data
- (set-buffer interblock-R-buffer)
- (while (progn
- (goto-char comint-last-input-end)
- (not (re-search-forward comint-prompt-regexp nil t)))
- (accept-process-output (get-buffer-process (current-buffer)))))))
- (defun interblock-R-last-output ()
- "Return the last R output as a string"
- (save-excursion
- (save-match-data
- (set-buffer interblock-R-buffer)
- (goto-char (process-mark (get-buffer-process (current-buffer))))
- (forward-line 0)
- (let ((raw (buffer-substring comint-last-input-end (- (point) 1))))
- (if (string-match "\n" raw)
- raw
- (and (string-match "\\[[[:digit:]+]\\] *\\(.*\\)$" raw)
- (message raw)
- (message (match-string 1 raw))
- (match-string 1 raw)))))))
|