* 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 via email to