emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: "Rudolf Adamkovič" <rudolf@adamkovic.org>
To: emacs-orgmode@gnu.org
Cc: "Rudolf Adamkovič" <rudolf@adamkovic.org>
Subject: [PATCH] ob-lua: Support all types and multiple values in results
Date: Tue, 23 Apr 2024 18:44:58 +0200	[thread overview]
Message-ID: <20240423164458.33702-1-rudolf@adamkovic.org> (raw)

* etc/ORG-NEWS
(New and changed options): Describe the new option
'org-babel-lua-multiple-values-separator'.
(New features): Describe the main change, as per the title of this
commit message.
* lisp/ob-lua.el
(org-babel-lua-multiple-values-separator): Enable the user to
customize the string that separates the individual values in
multi-valued returns.
(org-babel-lua-wrapper-method): Support all Lua types and multi-valued
returns.  Further, do not pretty-print tables with one or more
extraneous newline characters.
(org-babel-lua-pp-wrapper-method): Remove in favor of the new, more
general 'org-babel-lua-wrapper-method'.
(org-babel-lua-evaluate-external-process): Adapt for the new
'org-babel-lua-wrapper-method'.
* testing/lisp/test-ob-lua.el
(test-ob-lua/colnames-yes-header-argument-pp):
(test-ob-lua/colnames-nil-header-argument):
(test-ob-lua/colnames-no-header-argument): Stop expecting extraneous
newlines, now that the pretty printer does not output them.
(test-ob-lua/types): Test nil, boolean, number, string, and table
results.
(test-ob-lua/multiple-values): Test multi-valued results.
---
 etc/ORG-NEWS                | 17 +++++++++
 lisp/ob-lua.el              | 73 ++++++++++++++++++++++---------------
 testing/lisp/test-ob-lua.el | 48 ++++++++++++++++++++++--
 3 files changed, 105 insertions(+), 33 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index fc2ff9e00..696f46e53 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -637,6 +637,11 @@ link when storing any type of external link type in an Org file, not
 just =id:= links.
 
 ** New and changed options
+*** ~org-babel-lua-multiple-values-separator~
+
+The string that separates the values of multi-valued results returned
+from Lua code blocks.
+
 *** =.avif= images are now recognized in ~org-html-inline-image-rules~
 
 In =ox-html=, =.avif= image links are now inlined by default.
@@ -1012,6 +1017,18 @@ The option can be customized either by
 2. by setting the file local keyword =LATEX_FOOTNOTE_COMMAND=
 
 ** New features
+*** =ob-lua=: Support all types and multiple values in results
+
+Lua code blocks can now return values of any type and can also return
+multiple values.  Previously, values of certain types were incorrectly
+converted to the empty string =""=, which broke HTML export for inline
+code blocks, and multiple values were incorrectly concatenated, where
+~return 1, 2, 3~ was evaluated as =123=.
+
+Multiple values are comma-separated by default, so that they work well
+with inline code blocks.  To change the string used as the separator,
+customize ~org-babel-lua-multiple-values-separator~.
+
 *** ~org-paste-subtree~ now handles =C-u= and =C-u C-u= prefix arguments specially
 
 With =C-u= prefix argument, force inserting a sibling heading below.
diff --git a/lisp/ob-lua.el b/lisp/ob-lua.el
index b241fccdc..92a1b3344 100644
--- a/lisp/ob-lua.el
+++ b/lisp/ob-lua.el
@@ -81,6 +81,13 @@ This will typically be `lua-mode'."
   :package-version '(Org . "8.3")
   :type 'symbol)
 
+(defcustom org-babel-lua-multiple-values-separator ", "
+  "Separate multiple values with this string."
+  :group 'org-babel
+  :version "30.0"
+  :package-version '(Org . "9.7")
+  :type 'string)
+
 (defun org-babel-execute:lua (body params)
   "Execute Lua BODY according to PARAMS.
 This function is called by `org-babel-execute-src-block'."
@@ -251,41 +258,47 @@ function main()
 %s
 end
 
