浏览代码

playing with org-babel-script and comint buffers/functions

Eric Schulte 16 年之前
父节点
当前提交
c175d3ce0d
共有 2 个文件被更改,包括 79 次插入43 次删除
  1. 66 42
      lisp/org-babel-script.el
  2. 13 1
      org-babel.org

+ 66 - 42
lisp/org-babel-script.el

@@ -30,7 +30,10 @@
 
 ;;; Code:
 (require 'org-babel)
+(require 'inf-ruby)
+(require 'python)
 
+;; org-babel introduction and formalities
 (defun org-babel-script-add-interpreter (var cmds)
   (set-default var cmds)
   (mapc (lambda (cmd)
@@ -43,22 +46,6 @@ automatically generated wrapper for `org-babel-script-execute'.")
               (org-babel-script-execute ,cmd body params))))
         cmds))
 
-(defvar org-babel-script-ruby-wrapper-method
-  "
-def main
-%s
-end
-results = main()
-puts (results.class == String) ? results : results.inspect
-")
-
-(defvar org-babel-script-python-wrapper-method
-  "
-def main():
-%s
-
-print main()")
-
 (defcustom org-babel-script-interpreters '("ruby" "python")
   "List of interpreters of scripting languages which can be
 executed through org-babel."
@@ -67,33 +54,20 @@ executed through org-babel."
 
 (mapc #'org-babel-add-interpreter org-babel-script-interpreters)
 
-(defun org-babel-script-execute (cmd body params)
-  "Run CMD on BODY obeying any options set with PARAMS."
+;; main execute function used by org-babel
+(defun org-babel-script-execute (interpreter body params)
+  "Pass BODY to INTERPRETER obeying any options set with PARAMS."
   (message (format "executing %s code block..." cmd))
-  (let ((vars (org-babel-ref-variables params)))
-    (save-window-excursion
-      (with-temp-buffer
-        (insert
-         (format
-          (case (intern cmd)
-            ('ruby org-babel-script-ruby-wrapper-method)
-            ('python org-babel-script-python-wrapper-method))
-          (concat
-           (mapconcat ;; define any variables
-            (lambda (pair)
-              (format "\t%s=%s"
-                      (car pair)
-                      (org-babel-script-var-to-ruby/python (cdr pair))))
-            vars "\n")
-           "\n"
-           (let ((body-lines (split-string body "[\n\r]+" t)))
-             (concat
-              (mapconcat (lambda (line) (format "\t%s" line)) (butlast body-lines) "\n")
-              (format "\n\treturn %s\n" (car (last body-lines))))))))
-        ;; (message (buffer-substring (point-min) (point-max))) ;; debug script
-        (shell-command-on-region (point-min) (point-max) cmd nil 'replace)
-        ;; (message (format "shell output = %s" (buffer-string))) ;; debug results
-        (org-babel-script-table-or-results (buffer-string))))))
+  (let* ((vars (org-babel-ref-variables params))
+         (full-body (concat
+                     (mapconcat ;; define any variables
+                      (lambda (pair)
+                        (format "\t%s=%s"
+                                (car pair)
+                                (org-babel-script-var-to-ruby/python (cdr pair))))
+                      vars "\n") body "\n"))) ;; then the source block body
+    (org-babel-script-input-command interpreter full-body)
+    (org-babel-script-table-or-results (org-babel-script-last-value interpreter))))
 
 (defun org-babel-script-var-to-ruby/python (var)
   "Convert an elisp var into a string of ruby or python source
@@ -118,5 +92,55 @@ Emacs-lisp table, otherwise return the results as a string."
                                          "'" "\"" results)))))
      (org-babel-chomp results))))
 
+;; functions for interacting with comint
+(defvar org-babel-script-ruby-buffer nil
+  "variable to hold the current ruby buffer")
+
+(defvar org-babel-script-python-buffer nil
+  "variable to hold the current python buffer")
+
+(defun org-babel-script-interpreter-buffer (interpreter)
+  (intern (format "org-babel-script-%s-buffer" interpreter)))
+
+(defun org-babel-script-initiate-session (interpreter)
+  "If there is not a current inferior-process-buffer for
+INTERPRETER then create one.  Return the buffer in which the
+session has been created."
+  (save-window-excursion
+    (let ((buffer (org-babel-script-interpreter-buffer interpreter)))
+      (unless (and (buffer-live-p buffer) (get-buffer buffer))
+        (case (intern interpreter)
+          ('ruby (funcall #'run-ruby))
+          ('python (funcall #'run-python)))))))
+
+(defun org-babel-script-wait-for-output (interpreter)
+  "Wait until output arrives"
+  (save-window-excursion
+    (save-match-data
+      (set-buffer (org-babel-script-initiate-session interpreter))
+      (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 org-babel-script-input-command (interpreter cmd)
+  "Pass CMD to INTERPRETER"
+  (comint-send-string (get-buffer-process (org-babel-script-initiate-session interpreter)) (concat cmd "\n"))
+  (org-babel-script-wait-for-output interpreter))
+
+(defun org-babel-script-command-to-string (interpreter cmd)
+  (let ((buffer (org-babel-script-interpreter-buffer interpreter)))
+    (org-babel-script-input-command interpreter cmd)
+    (org-babel-script-last-value interpreter)))
+
+(defun org-babel-script-last-value (interpreter)
+  "Return the last value passed to INTERPRETER"
+  (save-excursion
+    (save-match-data
+      (set-buffer (org-babel-script-initiate-session interpreter))
+      (goto-char (process-mark (get-buffer-process (current-buffer))))
+      (forward-line 0)
+      (org-babel-clean-text-properties (buffer-substring comint-last-input-end (- (point) 1))))))
+
 (provide 'org-babel-script)
 ;;; org-babel-script.el ends here

+ 13 - 1
org-babel.org

@@ -341,15 +341,27 @@ this will involve...
 3) functions for retrieving results from the *sessions* buffers which
    can be overridden by each source code
 
-**** R
+**** DONE R
 
 #+srcname: task-R-with-inf-process-buffer
 #+begin_src R 
 a <- 8
 b <- 9
+c <- 10
 a + b
 #+end_src
 
+**** TODO Ruby
+
+#+srcname: ruby-use-last-output
+#+begin_src ruby 
+a = 1
+b = 2
+c = 3
+(a + b) * c
+#+end_src
+
+
 *** TODO implement a *session* header argument
 
 use this header argument to override the default *session* buffer