>From 23ef274fd418c876be85871f8da34738ae15ffd5 Mon Sep 17 00:00:00 2001 From: stardiviner Date: Thu, 8 Mar 2018 17:15:58 +0800 Subject: [PATCH] * ob-js.el: support :session for many JS packages. - ob-js.el: support :session for js-comint. - ob-js.el: support :session for Indium Node.js REPL. - ob-js.el: (org-babel-js-initiate-session): merge the `unless' into the `cond' --- etc/ORG-NEWS | 8 ++++ lisp/ob-js.el | 141 ++++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 10687ba83..5cbc10b8b 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -107,6 +107,14 @@ document, use =shrink= value instead, or in addition to align: #+END_EXAMPLE ** New features +*** Add support for ob-js :session with Indium +You can specify :session for js src block with ~*JS REPL*~. +*** Add support for ob-js :session with js-comint +After you launched js-comint REPL. You can specify :session for js +src block with ~*Javascript REPL*~. +*** Add support for ob-js :session with skewer-mode +After you launched skewer-mode REPL. You can specify :session for js +src block with ~*skewer-repl*~. *** Add support for open src block in below window Set option ~org-src-window-setup~ to ~'split-window-below~. *** Add support for links to LaTeX equations in HTML export diff --git a/lisp/ob-js.el b/lisp/ob-js.el index 38c8c39ac..93c08c162 100644 --- a/lisp/ob-js.el +++ b/lisp/ob-js.el @@ -41,6 +41,9 @@ (require 'ob) (declare-function run-mozilla "ext:moz" (arg)) +(declare-function run-js "js-comint" (cmd)) +(declare-function indium-run-node "indium-nodejs" (command)) +(declare-function indium-eval "indium-interaction" (string &optional callback)) (defvar org-babel-default-header-args:js '() "Default header arguments for js code blocks.") @@ -52,7 +55,11 @@ "Name of command used to evaluate js blocks." :group 'org-babel :version "24.1" - :type 'string) + :type '(choice (const "node") + (const "mozrepl") + (const "js-comint") + (const "skewer-mode")) + :safe #'stringp) (defvar org-babel-js-function-wrapper "require('sys').print(require('sys').inspect(function(){\n%s\n}()));" @@ -62,32 +69,40 @@ "Execute a block of Javascript code with org-babel. This function is called by `org-babel-execute-src-block'" (let* ((org-babel-js-cmd (or (cdr (assq :cmd params)) org-babel-js-cmd)) + (session (cdr (assq :session params))) (result-type (cdr (assq :result-type params))) (full-body (org-babel-expand-body:generic - body params (org-babel-variable-assignments:js params))) - (result (if (not (string= (cdr (assq :session params)) "none")) - ;; session evaluation - (let ((session (org-babel-prep-session:js - (cdr (assq :session params)) params))) - (nth 1 - (org-babel-comint-with-output - (session (format "%S" org-babel-js-eoe) t body) - (mapc - (lambda (line) - (insert (org-babel-chomp line)) - (comint-send-input nil t)) - (list body (format "%S" org-babel-js-eoe)))))) - ;; external evaluation - (let ((script-file (org-babel-temp-file "js-script-"))) - (with-temp-file script-file - (insert - ;; return the value or the output - (if (string= result-type "value") - (format org-babel-js-function-wrapper full-body) - full-body))) - (org-babel-eval - (format "%s %s" org-babel-js-cmd - (org-babel-process-file-name script-file)) ""))))) + body params (org-babel-variable-assignments:js params))) + (result (if (not (string= (cdr (assq :session params)) "none")) + ;; session evaluation + (cond + ;; Indium Node + ((string= "*JS REPL*" session) + (require 'indium-repl) + (unless (get-buffer session) + (indium-run-node)) + (indium-eval full-body)) + (t + (let ((session (org-babel-prep-session:js + (cdr (assq :session params)) params))) + (nth 1 + (org-babel-comint-with-output + (session (format "%S" org-babel-js-eoe) t body) + (dolist ((code (list body (format "%S" org-babel-js-eoe)))) + (lambda (code) + (insert (org-babel-chomp code)) + (comint-send-input nil t)))))))) + ;; external evaluation + (let ((script-file (org-babel-temp-file "js-script-"))) + (with-temp-file script-file + (insert + ;; return the value or the output + (if (string= result-type "value") + (format org-babel-js-function-wrapper full-body) + full-body))) + (org-babel-eval + (format "%s %s" org-babel-js-cmd + (org-babel-process-file-name script-file)) ""))))) (org-babel-result-cond (cdr (assq :result-params params)) result (org-babel-js-read result)))) @@ -97,16 +112,16 @@ If RESULTS look like a table, then convert them into an Emacs-lisp table, otherwise return the results as a string." (org-babel-read (if (and (stringp results) - (string-prefix-p "[" results) - (string-suffix-p "]" results)) + (string-prefix-p "[" results) + (string-suffix-p "]" results)) (org-babel-read (concat "'" (replace-regexp-in-string "\\[" "(" (replace-regexp-in-string "\\]" ")" (replace-regexp-in-string ",[[:space:]]" " " - (replace-regexp-in-string - "'" "\"" results)))))) + (replace-regexp-in-string + "'" "\"" results)))))) results))) (defun org-babel-js-var-to-js (var) @@ -120,42 +135,64 @@ specifying a variable of the same value." (defun org-babel-prep-session:js (session params) "Prepare SESSION according to the header arguments specified in PARAMS." (let* ((session (org-babel-js-initiate-session session)) - (var-lines (org-babel-variable-assignments:js params))) + (var-lines (org-babel-variable-assignments:js params))) (when session (org-babel-comint-in-buffer session - (sit-for .5) (goto-char (point-max)) - (mapc (lambda (var) - (insert var) (comint-send-input nil t) - (org-babel-comint-wait-for-output session) - (sit-for .1) (goto-char (point-max))) var-lines))) + (sit-for .5) (goto-char (point-max)) + (mapc (lambda (var) + (insert var) (comint-send-input nil t) + (org-babel-comint-wait-for-output session) + (sit-for .1) (goto-char (point-max))) var-lines))) session)) (defun org-babel-variable-assignments:js (params) "Return list of Javascript statements assigning the block's variables." (mapcar (lambda (pair) (format "var %s=%s;" - (car pair) (org-babel-js-var-to-js (cdr pair)))) + (car pair) (org-babel-js-var-to-js (cdr pair)))) (org-babel--get-vars params))) (defun org-babel-js-initiate-session (&optional session) "If there is not a current inferior-process-buffer in SESSION then create. Return the initialized session." - (unless (string= session "none") - (cond - ((string= "mozrepl" org-babel-js-cmd) - (require 'moz) - (let ((session-buffer (save-window-excursion - (run-mozilla nil) - (rename-buffer session) - (current-buffer)))) - (if (org-babel-comint-buffer-livep session-buffer) - (progn (sit-for .25) session-buffer) - (sit-for .5) - (org-babel-js-initiate-session session)))) - ((string= "node" org-babel-js-cmd ) - (error "Session evaluation with node.js is not supported")) - (t - (error "Sessions are only supported with mozrepl add \":cmd mozrepl\""))))) + (cond + ((string= session "none") + (error "Session evaluation is not supported")) + ((string= "*Javascript REPL*" session) + (require 'js-comint) + (let ((session-buffer "*Javascript REPL*")) + (if (and (org-babel-comint-buffer-livep (get-buffer session-buffer)) + (comint-check-proc session-buffer)) + session-buffer + (call-interactively 'run-js) + (sit-for .5) + session-buffer))) + ((string= "*skewer-repl*" session) ; `skewer-mode' + (require 'skewer-repl) + (let ((session-buffer (get-buffer "*skewer-repl*"))) + (if (and (org-babel-comint-buffer-livep (get-buffer session-buffer)) + (comint-check-proc session-buffer)) + session-buffer + ;; start skewer REPL. + (sit-for .5) + (httpd-start) + (run-skewer) + (sit-for .5) + session-buffer))) + ((string= "mozrepl" org-babel-js-cmd) + (require 'moz) + (let ((session-buffer (save-window-excursion + (run-mozilla nil) + (rename-buffer session) + (current-buffer)))) + (if (org-babel-comint-buffer-livep session-buffer) + (progn (sit-for .25) session-buffer) + (sit-for .5) + (org-babel-js-initiate-session session)))) + ((string= "node" org-babel-js-cmd ) + (error "Session evaluation with node.js is not supported")) + (t + (error "Sessions are only supported with mozrepl add \":cmd mozrepl\"")))) (provide 'ob-js) -- 2.16.2