ob-eval.el 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. ;;; ob-run.el --- org-babel functions for external code evaluation
  2. ;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
  3. ;; Author: Eric Schulte
  4. ;; Keywords: literate programming, reproducible research, comint
  5. ;; Homepage: http://orgmode.org
  6. ;; Version: 0.01
  7. ;; This file is part of GNU Emacs.
  8. ;; GNU Emacs is free software: you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation, either version 3 of the License, or
  11. ;; (at your option) any later version.
  12. ;; GNU Emacs is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Commentary:
  19. ;; These functions build existing Emacs support for executing external
  20. ;; shell commands.
  21. ;;; Code:
  22. (require 'ob)
  23. (eval-when-compile (require 'cl))
  24. (defun org-babel-eval-error-notify (exit-code stderr)
  25. "Open a buffer to display STDERR and a message with the value of EXIT-CODE."
  26. (let ((buf (get-buffer-create "*Org-Babel Error Output*")))
  27. (with-current-buffer buf
  28. (goto-char (point-max))
  29. (save-excursion (insert stderr)))
  30. (display-buffer buf))
  31. (message "Babel evaluation exited with code %d" exit-code))
  32. (defun org-babel-eval (cmd body)
  33. "Run CMD on BODY.
  34. If CMD succeeds then return it's results, otherwise display
  35. STDERR with `org-babel-eval-error-notify'."
  36. (let ((err-buff (get-buffer-create "*Org-Babel Error*")) exit-code)
  37. (with-current-buffer err-buff (erase-buffer))
  38. (with-temp-buffer
  39. (insert body)
  40. (setq exit-code
  41. (org-babel-shell-command-on-region
  42. (point-min) (point-max) cmd t 'replace err-buff))
  43. (if (> exit-code 0)
  44. (progn
  45. (with-current-buffer err-buff
  46. (org-babel-eval-error-notify exit-code (buffer-string)))
  47. nil)
  48. (buffer-string)))))
  49. (defun org-babel-eval-read-file (file)
  50. "Return the contents of FILE as a string."
  51. (with-temp-buffer (insert-file-contents
  52. (org-babel-maybe-remote-file file))
  53. (buffer-string)))
  54. (defun org-babel-shell-command-on-region (start end command
  55. &optional output-buffer replace
  56. error-buffer display-error-buffer)
  57. "Execute COMMAND in an inferior shell with region as input.
  58. Fixes bugs in the emacs 23.1.1 version of `shell-command-on-region'
  59. Normally display output (if any) in temp buffer `*Shell Command Output*';
  60. Prefix arg means replace the region with it. Return the exit code of
  61. COMMAND.
  62. To specify a coding system for converting non-ASCII characters in
  63. the input and output to the shell command, use
  64. \\[universal-coding-system-argument] before this command. By
  65. default, the input (from the current buffer) is encoded in the
  66. same coding system that will be used to save the file,
  67. `buffer-file-coding-system'. If the output is going to replace
  68. the region, then it is decoded from that same coding system.
  69. The noninteractive arguments are START, END, COMMAND,
  70. OUTPUT-BUFFER, REPLACE, ERROR-BUFFER, and DISPLAY-ERROR-BUFFER.
  71. Noninteractive callers can specify coding systems by binding
  72. `coding-system-for-read' and `coding-system-for-write'.
  73. If the command generates output, the output may be displayed
  74. in the echo area or in a buffer.
  75. If the output is short enough to display in the echo area
  76. \(determined by the variable `max-mini-window-height' if
  77. `resize-mini-windows' is non-nil), it is shown there. Otherwise
  78. it is displayed in the buffer `*Shell Command Output*'. The output
  79. is available in that buffer in both cases.
  80. If there is output and an error, a message about the error
  81. appears at the end of the output.
  82. If there is no output, or if output is inserted in the current buffer,
  83. then `*Shell Command Output*' is deleted.
  84. If the optional fourth argument OUTPUT-BUFFER is non-nil,
  85. that says to put the output in some other buffer.
  86. If OUTPUT-BUFFER is a buffer or buffer name, put the output there.
  87. If OUTPUT-BUFFER is not a buffer and not nil,
  88. insert output in the current buffer.
  89. In either case, the output is inserted after point (leaving mark after it).
  90. If REPLACE, the optional fifth argument, is non-nil, that means insert
  91. the output in place of text from START to END, putting point and mark
  92. around it.
  93. If optional sixth argument ERROR-BUFFER is non-nil, it is a buffer
  94. or buffer name to which to direct the command's standard error output.
  95. If it is nil, error output is mingled with regular output.
  96. If DISPLAY-ERROR-BUFFER is non-nil, display the error buffer if there
  97. were any errors. (This is always t, interactively.)
  98. In an interactive call, the variable `shell-command-default-error-buffer'
  99. specifies the value of ERROR-BUFFER."
  100. (interactive (let (string)
  101. (unless (mark)
  102. (error "The mark is not set now, so there is no region"))
  103. ;; Do this before calling region-beginning
  104. ;; and region-end, in case subprocess output
  105. ;; relocates them while we are in the minibuffer.
  106. (setq string (read-shell-command "Shell command on region: "))
  107. ;; call-interactively recognizes region-beginning and
  108. ;; region-end specially, leaving them in the history.
  109. (list (region-beginning) (region-end)
  110. string
  111. current-prefix-arg
  112. current-prefix-arg
  113. shell-command-default-error-buffer
  114. t)))
  115. (let ((error-file
  116. (if error-buffer
  117. (make-temp-file
  118. (expand-file-name "scor"
  119. (or (unless (featurep 'xemacs)
  120. small-temporary-file-directory)
  121. temporary-file-directory)))
  122. nil))
  123. exit-status)
  124. (if (or replace
  125. (and output-buffer
  126. (not (or (bufferp output-buffer) (stringp output-buffer)))))
  127. ;; Replace specified region with output from command.
  128. (let ((swap (and replace (< start end))))
  129. ;; Don't muck with mark unless REPLACE says we should.
  130. (goto-char start)
  131. (and replace (push-mark (point) 'nomsg))
  132. (setq exit-status
  133. (call-process-region start end shell-file-name t
  134. (if error-file
  135. (list output-buffer error-file)
  136. t)
  137. nil shell-command-switch command))
  138. ;; It is rude to delete a buffer which the command is not using.
  139. ;; (let ((shell-buffer (get-buffer "*Shell Command Output*")))
  140. ;; (and shell-buffer (not (eq shell-buffer (current-buffer)))
  141. ;; (kill-buffer shell-buffer)))
  142. ;; Don't muck with mark unless REPLACE says we should.
  143. (and replace swap (exchange-point-and-mark)))
  144. ;; No prefix argument: put the output in a temp buffer,
  145. ;; replacing its entire contents.
  146. (let ((buffer (get-buffer-create
  147. (or output-buffer "*Shell Command Output*"))))
  148. (unwind-protect
  149. (if (eq buffer (current-buffer))
  150. ;; If the input is the same buffer as the output,
  151. ;; delete everything but the specified region,
  152. ;; then replace that region with the output.
  153. (progn (setq buffer-read-only nil)
  154. (delete-region (max start end) (point-max))
  155. (delete-region (point-min) (min start end))
  156. (setq exit-status
  157. (call-process-region (point-min) (point-max)
  158. shell-file-name t
  159. (if error-file
  160. (list t error-file)
  161. t)
  162. nil shell-command-switch
  163. command)))
  164. ;; Clear the output buffer, then run the command with
  165. ;; output there.
  166. (let ((directory default-directory))
  167. (with-current-buffer buffer
  168. (setq buffer-read-only nil)
  169. (if (not output-buffer)
  170. (setq default-directory directory))
  171. (erase-buffer)))
  172. (setq exit-status
  173. (call-process-region start end shell-file-name nil
  174. (if error-file
  175. (list buffer error-file)
  176. buffer)
  177. nil shell-command-switch command)))
  178. ;; Report the output.
  179. (with-current-buffer buffer
  180. (setq mode-line-process
  181. (cond ((null exit-status)
  182. " - Error")
  183. ((stringp exit-status)
  184. (format " - Signal [%s]" exit-status))
  185. ((not (equal 0 exit-status))
  186. (format " - Exit [%d]" exit-status)))))
  187. (if (with-current-buffer buffer (> (point-max) (point-min)))
  188. ;; There's some output, display it
  189. (display-message-or-buffer buffer)
  190. ;; No output; error?
  191. (let ((output
  192. (if (and error-file
  193. (< 0 (nth 7 (file-attributes error-file))))
  194. "some error output"
  195. "no output")))
  196. (cond ((null exit-status)
  197. (message "(Shell command failed with error)"))
  198. ((equal 0 exit-status)
  199. (message "(Shell command succeeded with %s)"
  200. output))
  201. ((stringp exit-status)
  202. (message "(Shell command killed by signal %s)"
  203. exit-status))
  204. (t
  205. (message "(Shell command failed with code %d and %s)"
  206. exit-status output))))
  207. ;; Don't kill: there might be useful info in the undo-log.
  208. ;; (kill-buffer buffer)
  209. ))))
  210. (when (and error-file (file-exists-p error-file))
  211. (if (< 0 (nth 7 (file-attributes error-file)))
  212. (with-current-buffer (get-buffer-create error-buffer)
  213. (let ((pos-from-end (- (point-max) (point))))
  214. (or (bobp)
  215. (insert "\f\n"))
  216. ;; Do no formatting while reading error file,
  217. ;; because that can run a shell command, and we
  218. ;; don't want that to cause an infinite recursion.
  219. (format-insert-file error-file nil)
  220. ;; Put point after the inserted errors.
  221. (goto-char (- (point-max) pos-from-end)))
  222. (and display-error-buffer
  223. (display-buffer (current-buffer)))))
  224. (delete-file error-file))
  225. exit-status))
  226. (provide 'ob-eval)
  227. ;; arch-tag: 5328b17f-957d-42d9-94da-a2952682d04d
  228. ;;; ob-comint.el ends here