-fd=io.open(\"%s\", \"w\")
-fd:write( main() )
-fd:close()")
-(defvar org-babel-lua-pp-wrapper-method
-  "
--- table to string
-function t2s(t, indent)
+function dump(it, indent)
    if indent == nil then
-      indent = \"\"
+      indent = ''
    end
-   if type(t) == \"table\" then
-      ts = \"\"
-      for k,v in pairs(t) do
-         if type(v) == \"table\" then
-            ts = ts .. indent .. t2s(k,indent .. \"  \") .. \" = \\n\" ..
-               t2s(v, indent .. \"  \")
-         else
-            ts = ts .. indent .. t2s(k,indent .. \"  \") .. \" = \" ..
-               t2s(v, indent .. \"  \") .. \"\\n\"
+   if type(it) == 'table' and %s then
+      local count = 0
+      for _ in pairs(it) do
+         count = count + 1
+      end
+      local result = ''
+      if #indent ~= 0 then
+         result = result .. '\\n'
+      end
+      for key, value in pairs(it) do
+         result = result
+            .. indent
+            .. dump(key)
+            .. ' = '
+            .. dump(value, indent .. '  ')
+         count = count - 1
+         if count ~= 0 then
+            result = result .. '\\n'
          end
       end
-      return ts
+      return result
    else
-      return tostring(t)
+      return tostring(it)
    end
 end
 
-
-function main()
-%s
+function combine(...)
+  local result = {}
+  for index = 1, select('#', ...) do
+    result[index] = dump(select(index, ...))
+  end
+  return table.concat(result, '%s')
 end
 
-fd=io.open(\"%s\", \"w\")
-fd:write(t2s(main()))
-fd:close()")
+output = io.open('%s', 'w')
+output:write(combine(main()))
+output:close()")
 
 (defun org-babel-lua-evaluate
     (session body &optional result-type result-params preamble)
@@ -319,15 +332,17 @@ PREAMBLE string is appended to BODY."
 		      (concat
 		       preamble (and preamble "\n")
 		       (format
-			(if (member "pp" result-params)
-			    org-babel-lua-pp-wrapper-method
-			  org-babel-lua-wrapper-method)
+                        org-babel-lua-wrapper-method
 			(mapconcat
 			 (lambda (line) (format "\t%s" line))
 			 (split-string
 			  (org-remove-indentation
 			   (org-trim body))
-			  "[\r\n]") "\n")
+			  "[\r\n]")
+                         "\n")
+                        (if (member "pp" result-params)
+                            "true" "false")
+                        org-babel-lua-multiple-values-separator
 			(org-babel-process-file-name tmp-file 'noquote))))
 		     (org-babel-eval-read-file tmp-file))))))
     (org-babel-result-cond result-params
diff --git a/testing/lisp/test-ob-lua.el b/testing/lisp/test-ob-lua.el
index f30e65bb3..0a60c68ca 100644
--- a/testing/lisp/test-ob-lua.el
+++ b/testing/lisp/test-ob-lua.el
@@ -77,9 +77,9 @@ return x[1]
 
 
 (ert-deftest test-ob-lua/colnames-yes-header-argument-pp ()
-  "Test table passing with `colnames' header and pp option."
+  "Test table passing with `colnames' header and `pp' option."
   (should
-   (equal "a = 12\nb = 13\n"
+   (equal "a = 12\nb = 13"
 	  (org-test-with-temp-text
 	      "#+name: eg
 | col | val |
@@ -99,7 +99,7 @@ return x
 (ert-deftest test-ob-lua/colnames-nil-header-argument ()
   "Test table with `colnames' set to `nil'."
   (should
-   (equal "1 = a\n2 = b\n"
+   (equal "1 = a\n2 = b"
 	  (org-test-with-temp-text
 	      "#+name: eg
 | col |
@@ -119,7 +119,7 @@ return x
 (ert-deftest test-ob-lua/colnames-no-header-argument ()
   "Test table passing without `colnames'."
   (should
-   (equal "1 = col\n2 = a\n3 = b\n"
+   (equal "1 = col\n2 = a\n3 = b"
 	  (org-test-with-temp-text
 	      "#+name: eg
 | col |
@@ -136,6 +136,46 @@ return x
 	    (org-babel-next-src-block)
 	    (org-babel-execute-src-block)))))
 
+(ert-deftest test-ob-lua/types ()
+  "Test returning different types."
+  (should
+   (equal "nil"
+          (org-test-with-temp-text "src_lua{return nil}"
+            (org-babel-execute-src-block))))
+  (should
+   (equal "true"
+          (org-test-with-temp-text "src_lua{return true}"
+            (org-babel-execute-src-block))))
+  (should
+   (equal "false"
+          (org-test-with-temp-text "src_lua{return false}"
+            (org-babel-execute-src-block))))
+  (should
+   (equal 1
+          (org-test-with-temp-text "src_lua{return 1}"
+            (org-babel-execute-src-block))))
+  (should
+   (equal "hello world"
+          (org-test-with-temp-text "src_lua{return 'hello world'}"
+            (org-babel-execute-src-block))))
+  (should
+   (equal 0
+          (string-match "table: 0x[0-9A-F]+"
+                        (org-test-with-temp-text "src_lua{return {}}"
+                          (org-babel-execute-src-block))))))
+
+(ert-deftest test-ob-lua/multiple-values ()
+  "Test returning multiple values."
+  (should
+   (equal "1, 2, 3"
+          (org-test-with-temp-text "src_lua{return 1, 2, 3}"
+            (org-babel-execute-src-block))))
+  (should
+   (equal "1|2|3"
+          (let ((org-babel-lua-multiple-values-separator "|"))
+            (org-test-with-temp-text "src_lua{return 1, 2, 3}"
+              (org-babel-execute-src-block))))))
+
 (provide 'test-ob-lua)
 
 ;;; test-ob-lua.el ends here
-- 
2.44.0



             reply	other threads:[~2024-04-23 16:45 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-23 16:44 Rudolf Adamkovič [this message]
2024-04-23 17:05 ` [PATCH] ob-lua: Support all types and multiple values in results Rudolf Adamkovič
2024-04-24 14:20   ` Ihor Radchenko
2024-04-24 13:05 ` Ihor Radchenko
2024-04-24 15:01   ` Rudolf Adamkovič
2024-04-26 13:40     ` Ihor Radchenko
2024-04-27 10:57       ` Max Nikulin
2024-04-27 16:33       ` Rudolf Adamkovič
2024-04-28 12:36         ` Ihor Radchenko
2024-04-29 15:57           ` Rudolf Adamkovič
2024-04-29 20:26             ` Rudolf Adamkovič
2024-04-30 10:24               ` Ihor Radchenko
2024-05-02 15:57                 ` Rudolf Adamkovič
2024-05-02 15:58                 ` Rudolf Adamkovič
2024-05-02 16:02                   ` Rudolf Adamkovič
2024-05-01 11:05               ` Max Nikulin
2024-05-02 16:00                 ` Rudolf Adamkovič
2024-05-02 16:41                   ` Ihor Radchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240423164458.33702-1-rudolf@adamkovic.org \
    --to=rudolf@adamkovic.org \
    --cc=emacs-orgmode@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).