I added :session header argument for ob-lua.el library. I attached the patch file in email attachment.
I also have written a test for ob-lua :session, but failed. Hope you can
point out where is wrong. Thanks.
Here it is:
#+begin_src emacs-lisp
(ert-deftest test-ob-lua/session-default ()
(should
(equal
(string-join
'("#+BEGIN_SRC lua :session \"*lua*\""
"print(\"hello, world\")<point>"
"#+END_SRC"
""
"#+RESULTS:"
": "
": print(\"hello, world\")"
": "
": hello, world"
": >")
"\n")
(org-test-with-temp-text
(string-join
'("#+BEGIN_SRC lua :session \"*lua*\""
"print(\"hello, world\")<point>"
"#+END_SRC")
"\n")
(let ((org-babel-hash-show-time nil))
(org-babel-execute-src-block))
(buffer-substring-no-properties (point-min) (point-max))))))
#+end_src
But this single testing failed in two ways:
I tested this single test with steps:
1. first load the necessary macros and functions in tests.
=[M-x load-file RET /path/to/org-mode/testing/org-test.el RET]=
3. put point on the ert unit test and press =[C-M-x]= to evaluate the ert test.
4. =[M-x ert RET test-ob-lua/session-default RET]=
Here is the *ert* buffer output:
#+begin_example
Selector: test-ob-lua/session-default
Passed: 0
Failed: 1 (1 unexpected)
Skipped: 0
Total: 1/1
Started at: 2025-12-19 17:46:05+0800
Finished.
Finished at: 2025-12-19 17:46:08+0800
F
F test-ob-lua/session-default
(ert-test-failed
((should
(equal
(string-join
'("#+BEGIN_SRC lua :session \"*lua*\"" "print(\"hello,
world\")<point>" "#+END_SRC" ""
"#+RESULTS:" ": " ": print(\"hello, world\")" ": " ": hello, world"
": >")
"\n")
(org-test-with-temp-text (string-join ... "\n")
(let ... ...) (buffer-substring-no-properties ... ...))))
:form
(equal
"#+BEGIN_SRC lua :session \"*lua*\"\nprint(\"hello,
world\")<point>\n#+END_SRC\n\n#+RESULTS:\n: \n: print(\"hello, world\")\n: \n:
hello, world\n: >"
"#+BEGIN_SRC lua :session \"*lua*\"\nprint(\"hello,
world\")\n#+END_SRC\n\n#+RESULTS[833e9c971f68b6513b25586dae31dec28afd0af3]:\n:
\n: print(\"hello, world\")\n: \n: hello, world\n: >\n")
:value nil :explanation
(arrays-of-different-length 132 168
"#+BEGIN_SRC lua :session
\"*lua*\"\nprint(\"hello, world\")<point>\n#+END_SRC\n\n#+RESULTS:\n: \n:
print(\"hello, world\")\n: \n: hello, world\n: >"
"#+BEGIN_SRC lua :session
\"*lua*\"\nprint(\"hello,
world\")\n#+END_SRC\n\n#+RESULTS[833e9c971f68b6513b25586dae31dec28afd0af3]:\n:
\n: print(\"hello, world\")\n: \n: hello, world\n: >\n"
first-mismatch-at 54)))
#+end_example
The other way is executing command:
$ make BTEST_RE="test-ob-lua/session-default" test-dirty
Here is the output:
#+begin_example
install -m 755 -d /var/folders/ym/f3v5_yk1279g5ls70x3hzblh0000gn/T//tmp-orgtest
TMPDIR=/var/folders/ym/f3v5_yk1279g5ls70x3hzblh0000gn/T//tmp-orgtest emacs -Q
-batch --eval '(setq vc-handled-backends nil org-startup-folded nil
org-element-cache-persistent nil)' --eval '(add-to-list `load-path (concat
default-directory "lisp"))' --eval '(add-to-list `load-path (concat
default-directory "testing"))' -l org-batch-test-init --eval '(setq
org-batch-test t org-babel-load-languages (quote ( (awk . t) (C . t) (fortran
. t) (maxima . t) (lilypond . t) (octave . t) (perl . t) (python . t)
(java . t) (sqlite . t) (eshell . t) (calc . t) (emacs-lisp . t) (shell .
t) (org . t))) org-test-select-re "test-ob-lua/session-default" )' -l
org-loaddefs.el -l testing/org-test.el -l ert -l org -l ox -l ol --eval
'(org-test-run-batch-tests org-test-select-re)'
Finding ID locations (1/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/setupfile3.org
Finding ID locations (2/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/setupfile.org
Finding ID locations (3/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/property-inheritance.org
Finding ID locations (4/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/org-exp.org
Finding ID locations (5/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-sed-test.org
Finding ID locations (6/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-screen-test.org
Finding ID locations (7/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-octave-test.org
Finding ID locations (8/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-maxima-test.org
Finding ID locations (9/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-lilypond-test.org
Finding ID locations (10/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-lilypond-broken.org
Finding ID locations (11/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-header-arg-defaults.org
Finding ID locations (12/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-fortran-test.org
Finding ID locations (13/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-awk-test.org
Finding ID locations (14/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/ob-C-test.org
Finding ID locations (15/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/normal.org
Finding ID locations (16/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/no-heading.org
Finding ID locations (17/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/macro-templates.org
Finding ID locations (18/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/links.org
Finding ID locations (19/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/link-in-heading.org
Finding ID locations (20/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/include2.org
Finding ID locations (21/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/include.org
Finding ID locations (22/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/babel.org
Finding ID locations (23/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/babel-dangerous.org
Finding ID locations (24/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/attachments.org
Finding ID locations (25/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/agenda-search.org
Finding ID locations (26/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/agenda-file2.org
Finding ID locations (27/27 files):
/Users/stardiviner/Code/Emacs/org-mode/testing/examples/agenda-file.org
27 files scanned, 13 files contains IDs, and 54 IDs found.
0 source block added to Library of Babel
selected tests: test-ob-lua/session-default
Running 0 tests (2025-12-19 17:57:37+0800, selector
‘"test-ob-lua/session-default"’)
Ran 0 tests, 0 results as expected, 0 unexpected (2025-12-19 17:57:37+0800,
0.000059 sec)
/Applications/Xcode.app/Contents/Developer/usr/bin/make cleantest
rm -fr /var/folders/ym/f3v5_yk1279g5ls70x3hzblh0000gn/T//tmp-orgtest || { \
find /var/folders/ym/f3v5_yk1279g5ls70x3hzblh0000gn/T//tmp-orgtest
-type d -exec chmod u+w {} + && \
rm -fr /var/folders/ym/f3v5_yk1279g5ls70x3hzblh0000gn/T//tmp-orgtest
; \
}
#+end_example
From be88db97af74c35a6fc12b054831f4f9fcfd1bf7 Mon Sep 17 00:00:00 2001 From: stardiviner <[email protected]> Date: Fri, 19 Dec 2025 17:48:15 +0800 Subject: [PATCH] ob-lua.el: Add :session support for Lua source block * lisp/ob-lua.el (org-babel-execute:lua): Support :session header argument to evaluate source block code in Lua session buffer. (org-babel-prep-session:lua, org-babel-load-session:lua, org-babel-lua-initiate-session): functions to support :session header argument. --- etc/ORG-NEWS | 4 ++ lisp/ob-lua.el | 79 +++++++++++++++++++++++++++++++++---- testing/lisp/test-ob-lua.el | 27 ++++++++++++- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index f4ff44d29..c3f255dc8 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -271,6 +271,10 @@ executable can be configured via =org-ditaa-exec=. SVG output can now be generated; note, however, that this requires a ditaa version of at least 0.11.0. +*** =ob-lua=: support =:session= header argument + +Lua source block now support =:session= header argument like other Babel languages. + ** New and changed options # Changes dealing with changing default values of customizations, diff --git a/lisp/ob-lua.el b/lisp/ob-lua.el index 159229c22..db2ec4be1 100644 --- a/lisp/ob-lua.el +++ b/lisp/ob-lua.el @@ -74,23 +74,47 @@ (defcustom org-babel-lua-multiple-values-separator ", " :package-version '(Org . "9.7") :type 'string) +(defvar org-babel-lua-last-input-start nil) +(defvar org-babel-lua-last-input-end nil) +(defvar org-babel-lua-last-output-start nil) +(defvar org-babel-lua-last-output-end nil) + (defun org-babel-execute:lua (body params) "Execute Lua BODY according to PARAMS. This function is called by `org-babel-execute-src-block'." - (let* ((session (cdr (assq :session params))) + (let* ((session (org-babel-lua-initiate-session (cdr (assq :session params)))) (result-params (cdr (assq :result-params params))) (result-type (cdr (assq :result-type params))) (return-val (when (eq result-type 'value) (cdr (assq :return params)))) (preamble (cdr (assq :preamble params))) (full-body (org-babel-expand-body:generic (concat body (if return-val (format "\nreturn %s" return-val) "")) params (org-babel-variable-assignments:lua params))) - (result (org-babel-lua-evaluate - full-body result-type result-params preamble))) - (when (and session (not (equal session "none"))) - (user-error "Sessions not supported for Lua")) + (result (if session + (with-current-buffer session + ;; reset positions in a new evaluation + (setq-local org-babel-lua-last-input-start (point-max) + org-babel-lua-last-input-end (point-max) + org-babel-lua-last-output-start (point-max) + org-babel-lua-last-output-end (point-max)) + ;; send source block code to session buffer + (dolist (line (split-string full-body "\n")) + (goto-char (point-max)) + (insert line) + (setq-local org-babel-lua-last-input-end (point-max)) + (comint-accumulate)) + (comint-send-input nil t) + ;; get evaluation result output + (sit-for 1.0) + (when (null comint-process-echoes) + (setq-local org-babel-lua-last-output-start (1+ org-babel-lua-last-input-end)) + (setq-local org-babel-lua-last-output-end (- (point-max) 3)) + (buffer-substring-no-properties + org-babel-lua-last-output-start org-babel-lua-last-output-end))) + (org-babel-lua-evaluate + full-body result-type result-params preamble)))) (org-babel-reassemble-table result (org-babel-pick-name (cdr (assq :colname-names params)) @@ -142,8 +166,6 @@ (defun org-babel-lua-table-or-string (results) res) res))) -(defvar org-babel-lua-buffers '((:default . "*Lua*"))) - (defvar org-babel-lua-eoe-indicator "--eoe" "A string to indicate that evaluation has completed.") @@ -249,6 +271,49 @@ (defun org-babel-lua-evaluate raw (org-babel-lua-table-or-string (org-trim raw))))) +;; :session support + +(defvar org-babel-lua-default-buffer "*lua*") + +(defun org-babel-lua-session-live-p (session) + "Non-nil if Lua SESSION exists." + (get-buffer session)) + +(defun org-babel-prep-session:lua (session params) + "Prepare SESSION according to the header arguments in PARAMS." + (let* ((session (org-babel-gnuplot-initiate-session session)) + (var-lines (org-babel-variable-assignments:lua params))) + (org-babel-comint-in-buffer session + (dolist (var-line var-lines) + (insert var-line) + (comint-send-input nil t) + (org-babel-comint-wait-for-output session) + (sit-for .1) + (goto-char (point-max)))) + session)) + +(defun org-babel-load-session:lua (session body params) + "Load BODY into SESSION." + (save-window-excursion + (let ((buffer (org-babel-prep-session:lua session params))) + (with-current-buffer buffer + (goto-char (process-mark (get-buffer-process (current-buffer)))) + ;; (goto-char (point-max)) + (insert (org-babel-chomp body))) + buffer))) + +(defun org-babel-lua-initiate-session (&optional session _params) + "Initiate a Lua session. +If there is not a current inferior-process-buffer in SESSION +then create one. Return the initialized session. The current +`lua-mode' doesn't provide support for multiple sessions." + (org-require-package 'lua-mode) + (unless (string= session "none") + (unless (org-babel-lua-session-live-p session) + (run-lua (or session org-babel-lua-default-buffer) "lua")) + (get-buffer session))) + + (provide 'ob-lua) ;;; ob-lua.el ends here diff --git a/testing/lisp/test-ob-lua.el b/testing/lisp/test-ob-lua.el index 2e19c4a3d..df0b0e66e 100644 --- a/testing/lisp/test-ob-lua.el +++ b/testing/lisp/test-ob-lua.el @@ -417,9 +417,34 @@ (ert-deftest test-ob-lua/no-sessions () '(user-error "Sessions not supported for Lua") (should-error (org-test-with-temp-text "src_lua[:session 1]{}" - (org-babel-execute-src-block)) + (org-babel-execute-src-block)) :type 'user-error)))) +(ert-deftest test-ob-lua/session-default () + (should + (equal + (string-join + '("#+BEGIN_SRC lua :session \"*lua*\"" + "print(\"hello, world\")<point>" + "#+END_SRC" + "" + "#+RESULTS:" + ": " + ": print(\"hello, world\")" + ": " + ": hello, world" + ": >") + "\n") + (org-test-with-temp-text + (string-join + '("#+BEGIN_SRC lua :session \"*lua*\"" + "print(\"hello, world\")<point>" + "#+END_SRC") + "\n") + (let ((org-babel-hash-show-time nil)) + (org-babel-execute-src-block)) + (buffer-substring-no-properties (point-min) (point-max)))))) + (provide 'test-ob-lua) ;;; test-ob-lua.el ends here -- 2.50.1 (Apple Git-155)
-- [ stardiviner ] I try to make every word tell the meaning that I want to express without misunderstanding. Blog: https://stardiviner.github.io/ IRC(libera.chat, freenode): stardiviner, Matrix: stardiviner GPG: F09F650D7D674819892591401B5DF1C95AE89AC3
signature.asc
Description: PGP signature
