ob-lua: Support all types and multiple values in results

* 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.
This commit is contained in:
Rudolf Adamkovič 2024-04-23 18:44:58 +02:00 committed by Ihor Radchenko
parent 9e88e1c822
commit 252cc0be07
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
3 changed files with 104 additions and 33 deletions

View File

@ -642,6 +642,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.
@ -1017,6 +1022,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.

View File

@ -81,6 +81,12 @@ 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
: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 +257,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 +331,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

View File

@ -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