org-eval.el 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. ;;; org-eval.el --- Display result of evaluating code in various languanges
  2. ;; Copyright (C) 2008 Free Software Foundation, Inc.
  3. ;;
  4. ;; Author: Carsten Dominik <carsten at orgmode dot org>
  5. ;; Keywords: outlines, hypermedia, calendar, wp
  6. ;; Homepage: http://orgmode.org
  7. ;; Version: 0.03
  8. ;;
  9. ;; This file is not yet part of GNU Emacs.
  10. ;;
  11. ;; GNU Emacs is free software; you can redistribute it and/or modify
  12. ;; it under the terms of the GNU General Public License as published by
  13. ;; the Free Software Foundation; either version 3, or (at your option)
  14. ;; any later version.
  15. ;; GNU Emacs is distributed in the hope that it will be useful,
  16. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ;; GNU General Public License for more details.
  19. ;; You should have received a copy of the GNU General Public License
  20. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  21. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  22. ;; Boston, MA 02110-1301, USA.
  23. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  24. ;;
  25. ;;; Commentary:
  26. ;;
  27. ;; This modules allows to include output from various commands into an
  28. ;; Org-mode buffer. This technique has been copied from Emacs-Muse, and
  29. ;; we try to make it work here in a way as simila as possible to
  30. ;; Muse.
  31. (require 'org)
  32. ;;; Customization
  33. (defgroup org-eval nil
  34. "Options concerning including output from commands into the Org-mode buffer."
  35. :tag "Org Eval"
  36. :group 'org)
  37. (defface org-eval
  38. (org-compatible-face nil
  39. '((((class color grayscale) (min-colors 88) (background light))
  40. (:foreground "grey40"))
  41. (((class color grayscale) (min-colors 88) (background dark))
  42. (:foreground "grey60"))
  43. (((class color) (min-colors 8) (background light))
  44. (:foreground "green"))
  45. (((class color) (min-colors 8) (background dark))
  46. (:foreground "yellow"))))
  47. "Face for command output that is included into an Org-mode buffer."
  48. :group 'org-eval
  49. :group 'org-faces
  50. :version "22.1")
  51. (defvar org-eval-regexp nil)
  52. (defun org-eval-set-interpreters (var value)
  53. (set-default var value)
  54. (setq org-eval-regexp
  55. (concat "<\\("
  56. (mapconcat 'regexp-quote value "\\|")
  57. "\\)"
  58. "\\([^>]\\{0,50\\}?\\)>"
  59. "\\([^\000]+?\\)</\\1>")))
  60. (defcustom org-eval-interpreters '("lisp")
  61. "Interpreters allows for evaluation tags.
  62. This is a list of program names (as strings) that can evaluate code and
  63. insert the output into an Org-mode buffer. Valid choices are
  64. lisp Interpret Emacs Lisp code and display the result
  65. shell Pass command to the shell and display the result
  66. perl The perl interpreter
  67. python Thy python interpreter
  68. ruby The ruby interpreter"
  69. :group 'org-eval
  70. :set 'org-eval-set-interpreters
  71. :type '(set :greedy t
  72. (const "lisp")
  73. (const "perl")
  74. (const "python")
  75. (const "ruby")
  76. (const "shell")))
  77. (defun org-eval-handle-snippets (limit &optional replace)
  78. "Evaluate code nisppets and display the results as display property.
  79. When REPLACE is non-nil, replace the code region with the result (used
  80. for export)."
  81. (let (a)
  82. (while (setq a (text-property-any (point) (or limit (point-max))
  83. 'org-eval t))
  84. (remove-text-properties
  85. a (next-single-property-change a 'org-eval nil limit)
  86. '(display t intangible t org-eval t))))
  87. (while (re-search-forward org-eval-regexp limit t)
  88. (let* ((beg (match-beginning 0))
  89. (end (match-end 0))
  90. (kind (match-string 1))
  91. (attr (match-string 2))
  92. (code (match-string 3))
  93. (value (org-eval-code kind code))
  94. markup lang)
  95. (if replace
  96. (progn
  97. (setq attr (save-match-data (org-eval-get-attributes attr))
  98. markup (cdr (assoc "markup" attr))
  99. lang (cdr (assoc "lang" attr)))
  100. (replace-match
  101. (concat (if markup (format "#+BEGIN_%s" (upcase markup)))
  102. (if (and markup (equal (downcase markup) "src"))
  103. (concat " " (or lang "fundamental")))
  104. "\n"
  105. value
  106. (if markup (format "\n#+END_%s\n" (upcase markup))))
  107. t t))
  108. (add-text-properties
  109. beg end
  110. (list 'display value 'intangible t 'font-lock-multiline t
  111. 'face 'org-eval
  112. 'org-eval t))))))
  113. (defun org-eval-replace-snippts ()
  114. "Replace EVAL snippets in the entire buffer.
  115. This should go into the `org-export-preprocess-hook'."
  116. (goto-char (point-min))
  117. (org-eval-handle-snippets nil 'replace))
  118. (add-hook 'org-export-preprocess-hook 'org-eval-replace-snippts)
  119. (add-hook 'org-font-lock-hook 'org-eval-handle-snippets)
  120. (defun org-eval-get-attributes (str)
  121. (let ((start 0) key value rtn)
  122. (while (string-match "\\<\\([a-zA-Z]+\\)\\>=\"\\([^\"]+\\)\"" str start)
  123. (setq key (match-string 1 str)
  124. value (match-string 2 str)
  125. start (match-end 0))
  126. (push (cons key value) rtn))
  127. rtn))
  128. (defun org-eval-code (interpreter code)
  129. (cond
  130. ((equal interpreter "lisp")
  131. (org-eval-lisp (concat "(progn\n" code "\n)")))
  132. ((equal interpreter "shell")
  133. (shell-command-to-string code))
  134. ((member interpreter '("perl" "python" "ruby"))
  135. (org-eval-run (executable-find interpreter) code))
  136. (t (error "Cannot evaluate code type %s" interpreter))))
  137. (defun org-eval-lisp (form)
  138. "Evaluate the given form and return the result as a string."
  139. (require 'pp)
  140. (save-match-data
  141. (condition-case err
  142. (let ((object (eval (read form))))
  143. (cond
  144. ((stringp object) object)
  145. ((and (listp object)
  146. (not (eq object nil)))
  147. (let ((string (pp-to-string object)))
  148. (substring string 0 (1- (length string)))))
  149. ((numberp object)
  150. (number-to-string object))
  151. ((eq object nil) "")
  152. (t
  153. (pp-to-string object))))
  154. (error
  155. (org-display-warning (format "%s: Error evaluating %s: %s"
  156. "???" form err))
  157. "; INVALID LISP CODE"))))
  158. (defun org-eval-run (cmd code)
  159. (with-temp-buffer
  160. (insert code)
  161. (shell-command-on-region (point-min) (point-max) cmd nil 'replace)
  162. (buffer-string)))
  163. (provide 'org-eval)
  164. ;;; org-eval.el ends here