emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]
@ 2023-09-01  4:35 Lockywolf
  2023-09-01 18:33 ` Leo Butler
  2023-09-02  7:06 ` [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)] Ihor Radchenko
  0 siblings, 2 replies; 23+ messages in thread
From: Lockywolf @ 2023-09-01  4:35 UTC (permalink / raw)
  To: emacs-orgmode



Remember to cover the basics, that is, what you expected to happen and
what in fact did happen.  You don't know how to make a good report?  See

     https://orgmode.org/manual/Feedback.html#Feedback

Your bug report will be posted to the Org mailing list.
------------------------------------------------------------------------

Dear org developers,

At the moment, ob-maxima has a straightforward way of evaluating
babel blocks,

#+begin_src shell
maxima --very-quiet -r batchload\(\"/tmp/ob-maximaFOOBAR.mac\"\)\$
#+end_src
(line 87 of ob-maxima.el),

I suggest replacing batchload with batch(), and changing line 73 from
"gnuplot_close ()$" to 	"gnuplot_close ()$ \nquit();"

The difference between "batch" and "batchload" is that "batch" can
process :lisp expressions in addition to maxima's own, and it prints
input/output labels. However, it is possible to customise label printing
from maxima's own code, and being able to evaluate :lisp just seems
uncontrovercially good.

It might be that I am missing something, but batch seems a better fit
for Org-Babel.

Emacs  : GNU Emacs 30.0.50 (build 1, x86_64-slackware-linux-gnu, GTK+ Version 3.24.31, cairo version 1.16.0)
 of 2023-07-31
Package: Org mode version 9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)
-- 
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]
  2023-09-01  4:35 [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)] Lockywolf
@ 2023-09-01 18:33 ` Leo Butler
  2023-09-02  7:19   ` Ihor Radchenko
  2023-09-02  7:06 ` [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)] Ihor Radchenko
  1 sibling, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-01 18:33 UTC (permalink / raw)
  To: Lockywolf; +Cc: emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 1350 bytes --]

On Fri, Sep 01 2023, Lockywolf <for_org-bugs_2023-09-01@lockywolf.net> wrote:

> Dear org developers,
>
> At the moment, ob-maxima has a straightforward way of evaluating
> babel blocks,
>
> #+begin_src shell
> maxima --very-quiet -r batchload\(\"/tmp/ob-maximaFOOBAR.mac\"\)\$
> #+end_src
>
> (line 87 of ob-maxima.el),
>
> I suggest replacing batchload with batch(), and changing line 73 from
> "gnuplot_close ()$" to 	"gnuplot_close ()$ \nquit();"
>
> The difference between "batch" and "batchload" is that "batch" can
> process :lisp expressions in addition to maxima's own, and it prints
> input/output labels. However, it is possible to customise label printing
> from maxima's own code, and being able to evaluate :lisp just seems
> uncontrovercially good.
>
> It might be that I am missing something, but batch seems a better fit
> for Org-Babel.

Hello,

I think that your request may be handled by one of two improvements:

1. Implement session support in ob-maxima.el; and
2. Many of the design decisions in the existing ob-maxima code should be
customizable.

I am attaching a patch to address 2. Please try it out, I think that it
will satisfy your requests. Feedback is welcome.

---

This old thread may also be relevant:
https://list.orgmode.org/87o7q5rw62.fsf@t14.reltub.ca/

Best,
Leo



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-On-ltb-ob-max-ob-maxima.el-add-customizations.patch --]
[-- Type: text/x-diff; name="0001-On-ltb-ob-max-ob-maxima.el-add-customizations.patch", Size: 3071 bytes --]

diff --git a/lisp/ob-maxima.el b/lisp/ob-maxima.el
index d1d7c7424..848811628 100644
--- a/lisp/ob-maxima.el
+++ b/lisp/ob-maxima.el
@@ -48,6 +48,33 @@
   :group 'org-babel
   :type 'string)
 
+(defcustom org-babel-maxima-command-arguments
+  "--very-quiet"
+  "Command-line arguments used when calling the Maxima executable. See `org-babel-maxima-batch/load' and `org-babel-execute:maxima'."
+  :group 'org-babel
+  :type 'string)
+
+(defcustom org-babel-maxima-batch/load
+  "batchload"
+  "The Maxima function used to read and execute Maxima code: `batchload' and `batch' are two alternatives, although a user-defined Maxima function may also be used. See `org-babel-execute:maxima'."
+  :options '("batchload" "batch")
+  :group 'org-babel
+  :type 'string)
+
+(defcustom org-babel-maxima-graphic-file-format-string
+  "(set_plot_option ('[gnuplot_term, png]), set_plot_option ('[gnuplot_out_file, %S]))$"
+  "A string with the Maxima code to set the graphic file terminal and name. It must contain `%S' to set the filename. See `org-babel-maxima-expand'."
+  :options '("(set_plot_option ('[gnuplot_term, png]), set_plot_option ('[gnuplot_out_file, %S]))$" "(load(draw), set_draw_option(terminal='pngcairo,file_name=%S))$")
+  :group 'org-babel
+  :type 'string)
+
+
+(defcustom org-babel-maxima-default-epilogue
+  "gnuplot_close ()$"
+  "A string with the final Maxima code executed. See `org-babel-maxima-expand'."
+  :group 'org-babel
+  :type 'string)
+
 (defun org-babel-maxima-expand (body params)
   "Expand a block of Maxima code according to its header arguments."
   (let ((vars (org-babel--get-vars params))
@@ -60,9 +87,7 @@
 		;; graphic output
 		(let ((graphic-file (ignore-errors (org-babel-graphical-output-file params))))
 		  (if graphic-file
-		      (format
-		       "set_plot_option ([gnuplot_term, png]); set_plot_option ([gnuplot_out_file, %S]);"
-		       graphic-file)
+		      (format org-babel-maxima-graphic-file-format-string graphic-file)
 		    ""))
 		;; variables
 		(mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
@@ -70,7 +95,7 @@
 		body
 		;; Any code from the specified epilogue at the end.
 		epilogue
-		"gnuplot_close ()$")
+		org-babel-maxima-default-epilogue)
 	       "\n")))
 
 (defun org-babel-execute:maxima (body params)
@@ -81,10 +106,11 @@ This function is called by `org-babel-execute-src-block'."
 	(result
 	 (let* ((cmdline (or (cdr (assq :cmdline params)) ""))
 		(in-file (org-babel-temp-file "maxima-" ".max"))
-		(cmd (format "%s --very-quiet -r %s %s"
+		(cmd (format "%s %s -r %s %s"
 			     org-babel-maxima-command
+                             org-babel-maxima-command-arguments
                              (shell-quote-argument
-                              (format "batchload(%S)$" in-file))
+                              (format "%s(%S)$" org-babel-maxima-batch/load in-file))
                              cmdline)))
 	   (with-temp-file in-file (insert (org-babel-maxima-expand body params)))
 	   (message cmd)

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]
  2023-09-01  4:35 [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)] Lockywolf
  2023-09-01 18:33 ` Leo Butler
@ 2023-09-02  7:06 ` Ihor Radchenko
  2023-09-02 18:20   ` Leo Butler
  1 sibling, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-02  7:06 UTC (permalink / raw)
  To: Lockywolf; +Cc: emacs-orgmode

Lockywolf <for_org-bugs_2023-09-01@lockywolf.net> writes:

> At the moment, ob-maxima has a straightforward way of evaluating
> babel blocks,
>
> #+begin_src shell
> maxima --very-quiet -r batchload\(\"/tmp/ob-maximaFOOBAR.mac\"\)\$
> #+end_src
> (line 87 of ob-maxima.el),
>
> I suggest replacing batchload with batch(), and changing line 73 from
> "gnuplot_close ()$" to 	"gnuplot_close ()$ \nquit();"
>
> The difference between "batch" and "batchload" is that "batch" can
> process :lisp expressions in addition to maxima's own, and it prints
> input/output labels. However, it is possible to customise label printing
> from maxima's own code, and being able to evaluate :lisp just seems
> uncontrovercially good.
>
> It might be that I am missing something, but batch seems a better fit
> for Org-Babel.

May you please explain more about :lisp expressions?

Also, what is the benefit/downside of printing input/output labels? Is
there any chance they will be caught into the source block output? If
so, it would be a breaking change.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]
  2023-09-01 18:33 ` Leo Butler
@ 2023-09-02  7:19   ` Ihor Radchenko
  2023-09-02 18:12     ` Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-02  7:19 UTC (permalink / raw)
  To: Leo Butler; +Cc: Lockywolf, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

> I think that your request may be handled by one of two improvements:
>
> 1. Implement session support in ob-maxima.el; and
> 2. Many of the design decisions in the existing ob-maxima code should be
> customizable.

> I am attaching a patch to address 2. Please try it out, I think that it
> will satisfy your requests. Feedback is welcome.

Thanks for the patch!

> +(defcustom org-babel-maxima-command-arguments
> +  "--very-quiet"

> +(defcustom org-babel-maxima-batch/load
> +  "batchload"
> +
> +(defcustom org-babel-maxima-graphic-file-format-string
> +  "(set_plot_option ('[gnuplot_term, png]), set_plot_option ('[gnuplot_out_file, %S]))$"
> +
> +(defcustom org-babel-maxima-default-epilogue
> +  "gnuplot_close ()$"

This might be fine, but may you please explain what would be the purpose
of customizing each of these options?

IMHO, in their current state, if a user mindlessly customizes these
options without knowing how ob-maxima internals work, ob-maxima may
simply be broken. It is also not very clear what would be the benefit
customizing any of the proposed options.

As a general rule, we do not expose internal details that are _required_
for things to work to users. In the above,
`org-babel-maxima-default-epilogue' appears to be paired with
`org-babel-maxima-graphic-file-format-string' and may need to be changed
depending on its value. Also, I am not sure if removing --very-quiet may
not affect :results output.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]
  2023-09-02  7:19   ` Ihor Radchenko
@ 2023-09-02 18:12     ` Leo Butler
  2023-09-05 10:57       ` [MAINTENANCE] On how much we can expose internals into defcustom (was: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]) Ihor Radchenko
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-02 18:12 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Lockywolf, emacs-orgmode@gnu.org

On Sat, Sep 02 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>> I think that your request may be handled by one of two improvements:
>>
>> 1. Implement session support in ob-maxima.el; and
>> 2. Many of the design decisions in the existing ob-maxima code should be
>> customizable.
>
>> I am attaching a patch to address 2. Please try it out, I think that it
>> will satisfy your requests. Feedback is welcome.
>
> Thanks for the patch!
>
>> +(defcustom org-babel-maxima-command-arguments
>> +  "--very-quiet"
>
>> +(defcustom org-babel-maxima-batch/load
>> +  "batchload"
>> +
>> +(defcustom org-babel-maxima-graphic-file-format-string
>> +  "(set_plot_option ('[gnuplot_term, png]), set_plot_option ('[gnuplot_out_file, %S]))$"
>> +
>> +(defcustom org-babel-maxima-default-epilogue
>> +  "gnuplot_close ()$"
>
> This might be fine, but may you please explain what would be the purpose
> of customizing each of these options?

I am not sure of your request: do you want me to elaborate in the
docstrings? Or here?

>
> IMHO, in their current state, if a user mindlessly customizes these
> options without knowing how ob-maxima internals work, ob-maxima may
> simply be broken.

I think there is a fine line between being too rigid but working within
a limited scope (as ob-maxima is now), or providing enough customizable
options to let users do what they want. I would prefer the latter,
if the defaults provide a working configuration.

Note that I do attempt to suggest other working options in the defcustom
definitions.

> It is also not very clear what would be the benefit
> customizing any of the proposed options.

I had planned to update the worg documentation with some examples, but
here is one that answers the OP's original question:

>> +(defcustom org-babel-maxima-command-arguments
>> +  "--very-quiet"

This is the current setting.

It can be useful to include the build information that Maxima provides
on start-up, which would mean setting this to "".

>
>> +(defcustom org-babel-maxima-batch/load
>> +  "batchload"

This is the current setting.

Another option suggested is "batch". That is what the OP originally
requested.

>> +
>> +(defcustom org-babel-maxima-graphic-file-format-string
>> +  "(set_plot_option ('[gnuplot_term, png]), set_plot_option ('[gnuplot_out_file, %S]))$"

This is the current setting.

An alternative is to use the `draw' package, which is a suggested
option. Draw, in my opinion, is a much better package for plotting.

>> +
>> +(defcustom org-babel-maxima-default-epilogue
>> +  "gnuplot_close ()$"

This is the current setting.

The current setting is not needed in recent versions of Maxima (since
roughly 2010, I believe), except possibly on Windows. And, it is only
needed if `:results graphics file' is included as a src header.

On the other hand, the OP had requested adding

"quit() $"

to this setting. I don't think that is needed, but Maxima is built with
more than 6 different common-lisp implementations so there can be lots
of variability in how common tasks are performed...

>
> As a general rule, we do not expose internal details that are _required_
> for things to work to users.

I understand this principle, but, why not provide enough options for
users to configure a package to do what they want? Yes, that may mean
they break the package--but only temporarily, because returning to the
default options will return the package to a working state.

> In the above, `org-babel-maxima-default-epilogue' appears to be paired
> with `org-babel-maxima-graphic-file-format-string' and may need to be
> changed depending on its value.

No, they are not closely connected. Both plot and draw use gnuplot as
the graphing backend (although draw might be able to use vtk, that
capability has not been maintained...).

> Also, I am not sure if removing --very-quiet may
> not affect :results output.

Yes, it will. But that is what the OP is asking for.

----

I think that the original intention of ob-maxima was to provide a simple
`calculator'-like interface to Maxima. In many cases, though, one wants
to show a sequence of calculations that lead to the final answer. That
is why being able to configure some of these hard-coded settings is
desirable: to be able to modify how the input and output are presented.

Best regards,
Leo

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]
  2023-09-02  7:06 ` [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)] Ihor Radchenko
@ 2023-09-02 18:20   ` Leo Butler
  2023-09-03  5:25     ` Vladimir Nikishkin
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-02 18:20 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Lockywolf, emacs-orgmode@gnu.org

On Sat, Sep 02 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Lockywolf <for_org-bugs_2023-09-01@lockywolf.net> writes:
>
>> At the moment, ob-maxima has a straightforward way of evaluating
>> babel blocks,
>>
>> #+begin_src shell
>> maxima --very-quiet -r batchload\(\"/tmp/ob-maximaFOOBAR.mac\"\)\$
>> #+end_src
>> (line 87 of ob-maxima.el),
>>
>> I suggest replacing batchload with batch(), and changing line 73 from
>> "gnuplot_close ()$" to 	"gnuplot_close ()$ \nquit();"
>>
>> The difference between "batch" and "batchload" is that "batch" can
>> process :lisp expressions in addition to maxima's own, and it prints
>> input/output labels. However, it is possible to customise label printing
>> from maxima's own code, and being able to evaluate :lisp just seems
>> uncontrovercially good.
>>
>> It might be that I am missing something, but batch seems a better fit
>> for Org-Babel.
>
> May you please explain more about :lisp expressions?

This special syntax is not necessary. A recent change introduced the
function `eval_string_lisp' that removes the need for it. I.e. one can
batchload a file and execute lisp code inside a call to eval_string_lisp.

>
> Also, what is the benefit/downside of printing input/output labels? Is
> there any chance they will be caught into the source block output? If
> so, it would be a breaking change.

Yes, his requests are breaking changes. That is why I suggested opening
up the internals a bit so that one can alter the behavior while
maintaining the same default.

Leo


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]
  2023-09-02 18:20   ` Leo Butler
@ 2023-09-03  5:25     ` Vladimir Nikishkin
  0 siblings, 0 replies; 23+ messages in thread
From: Vladimir Nikishkin @ 2023-09-03  5:25 UTC (permalink / raw)
  To: Leo Butler; +Cc: Ihor Radchenko, emacs-orgmode@gnu.org


Leo Butler <Leo.Butler@umanitoba.ca> writes:

> On Sat, Sep 02 2023, Ihor Radchenko <yantar92@posteo.net> wrote:
>
>> Lockywolf <for_org-bugs_2023-09-01@lockywolf.net> writes:
>>
>>> At the moment, ob-maxima has a straightforward way of evaluating
>>> babel blocks,
>>>
>>> #+begin_src shell
>>> maxima --very-quiet -r batchload\(\"/tmp/ob-maximaFOOBAR.mac\"\)\$
>>> #+end_src
>>> (line 87 of ob-maxima.el),
>>>
>>> I suggest replacing batchload with batch(), and changing line 73 from
>>> "gnuplot_close ()$" to 	"gnuplot_close ()$ \nquit();"
>>>
>>> The difference between "batch" and "batchload" is that "batch" can
>>> process :lisp expressions in addition to maxima's own, and it prints
>>> input/output labels. However, it is possible to customise label printing
>>> from maxima's own code, and being able to evaluate :lisp just seems
>>> uncontrovercially good.
>>>
>>> It might be that I am missing something, but batch seems a better fit
>>> for Org-Babel.
>>
>> May you please explain more about :lisp expressions?
>
> This special syntax is not necessary. A recent change introduced the
> function `eval_string_lisp' that removes the need for it. I.e. one can
> batchload a file and execute lisp code inside a call to eval_string_lisp.
>

Well, necessary or not, but it existed for many years, and continues to
be a valid part of maxima so far. It is surprising for new users to not
see it working when quite a lot of howtos use it. (Especially the famous
pattern-matching howto from Michael Talon.)

Also, I would be hesitant to say that it "removes the need for it",
because a "valid expression" is not the same thing as a "string". In
particular, error processing should be different.

>>
>> Also, what is the benefit/downside of printing input/output labels? Is
>> there any chance they will be caught into the source block output? If
>> so, it would be a breaking change.
>
> Yes, his requests are breaking changes. That is why I suggested opening
> up the internals a bit so that one can alter the behavior while
> maintaining the same default.
>
> Leo

Well, this change is "breaking", in the sense that it would make the
output of ob-maxima be more consistent with what, say, imaxima is doing.
However, I thing that there is a way to make it non-breaking, by
prepending some maxima code which would make adjust maxima using "batch"
to have the same output as "batchload". Something like
src_maxima{programmode: true; nolabels: true;} should turn off labels
if that is desired.

But I would agree with Leo Butler that customisation is the best
solution here. Both "full batch", and "pseudo-interactive" modes are
useful.

-- 
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [MAINTENANCE] On how much we can expose internals into defcustom (was: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)])
  2023-09-02 18:12     ` Leo Butler
@ 2023-09-05 10:57       ` Ihor Radchenko
  2023-09-06 19:39         ` [MAINTENANCE] On how much we can expose internals into defcustom Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-05 10:57 UTC (permalink / raw)
  To: Leo Butler, Bastien; +Cc: Lockywolf, emacs-orgmode@gnu.org

CCing Bastien, as he might want to intervene.

Leo Butler <Leo.Butler@umanitoba.ca> writes:

   >> +(defcustom org-babel-maxima-command-arguments
   >> +  "--very-quiet"
   >
   >> +(defcustom org-babel-maxima-batch/load
   >> +  "batchload"
   >> +
   >> +(defcustom org-babel-maxima-graphic-file-format-string
   >> +  "(set_plot_option ('[gnuplot_term, png]), set_plot_option ('[gnuplot_out_file, %S]))$"
   >> +
   >> +(defcustom org-babel-maxima-default-epilogue
   >> +  "gnuplot_close ()$"

>> IMHO, in their current state, if a user mindlessly customizes these
>> options without knowing how ob-maxima internals work, ob-maxima may
>> simply be broken.
>
> I think there is a fine line between being too rigid but working within
> a limited scope (as ob-maxima is now), or providing enough customizable
> options to let users do what they want. I would prefer the latter,
> if the defaults provide a working configuration.
>
> Note that I do attempt to suggest other working options in the defcustom
> definitions.

>> As a general rule, we do not expose internal details that are _required_
>> for things to work to users.
>
> I understand this principle, but, why not provide enough options for
> users to configure a package to do what they want? Yes, that may mean
> they break the package--but only temporarily, because returning to the
> default options will return the package to a working state.

That's a bit more tricky.
Imagine, for example, that we commit

+(defcustom org-babel-maxima-command-arguments
+  "--very-quiet"

and some users will later customize the default value to

"--very-quite --my-personal-switch-I-want"

Then, in future, due to changes in Org or maxima, we might need to
change "--very-quite" to something else in order to keep ob-maxima in
working condition: "--very-quite=yes --another-useful-flag-we-absolutely-need-in-org"

In order to make such a switch, we will have to force all the users
change their customization - something we do not want to annoy users
with.

So, leaving essential settings customizeable is not necessarily a good idea.

This is not necessarily a rigid rule though - we do leave, for example,
`org-latex-engraved-preamble' exposed to the users in ways that can
break LaTeX src block export. The basic condition is that changing
something should be practically useful for users, which is why I asked
you to elaborate on why each of the new customizations need to be
introduced.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [MAINTENANCE] On how much we can expose internals into defcustom
  2023-09-05 10:57       ` [MAINTENANCE] On how much we can expose internals into defcustom (was: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]) Ihor Radchenko
@ 2023-09-06 19:39         ` Leo Butler
  2023-09-07 11:35           ` Ihor Radchenko
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-06 19:39 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

On Tue, Sep 05 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> CCing Bastien, as he might want to intervene.
>
> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>    >> +(defcustom org-babel-maxima-command-arguments
>    >> +  "--very-quiet"
>    >
>    >> +(defcustom org-babel-maxima-batch/load
>    >> +  "batchload"
>    >> +
>    >> +(defcustom org-babel-maxima-graphic-file-format-string
>    >> +  "(set_plot_option ('[gnuplot_term, png]), set_plot_option ('[gnuplot_out_file, %S]))$"
>    >> +
>    >> +(defcustom org-babel-maxima-default-epilogue
>    >> +  "gnuplot_close ()$"
>
>>> IMHO, in their current state, if a user mindlessly customizes these
>>> options without knowing how ob-maxima internals work, ob-maxima may
>>> simply be broken.
>>
>> I think there is a fine line between being too rigid but working within
>> a limited scope (as ob-maxima is now), or providing enough customizable
>> options to let users do what they want. I would prefer the latter,
>> if the defaults provide a working configuration.
>>
>> Note that I do attempt to suggest other working options in the defcustom
>> definitions.
>
>>> As a general rule, we do not expose internal details that are _required_
>>> for things to work to users.
>>
>> I understand this principle, but, why not provide enough options for
>> users to configure a package to do what they want? Yes, that may mean
>> they break the package--but only temporarily, because returning to the
>> default options will return the package to a working state.
>
> That's a bit more tricky.
> Imagine, for example, that we commit
>
> +(defcustom org-babel-maxima-command-arguments
> +  "--very-quiet"
>
> and some users will later customize the default value to
>
> "--very-quite --my-personal-switch-I-want"
>
> Then, in future, due to changes in Org or maxima, we might need to
> change "--very-quite" to something else in order to keep ob-maxima in
> working condition: "--very-quite=yes --another-useful-flag-we-absolutely-need-in-org"
>
> In order to make such a switch, we will have to force all the users
> change their customization - something we do not want to annoy users
> with.

I understand your general argument, but I doubt it is relevant to this
particular case.

In this specific case, that command-line option `--very-quiet' was
introduced in 17 years ago
(https://sourceforge.net/p/maxima/mailman/message/11796355/). The syntax
has not changed since it was introduced.

>
> So, leaving essential settings customizeable is not necessarily a good idea.

I understand your hesitation about full-blown customization using
`defcustom'. However, I would still like to have more dials to turn.

Perhaps we could add header arguments to get the desired customization?
E.g.

- :batch :: Control how the Maxima source is evaluated by Maxima.
  1. Default. If nil or no, then use batchload with the --very-quiet
     command-line flag.
  2. If t or yes, then use batch with the --quiet command-line flag;

- :plot-engine :: Set the plotting package.
  1. Default. If nil or no, the use `plot';
  2. If `draw', then use `draw'.

- Similarly, we could do something like ob-R.el does, and construct the
  graphics instructions using some additional header arguments and
  grovelling the terminal from the filename (see
  org-babel-R-construct-graphics-device-call).

My sense is that this would be more in keeping with how other ob-*.el
packages do things.

Best,
Leo

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [MAINTENANCE] On how much we can expose internals into defcustom
  2023-09-06 19:39         ` [MAINTENANCE] On how much we can expose internals into defcustom Leo Butler
@ 2023-09-07 11:35           ` Ihor Radchenko
  2023-09-12 21:09             ` [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom) Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-07 11:35 UTC (permalink / raw)
  To: Leo Butler; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

>> ...
>> In order to make such a switch, we will have to force all the users
>> change their customization - something we do not want to annoy users
>> with.
>
> I understand your general argument, but I doubt it is relevant to this
> particular case.
>
> In this specific case, that command-line option `--very-quiet' was
> introduced in 17 years ago
> (https://sourceforge.net/p/maxima/mailman/message/11796355/). The syntax
> has not changed since it was introduced.

`org-babel-execute:maxima' relies on certain output that maxima
produces. Removing --very-quiet will make the assumptions in the code no
longer valid. Worse - it might happen that in the absence of --very-quiet
`org-babel-execute:maxima' (or its future code) will work _almost_
correctly, with problems going unnoticed to the user.

If we want to support use-case when --very-quiet is absent, we need to
explicitly change `org-babel-execute:maxima' to account for it,
maintaining this support forever.

Either way, it will be an extra maintenance burden, which must be
justified.

The baseline is - we cannot put the burden of wrongly changing
customization onto the user. Because the user may or may not notice
them problem, especially when it is subtle and requires good knowledge
of the Elisp code in ob-maxima.

Of course, the above statement is not 100% strict. If you describe cases
when customization is necessary for certain valid use cases, we may
still put in such dangerous customization with all the appropriate
warnings in the docstring. But it should be justified.

>> So, leaving essential settings customizeable is not necessarily a good idea.
>
> I understand your hesitation about full-blown customization using
> `defcustom'. However, I would still like to have more dials to turn.
>
> Perhaps we could add header arguments to get the desired customization?

Header arguments are generally better, because they provide more
fine-grained control compared to global customization.

> E.g.
>
> - :batch :: Control how the Maxima source is evaluated by Maxima.
>   1. Default. If nil or no, then use batchload with the --very-quiet
>      command-line flag.
>   2. If t or yes, then use batch with the --quiet command-line flag;

Is there a place where I can see the differences between batch and batchload?

> - :plot-engine :: Set the plotting package.
>   1. Default. If nil or no, the use `plot';
>   2. If `draw', then use `draw'.

Sounds reasonable.

> - Similarly, we could do something like ob-R.el does, and construct the
>   graphics instructions using some additional header arguments and
>   grovelling the terminal from the filename (see
>   org-babel-R-construct-graphics-device-call).
>
> My sense is that this would be more in keeping with how other ob-*.el
> packages do things.

Yes.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-07 11:35           ` Ihor Radchenko
@ 2023-09-12 21:09             ` Leo Butler
  2023-09-15  9:41               ` Ihor Radchenko
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-12 21:09 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 3012 bytes --]

On Thu, Sep 07 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> `org-babel-execute:maxima' relies on certain output that maxima
> produces. Removing --very-quiet will make the assumptions in the code no
> longer valid. Worse - it might happen that in the absence of --very-quiet
> `org-babel-execute:maxima' (or its future code) will work _almost_
> correctly, with problems going unnoticed to the user.
>
> If we want to support use-case when --very-quiet is absent, we need to
> explicitly change `org-babel-execute:maxima' to account for it,
> maintaining this support forever.
>
> Either way, it will be an extra maintenance burden, which must be
> justified.
>
> The baseline is - we cannot put the burden of wrongly changing
> customization onto the user. Because the user may or may not notice
> them problem, especially when it is subtle and requires good knowledge
> of the Elisp code in ob-maxima.
>
> Of course, the above statement is not 100% strict. If you describe cases
> when customization is necessary for certain valid use cases, we may
> still put in such dangerous customization with all the appropriate
> warnings in the docstring. But it should be justified.
>
>>> So, leaving essential settings customizeable is not necessarily a good idea.
>>
>> I understand your hesitation about full-blown customization using
>> `defcustom'. However, I would still like to have more dials to turn.
>>
>> Perhaps we could add header arguments to get the desired customization?
>
> Header arguments are generally better, because they provide more
> fine-grained control compared to global customization.
>
>> E.g.
>>
>> - :batch :: Control how the Maxima source is evaluated by Maxima.
>>   1. Default. If nil or no, then use batchload with the --very-quiet
>>      command-line flag.
>>   2. If t or yes, then use batch with the --quiet command-line flag;
>
> Is there a place where I can see the differences between batch and batchload?
>
>> - :plot-engine :: Set the plotting package.
>>   1. Default. If nil or no, the use `plot';
>>   2. If `draw', then use `draw'.
>
> Sounds reasonable.
>
>> - Similarly, we could do something like ob-R.el does, and construct the
>>   graphics instructions using some additional header arguments and
>>   grovelling the terminal from the filename (see
>>   org-babel-R-construct-graphics-device-call).
>>
>> My sense is that this would be more in keeping with how other ob-*.el
>> packages do things.
>
> Yes.

Attached is a patch that tries to address some of Ihor's concerns. I
have added two header arguments for maxima src blocks:

- :graphics-pkg lets the user choose the graphics package to use;

- :batch lets the user choose which source-code loader Maxima will use.

I have also moved two defaults, that were embedded in the code, to
`defvar' forms.

I have added tests in test-ob-maxima.el and in ob-maxima-test.org to
demonstrate the use of these header arguments.

Leo



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-On-ltb-ob-max-ob-maxima.el-add-headers-and-custs.patch --]
[-- Type: text/x-diff; name="0001-On-ltb-ob-max-ob-maxima.el-add-headers-and-custs.patch", Size: 8185 bytes --]

diff --git a/lisp/ob-maxima.el b/lisp/ob-maxima.el
index d1d7c7424..ab166bfd4 100644
--- a/lisp/ob-maxima.el
+++ b/lisp/ob-maxima.el
@@ -48,29 +48,44 @@
   :group 'org-babel
   :type 'string)
 
+(defvar org-babel-maxima-command-arguments
+  "--very-quiet"
+  "A string containing the command-line arguments used when calling the Maxima executable. See `org-babel-maxima-command', `org-babel-maxima-batch/load' and `org-babel-execute:maxima'.")
+
+(defvar org-babel-maxima-graphic-package-options
+  '((plot . "(set_plot_option ('[gnuplot_term, %s]), set_plot_option ('[gnuplot_out_file, %S]))$")
+    (draw . "(load(draw), set_draw_defaults(terminal='%s,file_name=%S))$"))
+  "An alist, each element of the form (PACKAGE-NAME . FORMAT-STRING). The format string contains the Maxima code to set the graphic file terminal and name. It must contain `%s' to set the terminal and `%S' to set the filename. The default package is `plot'. See `org-babel-maxima-expand'.")
+
+(defvar org-babel-maxima-default-epilogue
+  "gnuplot_close ()$"
+  "A string with the final Maxima code executed. See `org-babel-maxima-expand'.")
+
 (defun org-babel-maxima-expand (body params)
   "Expand a block of Maxima code according to its header arguments."
-  (let ((vars (org-babel--get-vars params))
-	(epilogue (cdr (assq :epilogue params)))
-	(prologue (cdr (assq :prologue params))))
+  (let* ((vars (org-babel--get-vars params))
+         (graphic-file (ignore-errors (org-babel-graphical-output-file params)))
+	 (epilogue (cdr (assq :epilogue params)))
+	 (prologue (cdr (assq :prologue params))))
     (mapconcat 'identity
-	       (list
-		;; Any code from the specified prologue at the start.
-		prologue
-		;; graphic output
-		(let ((graphic-file (ignore-errors (org-babel-graphical-output-file params))))
-		  (if graphic-file
-		      (format
-		       "set_plot_option ([gnuplot_term, png]); set_plot_option ([gnuplot_out_file, %S]);"
-		       graphic-file)
-		    ""))
-		;; variables
-		(mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
-		;; body
-		body
-		;; Any code from the specified epilogue at the end.
-		epilogue
-		"gnuplot_close ()$")
+               (delq nil
+	             (list
+		      ;; Any code from the specified prologue at the start.
+		      prologue
+		      ;; graphic output
+		      (if graphic-file
+                          (let ((graphics-pkg (intern (or (cdr (assq :graphics-pkg params)) "plot")))
+                                (graphic-format-string (cdr (assq graphics-pkg org-babel-maxima-graphic-package-options)))
+                                (graphic-terminal (file-name-extension graphic-file))
+                                (graphic-file (if (eq graphics-pkg 'plot) graphic-file (file-name-sans-extension graphic-file))))
+                            (format graphic-format-string graphic-terminal graphic-file)))
+		      ;; variables
+		      (mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
+		      ;; body
+		      body
+		      ;; Any code from the specified epilogue at the end.
+		      epilogue
+		      (if graphic-file org-babel-maxima-default-epilogue)))
 	       "\n")))
 
 (defun org-babel-execute:maxima (body params)
@@ -80,11 +95,18 @@ This function is called by `org-babel-execute-src-block'."
   (let ((result-params (split-string (or (cdr (assq :results params)) "")))
 	(result
 	 (let* ((cmdline (or (cdr (assq :cmdline params)) ""))
+                (batch/load (or (cdr (assq :batch params)) "batchload"))
+                (cmdline (if (or (equal cmdline "") (equal batch/load "batchload"))
+                             ;; legacy behaviour:
+                             ;; ensure that --very-quiet is on command-line by default
+                             (concat cmdline " " org-babel-maxima-command-arguments)
+                           ;; if using an alternate loader, :cmdline overwrites default
+                           cmdline))
 		(in-file (org-babel-temp-file "maxima-" ".max"))
-		(cmd (format "%s --very-quiet -r %s %s"
+ 		(cmd (format "%s -r %s %s"
 			     org-babel-maxima-command
                              (shell-quote-argument
-                              (format "batchload(%S)$" in-file))
+                              (format "(linenum:0, %s(%S))$" batch/load in-file))
                              cmdline)))
 	   (with-temp-file in-file (insert (org-babel-maxima-expand body params)))
 	   (message cmd)
@@ -97,6 +119,8 @@ This function is called by `org-babel-execute-src-block'."
                               (unless (or (string-match "batch" line)
                                           (string-match "^rat: replaced .*$" line)
                                           (string-match "^;;; Loading #P" line)
+                                          (string-match "^read and interpret" line)
+                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)
                                           (= 0 (length line)))
                                 line))
                             (split-string raw "[\r\n]"))) "\n")))))
diff --git a/testing/examples/ob-maxima-test.org b/testing/examples/ob-maxima-test.org
index b83114a4f..2b88a65a5 100644
--- a/testing/examples/ob-maxima-test.org
+++ b/testing/examples/ob-maxima-test.org
@@ -23,6 +23,13 @@ plot2d(sin(a*x), [x, 0, 2*%pi])$
 #+begin_src maxima  :results graphics :file maxima-test-3d.png
 plot3d (2^(-u^2 + v^2), [u, -3, 3], [v, -2, 2])$
 #+end_src
+
+** Use the ~draw~ package
+This test exercises the ~:graphics-pkg~ header argument.
+#+begin_src maxima  :var a=0.5 :results graphics file :file maxima-test-cos.png :graphics-pkg draw
+draw2d(explicit(cos(a*x), x, -%pi, %pi))$
+#+end_src
+
 * Output to a file
 Output to a file
 #+begin_src maxima :file maxima-test-ouput.out
@@ -89,3 +96,18 @@ tex(ratsimp(diff(%e^(a*x), x)));
 #+BEGIN_LaTeX
 $$a\,e^{a\,x}$$
 #+END_LaTeX
+
+* Batch
+Exercise the ~:batch~ header argument. These tests are also defined in ~testing/lisp/test-ob-maxima.el~. The test name is name of the ~ert~ test.
+
+#+name: ob-maxima/batch+verbatim
+#+begin_src maxima :exports both :results verbatim :batch batch
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+quiet
+#+begin_src maxima :exports both :results verbatim :batch batch :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
diff --git a/testing/lisp/test-ob-maxima.el b/testing/lisp/test-ob-maxima.el
index e2433d232..1f6a1737a 100644
--- a/testing/lisp/test-ob-maxima.el
+++ b/testing/lisp/test-ob-maxima.el
@@ -69,6 +69,28 @@
      (equal
       '((1 2 3) (2 3 4) (3 4 5)) (org-babel-execute-src-block)))))
 
+(ert-deftest ob-maxima/batch+verbatim ()
+  "Exercise the `:batch' header argument: use Maxima `batch' command to execute src block. Since `--very-quiet' is set on command-line, the ground input and formatted output are printed (without input/output labels)."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+begin_src maxima :results verbatim :batch batch
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+      (should (equal (org-babel-execute-src-block)
+                     "(assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n                                 gamma(z + 1)")))))
+
+(ert-deftest ob-maxima/batch+verbatim+quiet ()
+  "Exercise the `:batch' header argument: use Maxima `batch' command to execute src block. Since `--quiet' is set by `:cmdline' header, the ground input and formatted output are printed with input/output labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+      (should (equal (org-babel-execute-src-block)
+                     "(%i1) (assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n(%o1)                            gamma(z + 1)")))))
+
 (provide 'test-ob-maxima)
 
 ;;; test-ob-maxima.el ends here

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-12 21:09             ` [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom) Leo Butler
@ 2023-09-15  9:41               ` Ihor Radchenko
  2023-09-15 15:13                 ` Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-15  9:41 UTC (permalink / raw)
  To: Leo Butler; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

> Attached is a patch that tries to address some of Ihor's concerns. I
> have added two header arguments for maxima src blocks:

Thanks!

> - :graphics-pkg lets the user choose the graphics package to use;
>
> - :batch lets the user choose which source-code loader Maxima will use.

We need to document the new header arguments in ORG-NEWS and in
https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-maxima.html

Also, non-standard arguments should be defined in `org-babel-header-args:maxima'.

> I have also moved two defaults, that were embedded in the code, to
> `defvar' forms.

This is fine, although I would prefer to keep these variables private for
now.

> +(defvar org-babel-maxima-command-arguments
> +  "--very-quiet"
> +  "A string containing the command-line arguments used when calling the Maxima executable. See `org-babel-maxima-command', `org-babel-maxima-batch/load' and `org-babel-execute:maxima'.")

Here and in the other docstrings, please use a single short sentence in
the first line. Also, please use double space between sentences and fill
the docstring text to standard fill-column. See
https://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html

> +(defvar org-babel-maxima-graphic-package-options
> +  '((plot . "(set_plot_option ('[gnuplot_term, %s]), set_plot_option ('[gnuplot_out_file, %S]))$")
> +    (draw . "(load(draw), set_draw_defaults(terminal='%s,file_name=%S))$"))
> +  "An alist, each element of the form (PACKAGE-NAME . FORMAT-STRING). The format string contains the Maxima code to set the graphic file terminal and name. It must contain `%s' to set the terminal and `%S' to set the filename. The default package is `plot'. See `org-babel-maxima-expand'.")

According to the docstring, it appears that the order of %s and %S do
not matter, which is probably not the case.

> +		      ;; graphic output
> +		      (if graphic-file
> +                          (let ((graphics-pkg (intern (or (cdr (assq :graphics-pkg params)) "plot")))
> +                                (graphic-format-string (cdr (assq graphics-pkg org-babel-maxima-graphic-package-options)))
> +                                (graphic-terminal (file-name-extension graphic-file))
> +                                (graphic-file (if (eq graphics-pkg 'plot) graphic-file (file-name-sans-extension graphic-file))))
> +                            (format graphic-format-string graphic-terminal graphic-file)))

What will happen if :graphics-pkg value is not expected? What about
unsupported graphics file extensions? And is it always the that terminal
name is the same as file extension (I am thinking about Gnuplot's
pngcairo terminal)?

> -                              (format "batchload(%S)$" in-file))
> +                              (format "(linenum:0, %s(%S))$" batch/load in-file))

May you clarify the purpose of "linenum"?

>                                (unless (or (string-match "batch" line)
>                                            (string-match "^rat: replaced .*$" line)
>                                            (string-match "^;;; Loading #P" line)
> +                                          (string-match "^read and interpret" line)
> +                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)

May you explain why you added these two conditions?

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-15  9:41               ` Ihor Radchenko
@ 2023-09-15 15:13                 ` Leo Butler
  2023-09-16  9:04                   ` Ihor Radchenko
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-15 15:13 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

On Fri, Sep 15 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>> Attached is a patch that tries to address some of Ihor's concerns. I
>> have added two header arguments for maxima src blocks:
>
> Thanks!
>
>> - :graphics-pkg lets the user choose the graphics package to use;
>>
>> - :batch lets the user choose which source-code loader Maxima will use.
>
> We need to document the new header arguments in ORG-NEWS and in
> https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-maxima.html

Thanks for your feedback.

Yes, I will do the documentation once the patch has attained a
nearer-to-finished state.

>
> Also, non-standard arguments should be defined in `org-babel-header-args:maxima'.
>

Ok. I see that some packages (e.g. ob-gnuplot.el) use a `defvar' form,
while others (e.g. ob-R.el) use a `defconst' form. Is there a preference?

>> I have also moved two defaults, that were embedded in the code, to
>> `defvar' forms.
>
> This is fine, although I would prefer to keep these variables private for
> now.

My understanding is that a special variable defined via `defvar' is one
that is intended to be "private", i.e. users should not change it unless
they really know what they are doing. Is that accurate?

Do you mean the names should be something like

org-babel-maxima--command-arguments

?

>
>> +(defvar org-babel-maxima-command-arguments
>> +  "--very-quiet"
>> + "A string containing the command-line arguments used when calling
>> the Maxima executable. See `org-babel-maxima-command',
>> `org-babel-maxima-batch/load' and `org-babel-execute:maxima'.")
>
> Here and in the other docstrings, please use a single short sentence in
> the first line. Also, please use double space between sentences and fill
> the docstring text to standard fill-column. See
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html

Yes.

>
>> +(defvar org-babel-maxima-graphic-package-options
>> +  '((plot . "(set_plot_option ('[gnuplot_term, %s]), set_plot_option ('[gnuplot_out_file, %S]))$")
>> +    (draw . "(load(draw), set_draw_defaults(terminal='%s,file_name=%S))$"))
>> + "An alist, each element of the form (PACKAGE-NAME
>> . FORMAT-STRING). The format string contains the Maxima code to set
>> the graphic file terminal and name. It must contain `%s' to set the
>> terminal and `%S' to set the filename. The default package is
>> `plot'. See `org-babel-maxima-expand'.")
>
> According to the docstring, it appears that the order of %s and %S do
> not matter, which is probably not the case.

Correct.

>
>> +		      ;; graphic output
>> +		      (if graphic-file
>> +                          (let ((graphics-pkg (intern (or (cdr (assq :graphics-pkg params)) "plot")))
>> +                                (graphic-format-string (cdr (assq graphics-pkg org-babel-maxima-graphic-package-options)))
>> +                                (graphic-terminal (file-name-extension graphic-file))
>> +                                (graphic-file (if (eq graphics-pkg 'plot) graphic-file (file-name-sans-extension graphic-file))))
>> +                            (format graphic-format-string graphic-terminal graphic-file)))
>
> What will happen if :graphics-pkg value is not expected? What about
> unsupported graphics file extensions? 

I need to add a fail-safe when setting `graphic-format-string'

> And is it always the that terminal name is the same as file extension
> (I am thinking about Gnuplot's pngcairo terminal)?

I see your point.

At the moment, the code works for the following terminals:

png, jpg, gif, eps, svg, pdf

To support a range of terminal options including, I would need to add a
:terminal header argument and an alist of graphics packages and their
supported terminals.

>
>> -                              (format "batchload(%S)$" in-file))
>> +                              (format "(linenum:0, %s(%S))$" batch/load in-file))
>
> May you clarify the purpose of "linenum"?

Maxima keeps track of input/output line numbers via the variable
`linenum'. I set the linenum to 0 so that the line numbering of the
input in `in-file' starts at 1 not 2.

This idiom has been used in other Maxima front-ends, such as
`imaxima.el', too (although imaxima now uses the lisp reader, instead).

See https://sourceforge.net/p/maxima/code/ci/76105d9ee231679eccac888a04c98e6ef66df087/


>
>>                                (unless (or (string-match "batch" line)
>>                                            (string-match "^rat: replaced .*$" line)
>>                                            (string-match "^;;; Loading #P" line)
>> +                                          (string-match "^read and interpret" line)
>> +                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)
>
> May you explain why you added these two conditions?

When `batch' starts, it emits the line starting with 'read and
interpret' and including the name of the file being read. This is
extraneous output, and should be filtered out.

The second addition filters out empty input/output lines. Without that
filter, the block

#+name: ob-maxima/batch+verbatim+quiet
#+begin_src maxima :exports both :results verbatim :batch batch :cmdline --quiet
(assume(z>0),
integrate(exp(-t)*t^z, t, 0, inf));
#+end_src

produces an output with a pair of empty lines:

#+RESULTS: ob-maxima/batch+verbatim+quiet
: (%i1) (assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))
: (%o1)                            gamma(z + 1)
: (%i2) 
: (%i4) 


I don't understand why those extra lines appear. It looks to me like a
bug in Maxima, but, because of that, they need to be filtered out.

----

If you recall, this thread started with the OP's request to replace
`batchload' with `batch' to support Maxima's :lisp reader. This patch
provides that support:

#+name: ob-maxima/batch+verbatim+:lisp
#+begin_src maxima :exports both :results verbatim :batch batch :cmdline --quiet
:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
#+end_src

#+RESULTS: ob-maxima/batch+verbatim+:lisp
: ((%GAMMA SIMP) ((MPLUS SIMP) 1 $Z))

(The code may look like line noise, but what it does is it switches the
reader to read lisp code via :lisp, then it uses the lisp reader macro
#$ $# to read and evaluate Maxima code within the lisp reader. That
returns the lisp form of the result. These tricks are not possible using
`batchload'.)

I will prepare a revised patch based on your comments and answers to my
questions in this email.

TIA,
Leo

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-15 15:13                 ` Leo Butler
@ 2023-09-16  9:04                   ` Ihor Radchenko
  2023-09-19 19:25                     ` Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-16  9:04 UTC (permalink / raw)
  To: Leo Butler; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

>> Also, non-standard arguments should be defined in `org-babel-header-args:maxima'.
>>
>
> Ok. I see that some packages (e.g. ob-gnuplot.el) use a `defvar' form,
> while others (e.g. ob-R.el) use a `defconst' form. Is there a preference?

defconst I think. The value is not supposed to be changed.

>>> I have also moved two defaults, that were embedded in the code, to
>>> `defvar' forms.
>>
>> This is fine, although I would prefer to keep these variables private for
>> now.
>
> My understanding is that a special variable defined via `defvar' is one
> that is intended to be "private", i.e. users should not change it unless
> they really know what they are doing. Is that accurate?

Users are indeed not supposed to change defvar unless they know what
they are doing. But it is not considered private - there is a guarantee
that the meaning or type of the variable is not going to change.

> Do you mean the names should be something like
>
> org-babel-maxima--command-arguments
>
> ?

Yes. Having "--" means - if you use this variable, do it at your own
risk; we can re-purpose it or change or rename or do whatever at any
time.

>>> -                              (format "batchload(%S)$" in-file))
>>> +                              (format "(linenum:0, %s(%S))$" batch/load in-file))
>>
>> May you clarify the purpose of "linenum"?
>
> Maxima keeps track of input/output line numbers via the variable
> `linenum'. I set the linenum to 0 so that the line numbering of the
> input in `in-file' starts at 1 not 2.
>
> This idiom has been used in other Maxima front-ends, such as
> `imaxima.el', too (although imaxima now uses the lisp reader, instead).
>
> See https://sourceforge.net/p/maxima/code/ci/76105d9ee231679eccac888a04c98e6ef66df087/

Do I understand correctly that the above will simply affect debug output
when maxima references where a problematic line is located in the source?

>>>                                (unless (or (string-match "batch" line)
>>>                                            (string-match "^rat: replaced .*$" line)
>>>                                            (string-match "^;;; Loading #P" line)
>>> +                                          (string-match "^read and interpret" line)
>>> +                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)
>>
>> May you explain why you added these two conditions?
>
> When `batch' starts, it emits the line starting with 'read and
> interpret' and including the name of the file being read. This is
> extraneous output, and should be filtered out.
>
> The second addition filters out empty input/output lines. Without that
> filter, the block
>
> #+name: ob-maxima/batch+verbatim+quiet
> #+begin_src maxima :exports both :results verbatim :batch batch :cmdline --quiet
> (assume(z>0),
> integrate(exp(-t)*t^z, t, 0, inf));
> #+end_src
>
> produces an output with a pair of empty lines:
>
> #+RESULTS: ob-maxima/batch+verbatim+quiet
> : (%i1) (assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))
> : (%o1)                            gamma(z + 1)
> : (%i2) 
> : (%i4) 
>
>
> I don't understand why those extra lines appear. It looks to me like a
> bug in Maxima, but, because of that, they need to be filtered out.

May empty lines be intentional in some maxima code?

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-16  9:04                   ` Ihor Radchenko
@ 2023-09-19 19:25                     ` Leo Butler
  2023-09-20  9:17                       ` Ihor Radchenko
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-19 19:25 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 2133 bytes --]

On Sat, Sep 16 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>>> Also, non-standard arguments should be defined in `org-babel-header-args:maxima'.
>>>
>>
>> Ok. I see that some packages (e.g. ob-gnuplot.el) use a `defvar' form,
>> while others (e.g. ob-R.el) use a `defconst' form. Is there a preference?
>
> defconst I think. The value is not supposed to be changed.

Done.

>
>>>> I have also moved two defaults, that were embedded in the code, to
>>>> `defvar' forms.
>>>
>>> This is fine, although I would prefer to keep these variables private for
>>> now.

Done.

>>>> -                              (format "batchload(%S)$" in-file))
>>>> +                              (format "(linenum:0, %s(%S))$" batch/load in-file))
>>>
>>> May you clarify the purpose of "linenum"?
> Do I understand correctly that the above will simply affect debug output
> when maxima references where a problematic line is located in the source?

No, it affects how output labels are printed. With this value, the
"first" line in the source block receives the line number 1; without it,
it would get 2.

>
>>>>                                (unless (or (string-match "batch" line)
>>>>                                            (string-match "^rat: replaced .*$" line)
>>>>                                            (string-match "^;;; Loading #P" line)
>>>> +                                          (string-match "^read and interpret" line)
>>>> +                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)
>>>
>>> May you explain why you added these two conditions?
>>

<snip>

>
> May empty lines be intentional in some maxima code?

A blank line is simply skipped by the maxima reader; an empty input line
is a syntax error.

However, "empty" output may appear, so I have modified that filter. I
have included a number of test cases in the testsuite to make sure that
such corner cases are being handled correctly.

Please see the attached patch.

Thank you for your time and patience.

Leo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lisp-ob-maxima.el-enable-use-of-batch-loader-and-dra.patch --]
[-- Type: text/x-diff; name="0001-lisp-ob-maxima.el-enable-use-of-batch-loader-and-dra.patch", Size: 14562 bytes --]

From d2934b38a28a8593554af69622be5b11bc13406d Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Tue, 19 Sep 2023 13:36:06 -0500
Subject: [PATCH] * lisp/ob-maxima.el: enable use of `batch' loader and `draw'

* (org-babel-header-args:maxima): document the two
new header arguments, specific to ob-maxima.
* (org-babel-maxima--command-arguments-default):
move the default command-line argument into this variable, from
`org-babel-maxima:execute'.
* (org-babel-maxima--graphic-package-options): an alist of Maxima
graphics packages and the Maxima code to set up that package.
* (org-babel-maxima--default-epilogue): an alist of the clean-up code
that is run at end of a `graphical-output' or `non-graphical-output'
source block.
* (org-babel-maxima-expand): prepare the source block for
execution.
* (org-babel-execute:maxima): use the :batch header argument and
`org-babel-maxima--command-arguments-default' to execute the source
block.  Add a couple extra regexps to filter the output of a batch-ed
source block.

* testing/examples/ob-maxima-test.org: add a draw test

Provide an example of the `:graphics-pkg' header argument with the
`draw' package.

* testing/lisp/test-ob-maxima.el: add batch-related tests

* testing/lisp/test-ob-maxima.el: introduce six new tests.  Each test
exercises the :batch header argument.  The response to unusual inputs
is tested (empty strings, strings with just whitespace, input with the
`:lisp' reader, and two syntax-related errors).
* testing/examples/ob-maxima-test.org: include examples of the
batch-related tests from testing/lisp/test-ob-maxima.el.
---
 lisp/ob-maxima.el                   |  88 +++++++++++++++++------
 testing/examples/ob-maxima-test.org |  54 ++++++++++++++
 testing/lisp/test-ob-maxima.el      | 107 ++++++++++++++++++++++++++++
 3 files changed, 227 insertions(+), 22 deletions(-)

diff --git a/lisp/ob-maxima.el b/lisp/ob-maxima.el
index d1d7c7424..3814049ca 100644
--- a/lisp/ob-maxima.el
+++ b/lisp/ob-maxima.el
@@ -37,6 +37,11 @@
 
 (require 'ob)
 
+(defconst org-babel-header-args:maxima
+  '((batch               . :any)
+    (graphics-pkg        . :any))
+  "Maxima-specific header arguments.")
+
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("maxima" . "max"))
 
@@ -48,29 +53,59 @@
   :group 'org-babel
   :type 'string)
 
+(defvar org-babel-maxima--command-arguments-default
+  "--very-quiet"
+  "Command-line arguments sent to Maxima by default.  If the
+`:batch' header argument is set to `batchload' or unset, then the
+`:cmdline' header argument is appended to this default;
+otherwise, if the `:cmdline' argument is set, it over-rides this
+default.  See `org-babel-maxima-command' and
+`org-babel-execute:maxima'.")
+
+(defvar org-babel-maxima--graphic-package-options
+  '((plot . "(set_plot_option ('[gnuplot_term, %s]), set_plot_option ('[gnuplot_out_file, %S]))$")
+    (draw . "(load(draw), set_draw_defaults(terminal='%s,file_name=%S))$"))
+  "An alist of graphics packages and Maxima code.  Each element is a
+cons (PACKAGE-NAME . FORMAT-STRING).  FORMAT-STRING contains
+Maxima code to configure the graphics package; it must contain
+`%s' to set the terminal and `%S' to set the filename, in that
+order.  The default graphics package is `plot'; `draw' is also
+supported.  See `org-babel-maxima-expand'.")
+
+(defvar org-babel-maxima--default-epilogue
+  '((graphical-output . "gnuplot_close ()$")
+    (non-graphical-output . ""))
+  "The final Maxima code executed in a source block.  An alist with
+the epilogue for graphical and non-graphical output.  See
+`org-babel-maxima-expand'.")
+
 (defun org-babel-maxima-expand (body params)
   "Expand a block of Maxima code according to its header arguments."
-  (let ((vars (org-babel--get-vars params))
-	(epilogue (cdr (assq :epilogue params)))
-	(prologue (cdr (assq :prologue params))))
+  (let* ((vars (org-babel--get-vars params))
+         (graphic-file (ignore-errors (org-babel-graphical-output-file params)))
+	 (epilogue (cdr (assq :epilogue params)))
+	 (prologue (cdr (assq :prologue params))))
     (mapconcat 'identity
-	       (list
-		;; Any code from the specified prologue at the start.
-		prologue
-		;; graphic output
-		(let ((graphic-file (ignore-errors (org-babel-graphical-output-file params))))
-		  (if graphic-file
-		      (format
-		       "set_plot_option ([gnuplot_term, png]); set_plot_option ([gnuplot_out_file, %S]);"
-		       graphic-file)
-		    ""))
-		;; variables
-		(mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
-		;; body
-		body
-		;; Any code from the specified epilogue at the end.
-		epilogue
-		"gnuplot_close ()$")
+               (delq nil
+	             (list
+		      ;; Any code from the specified prologue at the start.
+		      prologue
+		      ;; graphic output
+		      (if graphic-file
+                          (let* ((graphics-pkg (intern (or (cdr (assq :graphics-pkg params)) "plot")))
+                                 (graphic-format-string (cdr (assq graphics-pkg org-babel-maxima--graphic-package-options)))
+                                 (graphic-terminal (file-name-extension graphic-file))
+                                 (graphic-file (if (eq graphics-pkg 'plot) graphic-file (file-name-sans-extension graphic-file))))
+                            (format graphic-format-string graphic-terminal graphic-file)))
+		      ;; variables
+		      (mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
+		      ;; body
+		      body
+		      ;; Any code from the specified epilogue at the end.
+		      epilogue
+		      (if graphic-file
+                          (cdr (assq :graphical-output org-babel-maxima--default-epilogue))
+                        (cdr (assq :non-graphical-output org-babel-maxima--default-epilogue)))))
 	       "\n")))
 
 (defun org-babel-execute:maxima (body params)
@@ -80,11 +115,18 @@ This function is called by `org-babel-execute-src-block'."
   (let ((result-params (split-string (or (cdr (assq :results params)) "")))
 	(result
 	 (let* ((cmdline (or (cdr (assq :cmdline params)) ""))
+                (batch/load (or (cdr (assq :batch params)) "batchload"))
+                (cmdline (if (or (equal cmdline "") (equal batch/load "batchload"))
+                             ;; legacy behaviour:
+                             ;; ensure that --very-quiet is on command-line by default
+                             (concat cmdline " " org-babel-maxima--command-arguments-default)
+                           ;; if using an alternate loader, :cmdline overwrites default
+                           cmdline))
 		(in-file (org-babel-temp-file "maxima-" ".max"))
-		(cmd (format "%s --very-quiet -r %s %s"
+ 		(cmd (format "%s -r %s %s"
 			     org-babel-maxima-command
                              (shell-quote-argument
-                              (format "batchload(%S)$" in-file))
+                              (format "(linenum:0, %s(%S))$" batch/load in-file))
                              cmdline)))
 	   (with-temp-file in-file (insert (org-babel-maxima-expand body params)))
 	   (message cmd)
@@ -97,6 +139,8 @@ This function is called by `org-babel-execute-src-block'."
                               (unless (or (string-match "batch" line)
                                           (string-match "^rat: replaced .*$" line)
                                           (string-match "^;;; Loading #P" line)
+                                          (string-match "^read and interpret" line)
+                                          (string-match "^(%\\([i]-?[0-9]+\\))[ ]$" line)
                                           (= 0 (length line)))
                                 line))
                             (split-string raw "[\r\n]"))) "\n")))))
diff --git a/testing/examples/ob-maxima-test.org b/testing/examples/ob-maxima-test.org
index b83114a4f..c7847d959 100644
--- a/testing/examples/ob-maxima-test.org
+++ b/testing/examples/ob-maxima-test.org
@@ -23,6 +23,14 @@ plot2d(sin(a*x), [x, 0, 2*%pi])$
 #+begin_src maxima  :results graphics :file maxima-test-3d.png
 plot3d (2^(-u^2 + v^2), [u, -3, 3], [v, -2, 2])$
 #+end_src
+
+** Use the ~draw~ package
+This test exercises the ~:graphics-pkg~ header argument.
+#+name: ob-maxima/draw
+#+begin_src maxima  :var a=0.5 :results graphics file :file ./maxima-test-cos.png :graphics-pkg draw
+draw2d(explicit(cos(a*x), x, -%pi, %pi))$
+#+end_src
+
 * Output to a file
 Output to a file
 #+begin_src maxima :file maxima-test-ouput.out
@@ -89,3 +97,49 @@ tex(ratsimp(diff(%e^(a*x), x)));
 #+BEGIN_LaTeX
 $$a\,e^{a\,x}$$
 #+END_LaTeX
+
+* Batch
+:PROPERTIES:
+:header-args:maxima: :exports both :results verbatim :batch batch
+:END:
+
+Exercise the ~:batch~ header argument. These tests are also defined in
+~testing/lisp/test-ob-maxima.el~. The test name is name of the ~ert~
+test.
+
+#+name: ob-maxima/batch+verbatim
+#+begin_src maxima
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+quiet
+#+begin_src maxima :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+:lisp
+#+begin_src maxima :cmdline --quiet
+:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+empty-string
+#+begin_src maxima :cmdline --quiet
+"";
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+whitespace-string
+#+begin_src maxima :cmdline --quiet
+" ";
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+syntax-error
+#+begin_src maxima :cmdline --quiet
+;
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+eof-error
+#+begin_src maxima :cmdline --quiet
+x:
+#+end_src
diff --git a/testing/lisp/test-ob-maxima.el b/testing/lisp/test-ob-maxima.el
index ae9fdc775..211b70e06 100644
--- a/testing/lisp/test-ob-maxima.el
+++ b/testing/lisp/test-ob-maxima.el
@@ -66,6 +66,113 @@
      (equal
       '((1 2 3) (2 3 4) (3 4 5)) (org-babel-execute-src-block)))))
 
+
+;; 6 tests to test the :batch header argument
+(ert-deftest ob-maxima/batch+verbatim ()
+  "Exercise the `:batch' header argument.  Since `--very-quiet'
+is set, the input and output are printed without labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+begin_src maxima :results verbatim :batch batch
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+      (should (equal (org-babel-execute-src-block)
+                     "(assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n                                 gamma(z + 1)")))))
+
+(ert-deftest ob-maxima/batch+verbatim+quiet ()
+  "Exercise the `:batch' header argument.  Since `--quiet' is
+set, the input and output are printed with labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+      (should (equal (org-babel-execute-src-block)
+                     "(%i1) (assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n(%o1)                            gamma(z + 1)")))))
+
+(ert-deftest ob-maxima/batch+verbatim+:lisp ()
+  "Exercise the `:batch' header argument with `:lisp' reader.
+Since `--quiet' is set, the output is printed (as a lisp form)."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+:lisp
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
+#+end_src
+")
+      (should (equal (org-babel-execute-src-block)
+                     "((%GAMMA SIMP) ((MPLUS SIMP) 1 $Z))")))))
+
+(ert-deftest ob-maxima/batch+verbatim+empty-string-vq ()
+  "Exercise the `:batch' header argument.  Send an empty string to
+Maxima.  Since `--very-quiet' is set, the output is printed."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+empty-string-vq
+#+begin_src maxima :results verbatim :batch batch :cmdline --very-quiet
+\"\";
+#+end_src
+")
+      (should (equal (org-babel-execute-src-block) "\"\"\n ")))))
+
+(ert-deftest ob-maxima/batch+verbatim+empty-string ()
+  "Exercise the `:batch' header argument.  Send an empty string to
+Maxima.  Since `--quiet' is set, the input and output are printed
+with labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+empty-string
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+\"\";
+#+end_src
+")
+      (should (equal (org-babel-execute-src-block) "(%i1) \"\"\n(%o1) ")))))
+
+(ert-deftest ob-maxima/batch+verbatim+whitespace-string ()
+  "Exercise the `:batch' header argument.  Send an empty string to
+Maxima.  Since `--quiet' is set, the input and output are printed
+with labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+whitespace-string
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+\" \";
+#+end_src
+")
+      (should (equal (org-babel-execute-src-block)
+                     "(%i1) \" \"\n(%o1)                                   ")))))
+
+(ert-deftest ob-maxima/batch+verbatim+syntax-error ()
+  "Exercise the `:batch' header argument.  Send invalid input to
+Maxima."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+syntax-error
+#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
+;
+#+end_src
+")
+      (should (string-match "incorrect syntax: Premature termination of input at ;\\."
+                            (org-babel-execute-src-block))))))
+
+(ert-deftest ob-maxima/batch+verbatim+eof-error ()
+  "Exercise the `:batch' header argument.  Send invalid input to
+Maxima."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+eof-error
+#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
+x:
+#+end_src
+")
+      (should (string-match "end of file while scanning expression\\."
+                            (org-babel-execute-src-block))))))
+
+
+
 (provide 'test-ob-maxima)
 
 ;;; test-ob-maxima.el ends here
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-19 19:25                     ` Leo Butler
@ 2023-09-20  9:17                       ` Ihor Radchenko
  2023-09-20 15:02                         ` Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-20  9:17 UTC (permalink / raw)
  To: Leo Butler; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

>>>> May you clarify the purpose of "linenum"?
>> Do I understand correctly that the above will simply affect debug output
>> when maxima references where a problematic line is located in the source?
>
> No, it affects how output labels are printed. With this value, the
> "first" line in the source block receives the line number 1; without it,
> it would get 2.

Ok. This should be documented in the commit message and possibly in the
code itself.

>>
>>>>>                                (unless (or (string-match "batch" line)
>>>>>                                            (string-match "^rat: replaced .*$" line)
>>>>>                                            (string-match "^;;; Loading #P" line)
>>>>> +                                          (string-match "^read and interpret" line)
>>>>> +                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)
>>>>
>>>> May you explain why you added these two conditions?
>>>
>
> <snip>
>
>>
>> May empty lines be intentional in some maxima code?
>
> A blank line is simply skipped by the maxima reader; an empty input line
> is a syntax error.
>
> However, "empty" output may appear, so I have modified that filter.

       +                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)

It would be nice to add a comment line explaining what this regexp
matches against.

> * (org-babel-maxima--graphic-package-options): an alist of Maxima
> graphics packages and the Maxima code to set up that package.

This is a bit confusing. I'd say "A new variable storing alist of Maxima ..."

> * (org-babel-maxima--default-epilogue): an alist of the clean-up code
> that is run at end of a `graphical-output' or `non-graphical-output'
> source block.

Same here.
Basically, it should be clear from the commit message when you add new
variables and when you modify existing.

> * (org-babel-maxima-expand): prepare the source block for
> execution.

This is vague. Please explain what is changed in more details.

> * (org-babel-execute:maxima): use the :batch header argument and
> `org-babel-maxima--command-arguments-default' to execute the source
> block.  Add a couple extra regexps to filter the output of a batch-ed
> source block.

This reads better compared to the above.

> +(defconst org-babel-header-args:maxima
> +  '((batch               . :any)

Why :any? Only two values are allowed here.

> +    (graphics-pkg        . :any))

Same. The value is a closed list.

> +(defvar org-babel-maxima--command-arguments-default
> +  "--very-quiet"
> +  "Command-line arguments sent to Maxima by default.  If the

Please keep the first line as a single sentence.
See https://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html

> +(defvar org-babel-maxima--default-epilogue
> +  '((graphical-output . "gnuplot_close ()$")
> +    (non-graphical-output . ""))
> +  "The final Maxima code executed in a source block.  An alist with

Same problem with the first line.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-20  9:17                       ` Ihor Radchenko
@ 2023-09-20 15:02                         ` Leo Butler
  2023-09-21  9:18                           ` Ihor Radchenko
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-20 15:02 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 4421 bytes --]

On Wed, Sep 20 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>>>>> May you clarify the purpose of "linenum"?
>>> Do I understand correctly that the above will simply affect debug output
>>> when maxima references where a problematic line is located in the source?
>>
>> No, it affects how output labels are printed. With this value, the
>> "first" line in the source block receives the line number 1; without it,
>> it would get 2.
>
> Ok. This should be documented in the commit message and possibly in the
> code itself.

I think it makes most sense to put in a source-code comment, explaining
the why. That is what I have done.

>
>>>
>>>>>>                                (unless (or (string-match "batch" line)
>>>>>>                                            (string-match "^rat: replaced .*$" line)
>>>>>>                                            (string-match "^;;; Loading #P" line)
>>>>>> +                                          (string-match "^read and interpret" line)
>>>>>> +                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)
>>>>>
>>>>> May you explain why you added these two conditions?
>>>>
>>
>> <snip>
>>
>>>
>>> May empty lines be intentional in some maxima code?
>>
>> A blank line is simply skipped by the maxima reader; an empty input line
>> is a syntax error.
>>
>> However, "empty" output may appear, so I have modified that filter.
>
>        +                                          (string-match "^(%\\([io]-?[0-9]+\\))[ ]+$" line)
>
> It would be nice to add a comment line explaining what this regexp
> matches against.

Ok. I think it makes the most sense to explain the purpose of each
regexp, new and old, and to make this somewhat extensible.

What I have done is cut out that undocumented filter, put the regexps
into a new variable (`org-babel-maxima--output-filter-regexps'), added
source-code comments to explain what each one does and added a new
function (`org-babel-maxima--output-filter') that replaces the old
filter in `org-babel-execute:maxima'.


>
>> * (org-babel-maxima--graphic-package-options): an alist of Maxima
>> graphics packages and the Maxima code to set up that package.
>
> This is a bit confusing. I'd say "A new variable storing alist of Maxima ..."
>
>> * (org-babel-maxima--default-epilogue): an alist of the clean-up code
>> that is run at end of a `graphical-output' or `non-graphical-output'
>> source block.
>
> Same here.
> Basically, it should be clear from the commit message when you add new
> variables and when you modify existing.

Points taken.

>
>> * (org-babel-maxima-expand): prepare the source block for
>> execution.
>
> This is vague. Please explain what is changed in more details.

Done.

>
>> * (org-babel-execute:maxima): use the :batch header argument and
>> `org-babel-maxima--command-arguments-default' to execute the source
>> block.  Add a couple extra regexps to filter the output of a batch-ed
>> source block.
>
> This reads better compared to the above.
>
>> +(defconst org-babel-header-args:maxima
>> +  '((batch               . :any)
>
> Why :any? Only two values are allowed here.
>
>> +    (graphics-pkg        . :any))
>
> Same. The value is a closed list.

I have made the change requested.

However, beyond the documentation value, I don't see this variable's
values being used.

>
>> +(defvar org-babel-maxima--command-arguments-default
>> +  "--very-quiet"
>> +  "Command-line arguments sent to Maxima by default.  If the
>
> Please keep the first line as a single sentence.
> See https://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html
>
>> +(defvar org-babel-maxima--default-epilogue
>> +  '((graphical-output . "gnuplot_close ()$")
>> +    (non-graphical-output . ""))
>> +  "The final Maxima code executed in a source block.  An alist with
>
> Same problem with the first line.

Fixed. I don't use `apropos', so I didn't see the problem (and I had
failed to absorb everything in §D.6).

Please see the attached, revised patch. It fixes the problems that you
have identified–except for the way that the gnuplot terminal is
determined. I would like to leave that for a subsequent patch, mainly
because this one has become quite large.

Best regards,
Leo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lisp-ob-maxima.el-enable-use-of-batch-loader-and-dra.patch --]
[-- Type: text/x-diff; name="0001-lisp-ob-maxima.el-enable-use-of-batch-loader-and-dra.patch", Size: 17046 bytes --]

From 078e29f13f15305e291b1c0e46e306d633a8b93a Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Tue, 19 Sep 2023 13:36:06 -0500
Subject: [PATCH] * lisp/ob-maxima.el: enable use of `batch' loader and `draw'

* (org-babel-header-args:maxima): Document the two new header
arguments (batch and graphics-pkg) that are specific to ob-maxima.
* (org-babel-maxima--command-arguments-default): A new variable
storing the default command-line argument(s).  This value was
hard-coded in `org-babel-maxima:execute'.
* (org-babel-maxima--graphic-package-options): A new variable that
stores an alist of Maxima graphics packages and the Maxima code to set
up that package.
* (org-babel-maxima--default-epilogue): A new variable that stores an
alist of the clean-up code that is run at end of a `graphical-output'
or `non-graphical-output' source block.
* (org-babel-maxima--output-filter-regexps): A new variable that
stores a list of regexps to identify "bad" output lines to be removed
from Maxima's output.  Source-code comments document each regexp's
purpose.  Two additional regexps have been added: one filters
un-wanted output from `batch' and the other removes empty input lines
that `batch'-ed output may spuriously produce (actual empty input
lines are syntax errors, see the new tests below).
* (org-babel-maxima--output-filter): A new function that takes a
single line of Maxima output.  It returns nil if the line has zero
length or matches a regexp in
`org-babel-maxima--output-filter-regexps'; otherwise, it returns the
line.  This function and regexp replace the hard-coded filter in
`org-babel-execute:maxima'.
* (org-babel-maxima-expand): Prepare the source block for execution,
depending on whether it is producing graphical output or not.  In case
of graphical output, use the `graphics-pkg' header to set the graphics
package and use `org-babel-maxima--graphic-package-options' to set-up
the package.  Grovel the graphics terminal from the output filename.
* (org-babel-execute:maxima): Use the :batch header argument and
`org-babel-maxima--command-arguments-default' to execute the source
block.  Replace the existing, in-line output filter and its regexps
with `org-babel-maxima--output-filter' and
`org-babel-maxima--output-filter-regexps'.

* testing/examples/ob-maxima-test.org: Add test examples.

Include examples of the batch-related tests from
testing/lisp/test-ob-maxima.el.  Provide an example of the
`:graphics-pkg' header argument with the `draw' package.

* testing/lisp/test-ob-maxima.el: Introduce six new, batch-related
test function.  Each test exercises the :batch header argument.  The
response to unusual inputs is tested (empty strings, strings with just
whitespace, input with the `:lisp' reader, and two syntax-related
errors).
---
 lisp/ob-maxima.el                   | 115 +++++++++++++++++++++-------
 testing/examples/ob-maxima-test.org |  54 +++++++++++++
 testing/lisp/test-ob-maxima.el      | 107 ++++++++++++++++++++++++++
 3 files changed, 248 insertions(+), 28 deletions(-)

diff --git a/lisp/ob-maxima.el b/lisp/ob-maxima.el
index d1d7c7424..eac44ff9a 100644
--- a/lisp/ob-maxima.el
+++ b/lisp/ob-maxima.el
@@ -37,6 +37,11 @@
 
 (require 'ob)
 
+(defconst org-babel-header-args:maxima
+  '((batch               . (batchload batch load))
+    (graphics-pkg        . (plot draw)))
+  "Maxima-specific header arguments.")
+
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("maxima" . "max"))
 
@@ -48,31 +53,81 @@
   :group 'org-babel
   :type 'string)
 
+(defvar org-babel-maxima--command-arguments-default
+  "--very-quiet"
+  "Command-line arguments sent to Maxima by default.
+If the `:batch' header argument is set to `batchload' or unset,
+then the `:cmdline' header argument is appended to this default;
+otherwise, if the `:cmdline' argument is set, it over-rides this
+default.  See `org-babel-maxima-command' and
+`org-babel-execute:maxima'.")
+
+(defvar org-babel-maxima--graphic-package-options
+  '((plot . "(set_plot_option ('[gnuplot_term, %s]), set_plot_option ('[gnuplot_out_file, %S]))$")
+    (draw . "(load(draw), set_draw_defaults(terminal='%s,file_name=%S))$"))
+  "An alist of graphics packages and Maxima code.
+Each element is a cons (PACKAGE-NAME . FORMAT-STRING).
+FORMAT-STRING contains Maxima code to configure the graphics
+package; it must contain `%s' to set the terminal and `%S' to set
+the filename, in that order.  The default graphics package is
+`plot'; `draw' is also supported.  See
+`org-babel-maxima-expand'.")
+
+(defvar org-babel-maxima--default-epilogue
+  '((graphical-output . "gnuplot_close ()$")
+    (non-graphical-output . ""))
+  "The final Maxima code executed in a source block.
+An alist with the epilogue for graphical and non-graphical
+output.  See `org-babel-maxima-expand'.")
+
 (defun org-babel-maxima-expand (body params)
   "Expand a block of Maxima code according to its header arguments."
-  (let ((vars (org-babel--get-vars params))
-	(epilogue (cdr (assq :epilogue params)))
-	(prologue (cdr (assq :prologue params))))
+  (let* ((vars (org-babel--get-vars params))
+         (graphic-file (ignore-errors (org-babel-graphical-output-file params)))
+	 (epilogue (cdr (assq :epilogue params)))
+	 (prologue (cdr (assq :prologue params))))
     (mapconcat 'identity
-	       (list
-		;; Any code from the specified prologue at the start.
-		prologue
-		;; graphic output
-		(let ((graphic-file (ignore-errors (org-babel-graphical-output-file params))))
-		  (if graphic-file
-		      (format
-		       "set_plot_option ([gnuplot_term, png]); set_plot_option ([gnuplot_out_file, %S]);"
-		       graphic-file)
-		    ""))
-		;; variables
-		(mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
-		;; body
-		body
-		;; Any code from the specified epilogue at the end.
-		epilogue
-		"gnuplot_close ()$")
+               (delq nil
+	             (list
+		      ;; Any code from the specified prologue at the start.
+		      prologue
+		      ;; graphic output
+		      (if graphic-file
+                          (let* ((graphics-pkg (intern (or (cdr (assq :graphics-pkg params)) "plot")))
+                                 (graphic-format-string (cdr (assq graphics-pkg org-babel-maxima--graphic-package-options)))
+                                 (graphic-terminal (file-name-extension graphic-file))
+                                 (graphic-file (if (eq graphics-pkg 'plot) graphic-file (file-name-sans-extension graphic-file))))
+                            (format graphic-format-string graphic-terminal graphic-file)))
+		      ;; variables
+		      (mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
+		      ;; body
+		      body
+		      ;; Any code from the specified epilogue at the end.
+		      epilogue
+		      (if graphic-file
+                          (cdr (assq :graphical-output org-babel-maxima--default-epilogue))
+                        (cdr (assq :non-graphical-output org-babel-maxima--default-epilogue)))))
 	       "\n")))
 
+(defvar org-babel-maxima--output-filter-regexps
+  '("batch"                     ;; remove the `batch' or `batchload' line
+    "^rat: replaced .*$"        ;; remove notices from `rat'
+    "^;;; Loading #P"           ;; remove notices from the lisp implementation
+    "^read and interpret"       ;; remove notice from `batch'
+    "^(%\\([i]-?[0-9]+\\))[ ]$" ;; remove empty input lines from `batch'-ing
+    )
+  "Regexps to remove extraneous lines from Maxima's output.
+See `org-babel-maxima--output-filter'.")
+
+(defun org-babel-maxima--output-filter (line)
+  "Filter empty or undesired lines from Maxima output.
+Return nil if LINE is zero-length or it matches a regexp in
+`org-babel-maxima--output-filter'; otherwise, return LINE."
+  (unless (or (= 0 (length line))
+              (cl-some #'(lambda(r) (string-match r line))
+                       org-babel-maxima--output-filter-regexps))
+    line))
+
 (defun org-babel-execute:maxima (body params)
   "Execute a block of Maxima entries with org-babel.
 This function is called by `org-babel-execute-src-block'."
@@ -80,11 +135,20 @@ This function is called by `org-babel-execute-src-block'."
   (let ((result-params (split-string (or (cdr (assq :results params)) "")))
 	(result
 	 (let* ((cmdline (or (cdr (assq :cmdline params)) ""))
+                (batch/load (or (cdr (assq :batch params)) "batchload"))
+                (cmdline (if (or (equal cmdline "") (equal batch/load "batchload"))
+                             ;; legacy behaviour:
+                             ;; ensure that --very-quiet is on command-line by default
+                             (concat cmdline " " org-babel-maxima--command-arguments-default)
+                           ;; if using an alternate loader, :cmdline overwrites default
+                           cmdline))
 		(in-file (org-babel-temp-file "maxima-" ".max"))
-		(cmd (format "%s --very-quiet -r %s %s"
+ 		(cmd (format "%s -r %s %s"
 			     org-babel-maxima-command
                              (shell-quote-argument
-                              (format "batchload(%S)$" in-file))
+                              ;; bind linenum to 0 so the first line
+                              ;; of in-file has line number 1
+                              (format "(linenum:0, %s(%S))$" batch/load in-file))
                              cmdline)))
 	   (with-temp-file in-file (insert (org-babel-maxima-expand body params)))
 	   (message cmd)
@@ -93,12 +157,7 @@ This function is called by `org-babel-execute-src-block'."
              (mapconcat
               #'identity
               (delq nil
-                    (mapcar (lambda (line)
-                              (unless (or (string-match "batch" line)
-                                          (string-match "^rat: replaced .*$" line)
-                                          (string-match "^;;; Loading #P" line)
-                                          (= 0 (length line)))
-                                line))
+                    (mapcar #'org-babel-maxima--output-filter
                             (split-string raw "[\r\n]"))) "\n")))))
     (if (ignore-errors (org-babel-graphical-output-file params))
 	nil
diff --git a/testing/examples/ob-maxima-test.org b/testing/examples/ob-maxima-test.org
index b83114a4f..c7847d959 100644
--- a/testing/examples/ob-maxima-test.org
+++ b/testing/examples/ob-maxima-test.org
@@ -23,6 +23,14 @@ plot2d(sin(a*x), [x, 0, 2*%pi])$
 #+begin_src maxima  :results graphics :file maxima-test-3d.png
 plot3d (2^(-u^2 + v^2), [u, -3, 3], [v, -2, 2])$
 #+end_src
+
+** Use the ~draw~ package
+This test exercises the ~:graphics-pkg~ header argument.
+#+name: ob-maxima/draw
+#+begin_src maxima  :var a=0.5 :results graphics file :file ./maxima-test-cos.png :graphics-pkg draw
+draw2d(explicit(cos(a*x), x, -%pi, %pi))$
+#+end_src
+
 * Output to a file
 Output to a file
 #+begin_src maxima :file maxima-test-ouput.out
@@ -89,3 +97,49 @@ tex(ratsimp(diff(%e^(a*x), x)));
 #+BEGIN_LaTeX
 $$a\,e^{a\,x}$$
 #+END_LaTeX
+
+* Batch
+:PROPERTIES:
+:header-args:maxima: :exports both :results verbatim :batch batch
+:END:
+
+Exercise the ~:batch~ header argument. These tests are also defined in
+~testing/lisp/test-ob-maxima.el~. The test name is name of the ~ert~
+test.
+
+#+name: ob-maxima/batch+verbatim
+#+begin_src maxima
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+quiet
+#+begin_src maxima :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+:lisp
+#+begin_src maxima :cmdline --quiet
+:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+empty-string
+#+begin_src maxima :cmdline --quiet
+"";
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+whitespace-string
+#+begin_src maxima :cmdline --quiet
+" ";
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+syntax-error
+#+begin_src maxima :cmdline --quiet
+;
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+eof-error
+#+begin_src maxima :cmdline --quiet
+x:
+#+end_src
diff --git a/testing/lisp/test-ob-maxima.el b/testing/lisp/test-ob-maxima.el
index ae9fdc775..211b70e06 100644
--- a/testing/lisp/test-ob-maxima.el
+++ b/testing/lisp/test-ob-maxima.el
@@ -66,6 +66,113 @@
      (equal
       '((1 2 3) (2 3 4) (3 4 5)) (org-babel-execute-src-block)))))
 
+
+;; 6 tests to test the :batch header argument
+(ert-deftest ob-maxima/batch+verbatim ()
+  "Exercise the `:batch' header argument.  Since `--very-quiet'
+is set, the input and output are printed without labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+begin_src maxima :results verbatim :batch batch
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+      (should (equal (org-babel-execute-src-block)
+                     "(assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n                                 gamma(z + 1)")))))
+
+(ert-deftest ob-maxima/batch+verbatim+quiet ()
+  "Exercise the `:batch' header argument.  Since `--quiet' is
+set, the input and output are printed with labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+      (should (equal (org-babel-execute-src-block)
+                     "(%i1) (assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n(%o1)                            gamma(z + 1)")))))
+
+(ert-deftest ob-maxima/batch+verbatim+:lisp ()
+  "Exercise the `:batch' header argument with `:lisp' reader.
+Since `--quiet' is set, the output is printed (as a lisp form)."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+:lisp
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
+#+end_src
+")
+      (should (equal (org-babel-execute-src-block)
+                     "((%GAMMA SIMP) ((MPLUS SIMP) 1 $Z))")))))
+
+(ert-deftest ob-maxima/batch+verbatim+empty-string-vq ()
+  "Exercise the `:batch' header argument.  Send an empty string to
+Maxima.  Since `--very-quiet' is set, the output is printed."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+empty-string-vq
+#+begin_src maxima :results verbatim :batch batch :cmdline --very-quiet
+\"\";
+#+end_src
+")
+      (should (equal (org-babel-execute-src-block) "\"\"\n ")))))
+
+(ert-deftest ob-maxima/batch+verbatim+empty-string ()
+  "Exercise the `:batch' header argument.  Send an empty string to
+Maxima.  Since `--quiet' is set, the input and output are printed
+with labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+empty-string
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+\"\";
+#+end_src
+")
+      (should (equal (org-babel-execute-src-block) "(%i1) \"\"\n(%o1) ")))))
+
+(ert-deftest ob-maxima/batch+verbatim+whitespace-string ()
+  "Exercise the `:batch' header argument.  Send an empty string to
+Maxima.  Since `--quiet' is set, the input and output are printed
+with labels."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+whitespace-string
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+\" \";
+#+end_src
+")
+      (should (equal (org-babel-execute-src-block)
+                     "(%i1) \" \"\n(%o1)                                   ")))))
+
+(ert-deftest ob-maxima/batch+verbatim+syntax-error ()
+  "Exercise the `:batch' header argument.  Send invalid input to
+Maxima."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+syntax-error
+#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
+;
+#+end_src
+")
+      (should (string-match "incorrect syntax: Premature termination of input at ;\\."
+                            (org-babel-execute-src-block))))))
+
+(ert-deftest ob-maxima/batch+verbatim+eof-error ()
+  "Exercise the `:batch' header argument.  Send invalid input to
+Maxima."
+  (unwind-protect
+    (org-test-with-temp-text
+        (format "#+name: ob-maxima/batch+verbatim+eof-error
+#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
+x:
+#+end_src
+")
+      (should (string-match "end of file while scanning expression\\."
+                            (org-babel-execute-src-block))))))
+
+
+
 (provide 'test-ob-maxima)
 
 ;;; test-ob-maxima.el ends here
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-20 15:02                         ` Leo Butler
@ 2023-09-21  9:18                           ` Ihor Radchenko
  2023-09-21 14:03                             ` Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-21  9:18 UTC (permalink / raw)
  To: Leo Butler; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

>>> +(defconst org-babel-header-args:maxima
>>> +  '((batch               . :any)
>>
>> Why :any? Only two values are allowed here.
>>
>>> +    (graphics-pkg        . :any))
>>
>> Same. The value is a closed list.
>
> I have made the change requested.
>
> However, beyond the documentation value, I don't see this variable's
> values being used.

In completion. See `pcomplete/org-mode/block-option/src'.
Also, in org-lint. See `org-lint-wrong-header-argument'.

> Fixed. I don't use `apropos', so I didn't see the problem (and I had
> failed to absorb everything in §D.6).

M-x checkdoc checks for many of the §D.6 conventions.

> Please see the attached, revised patch. It fixes the problems that you
> have identified–except for the way that the gnuplot terminal is
> determined. I would like to leave that for a subsequent patch, mainly
> because this one has become quite large.

Ok. Thanks!

I have one more comment on the tests:

> +(ert-deftest ob-maxima/batch+verbatim+eof-error ()
> +  "Exercise the `:batch' header argument.  Send invalid input to
> +Maxima."
> +  (unwind-protect

What is the purpose of this `unwind-protect'?
In its current form, it does nothing because no UNWINDFORMS are
provided.

> +    (org-test-with-temp-text
> +        (format "#+name: ob-maxima/batch+verbatim+eof-error
> +#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
> +x:
> +#+end_src
> +")
> +      (should (string-match "end of file while scanning expression\\."
> +                            (org-babel-execute-src-block))))))



-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-21  9:18                           ` Ihor Radchenko
@ 2023-09-21 14:03                             ` Leo Butler
  2023-09-22  9:43                               ` Ihor Radchenko
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-09-21 14:03 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 1850 bytes --]

On Thu, Sep 21 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>>>> +(defconst org-babel-header-args:maxima
>>>> +  '((batch               . :any)
>>>
>>> Why :any? Only two values are allowed here.
>>>
>>>> +    (graphics-pkg        . :any))
>>>
>>> Same. The value is a closed list.
>>
>> I have made the change requested.
>>
>> However, beyond the documentation value, I don't see this variable's
>> values being used.
>
> In completion. See `pcomplete/org-mode/block-option/src'.
> Also, in org-lint. See `org-lint-wrong-header-argument'.

Thanks.

>
>> Fixed. I don't use `apropos', so I didn't see the problem (and I had
>> failed to absorb everything in §D.6).
>
> M-x checkdoc checks for many of the §D.6 conventions.

Yes, I discovered that from the documentation. I must have done
something wrong, because it didn't work for me when I tried it, but
after re-starting emacs it is working.

>
>> Please see the attached, revised patch. It fixes the problems that you
>> have identified–except for the way that the gnuplot terminal is
>> determined. I would like to leave that for a subsequent patch, mainly
>> because this one has become quite large.
>
> Ok. Thanks!
>
> I have one more comment on the tests:
>
>> +(ert-deftest ob-maxima/batch+verbatim+eof-error ()
>> +  "Exercise the `:batch' header argument.  Send invalid input to
>> +Maxima."
>> +  (unwind-protect
>
> What is the purpose of this `unwind-protect'?
> In its current form, it does nothing because no UNWINDFORMS are
> provided.

I copied the forms from tests I had written for ob-octave, without
thinking about why those tests were wrapped in an `unwind-protect'
form. The attached patch removes them, otherwise it is identical to the
previous patch.

Leo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lisp-ob-maxima.el-enable-use-of-batch-loader-and-dra.patch --]
[-- Type: text/x-diff; name="0001-lisp-ob-maxima.el-enable-use-of-batch-loader-and-dra.patch", Size: 16835 bytes --]

From 425ea8ed47af5bccfd9bc37f1e4de4c53cc9b1f1 Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Tue, 19 Sep 2023 13:36:06 -0500
Subject: [PATCH] * lisp/ob-maxima.el: enable use of `batch' loader and `draw'

* (org-babel-header-args:maxima): Document the two new header
arguments (batch and graphics-pkg) that are specific to ob-maxima.
* (org-babel-maxima--command-arguments-default): A new variable
storing the default command-line argument(s).  This value was
hard-coded in `org-babel-maxima:execute'.
* (org-babel-maxima--graphic-package-options): A new variable that
stores an alist of Maxima graphics packages and the Maxima code to set
up that package.
* (org-babel-maxima--default-epilogue): A new variable that stores an
alist of the clean-up code that is run at end of a `graphical-output'
or `non-graphical-output' source block.
* (org-babel-maxima--output-filter-regexps): A new variable that
stores a list of regexps to identify "bad" output lines to be removed
from Maxima's output.  Source-code comments document each regexp's
purpose.  Two additional regexps have been added: one filters
un-wanted output from `batch' and the other removes empty input lines
that `batch'-ed output may spuriously produce (actual empty input
lines are syntax errors, see the new tests below).
* (org-babel-maxima--output-filter): A new function that takes a
single line of Maxima output.  It returns nil if the line has zero
length or matches a regexp in
`org-babel-maxima--output-filter-regexps'; otherwise, it returns the
line.  This function and regexp replace the hard-coded filter in
`org-babel-execute:maxima'.
* (org-babel-maxima-expand): Prepare the source block for execution,
depending on whether it is producing graphical output or not.  In case
of graphical output, use the `graphics-pkg' header to set the graphics
package and use `org-babel-maxima--graphic-package-options' to set-up
the package.  Grovel the graphics terminal from the output filename.
* (org-babel-execute:maxima): Use the :batch header argument and
`org-babel-maxima--command-arguments-default' to execute the source
block.  Replace the existing, in-line output filter and its regexps
with `org-babel-maxima--output-filter' and
`org-babel-maxima--output-filter-regexps'.

* testing/examples/ob-maxima-test.org: Add test examples.

Include examples of the batch-related tests from
testing/lisp/test-ob-maxima.el.  Provide an example of the
`:graphics-pkg' header argument with the `draw' package.

* testing/lisp/test-ob-maxima.el: Introduce six new, batch-related
test functions.  Each test exercises the :batch header argument.  The
response to unusual inputs is tested (empty strings, strings with just
whitespace, input with the `:lisp' reader, and two syntax-related
errors).
---
 lisp/ob-maxima.el                   | 115 +++++++++++++++++++++-------
 testing/examples/ob-maxima-test.org |  54 +++++++++++++
 testing/lisp/test-ob-maxima.el      | 101 ++++++++++++++++++++++++
 3 files changed, 242 insertions(+), 28 deletions(-)

diff --git a/lisp/ob-maxima.el b/lisp/ob-maxima.el
index d1d7c7424..eac44ff9a 100644
--- a/lisp/ob-maxima.el
+++ b/lisp/ob-maxima.el
@@ -37,6 +37,11 @@
 
 (require 'ob)
 
+(defconst org-babel-header-args:maxima
+  '((batch               . (batchload batch load))
+    (graphics-pkg        . (plot draw)))
+  "Maxima-specific header arguments.")
+
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("maxima" . "max"))
 
@@ -48,31 +53,81 @@
   :group 'org-babel
   :type 'string)
 
+(defvar org-babel-maxima--command-arguments-default
+  "--very-quiet"
+  "Command-line arguments sent to Maxima by default.
+If the `:batch' header argument is set to `batchload' or unset,
+then the `:cmdline' header argument is appended to this default;
+otherwise, if the `:cmdline' argument is set, it over-rides this
+default.  See `org-babel-maxima-command' and
+`org-babel-execute:maxima'.")
+
+(defvar org-babel-maxima--graphic-package-options
+  '((plot . "(set_plot_option ('[gnuplot_term, %s]), set_plot_option ('[gnuplot_out_file, %S]))$")
+    (draw . "(load(draw), set_draw_defaults(terminal='%s,file_name=%S))$"))
+  "An alist of graphics packages and Maxima code.
+Each element is a cons (PACKAGE-NAME . FORMAT-STRING).
+FORMAT-STRING contains Maxima code to configure the graphics
+package; it must contain `%s' to set the terminal and `%S' to set
+the filename, in that order.  The default graphics package is
+`plot'; `draw' is also supported.  See
+`org-babel-maxima-expand'.")
+
+(defvar org-babel-maxima--default-epilogue
+  '((graphical-output . "gnuplot_close ()$")
+    (non-graphical-output . ""))
+  "The final Maxima code executed in a source block.
+An alist with the epilogue for graphical and non-graphical
+output.  See `org-babel-maxima-expand'.")
+
 (defun org-babel-maxima-expand (body params)
   "Expand a block of Maxima code according to its header arguments."
-  (let ((vars (org-babel--get-vars params))
-	(epilogue (cdr (assq :epilogue params)))
-	(prologue (cdr (assq :prologue params))))
+  (let* ((vars (org-babel--get-vars params))
+         (graphic-file (ignore-errors (org-babel-graphical-output-file params)))
+	 (epilogue (cdr (assq :epilogue params)))
+	 (prologue (cdr (assq :prologue params))))
     (mapconcat 'identity
-	       (list
-		;; Any code from the specified prologue at the start.
-		prologue
-		;; graphic output
-		(let ((graphic-file (ignore-errors (org-babel-graphical-output-file params))))
-		  (if graphic-file
-		      (format
-		       "set_plot_option ([gnuplot_term, png]); set_plot_option ([gnuplot_out_file, %S]);"
-		       graphic-file)
-		    ""))
-		;; variables
-		(mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
-		;; body
-		body
-		;; Any code from the specified epilogue at the end.
-		epilogue
-		"gnuplot_close ()$")
+               (delq nil
+	             (list
+		      ;; Any code from the specified prologue at the start.
+		      prologue
+		      ;; graphic output
+		      (if graphic-file
+                          (let* ((graphics-pkg (intern (or (cdr (assq :graphics-pkg params)) "plot")))
+                                 (graphic-format-string (cdr (assq graphics-pkg org-babel-maxima--graphic-package-options)))
+                                 (graphic-terminal (file-name-extension graphic-file))
+                                 (graphic-file (if (eq graphics-pkg 'plot) graphic-file (file-name-sans-extension graphic-file))))
+                            (format graphic-format-string graphic-terminal graphic-file)))
+		      ;; variables
+		      (mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
+		      ;; body
+		      body
+		      ;; Any code from the specified epilogue at the end.
+		      epilogue
+		      (if graphic-file
+                          (cdr (assq :graphical-output org-babel-maxima--default-epilogue))
+                        (cdr (assq :non-graphical-output org-babel-maxima--default-epilogue)))))
 	       "\n")))
 
+(defvar org-babel-maxima--output-filter-regexps
+  '("batch"                     ;; remove the `batch' or `batchload' line
+    "^rat: replaced .*$"        ;; remove notices from `rat'
+    "^;;; Loading #P"           ;; remove notices from the lisp implementation
+    "^read and interpret"       ;; remove notice from `batch'
+    "^(%\\([i]-?[0-9]+\\))[ ]$" ;; remove empty input lines from `batch'-ing
+    )
+  "Regexps to remove extraneous lines from Maxima's output.
+See `org-babel-maxima--output-filter'.")
+
+(defun org-babel-maxima--output-filter (line)
+  "Filter empty or undesired lines from Maxima output.
+Return nil if LINE is zero-length or it matches a regexp in
+`org-babel-maxima--output-filter'; otherwise, return LINE."
+  (unless (or (= 0 (length line))
+              (cl-some #'(lambda(r) (string-match r line))
+                       org-babel-maxima--output-filter-regexps))
+    line))
+
 (defun org-babel-execute:maxima (body params)
   "Execute a block of Maxima entries with org-babel.
 This function is called by `org-babel-execute-src-block'."
@@ -80,11 +135,20 @@ This function is called by `org-babel-execute-src-block'."
   (let ((result-params (split-string (or (cdr (assq :results params)) "")))
 	(result
 	 (let* ((cmdline (or (cdr (assq :cmdline params)) ""))
+                (batch/load (or (cdr (assq :batch params)) "batchload"))
+                (cmdline (if (or (equal cmdline "") (equal batch/load "batchload"))
+                             ;; legacy behaviour:
+                             ;; ensure that --very-quiet is on command-line by default
+                             (concat cmdline " " org-babel-maxima--command-arguments-default)
+                           ;; if using an alternate loader, :cmdline overwrites default
+                           cmdline))
 		(in-file (org-babel-temp-file "maxima-" ".max"))
-		(cmd (format "%s --very-quiet -r %s %s"
+ 		(cmd (format "%s -r %s %s"
 			     org-babel-maxima-command
                              (shell-quote-argument
-                              (format "batchload(%S)$" in-file))
+                              ;; bind linenum to 0 so the first line
+                              ;; of in-file has line number 1
+                              (format "(linenum:0, %s(%S))$" batch/load in-file))
                              cmdline)))
 	   (with-temp-file in-file (insert (org-babel-maxima-expand body params)))
 	   (message cmd)
@@ -93,12 +157,7 @@ This function is called by `org-babel-execute-src-block'."
              (mapconcat
               #'identity
               (delq nil
-                    (mapcar (lambda (line)
-                              (unless (or (string-match "batch" line)
-                                          (string-match "^rat: replaced .*$" line)
-                                          (string-match "^;;; Loading #P" line)
-                                          (= 0 (length line)))
-                                line))
+                    (mapcar #'org-babel-maxima--output-filter
                             (split-string raw "[\r\n]"))) "\n")))))
     (if (ignore-errors (org-babel-graphical-output-file params))
 	nil
diff --git a/testing/examples/ob-maxima-test.org b/testing/examples/ob-maxima-test.org
index b83114a4f..c7847d959 100644
--- a/testing/examples/ob-maxima-test.org
+++ b/testing/examples/ob-maxima-test.org
@@ -23,6 +23,14 @@ plot2d(sin(a*x), [x, 0, 2*%pi])$
 #+begin_src maxima  :results graphics :file maxima-test-3d.png
 plot3d (2^(-u^2 + v^2), [u, -3, 3], [v, -2, 2])$
 #+end_src
+
+** Use the ~draw~ package
+This test exercises the ~:graphics-pkg~ header argument.
+#+name: ob-maxima/draw
+#+begin_src maxima  :var a=0.5 :results graphics file :file ./maxima-test-cos.png :graphics-pkg draw
+draw2d(explicit(cos(a*x), x, -%pi, %pi))$
+#+end_src
+
 * Output to a file
 Output to a file
 #+begin_src maxima :file maxima-test-ouput.out
@@ -89,3 +97,49 @@ tex(ratsimp(diff(%e^(a*x), x)));
 #+BEGIN_LaTeX
 $$a\,e^{a\,x}$$
 #+END_LaTeX
+
+* Batch
+:PROPERTIES:
+:header-args:maxima: :exports both :results verbatim :batch batch
+:END:
+
+Exercise the ~:batch~ header argument. These tests are also defined in
+~testing/lisp/test-ob-maxima.el~. The test name is name of the ~ert~
+test.
+
+#+name: ob-maxima/batch+verbatim
+#+begin_src maxima
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+quiet
+#+begin_src maxima :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+:lisp
+#+begin_src maxima :cmdline --quiet
+:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+empty-string
+#+begin_src maxima :cmdline --quiet
+"";
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+whitespace-string
+#+begin_src maxima :cmdline --quiet
+" ";
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+syntax-error
+#+begin_src maxima :cmdline --quiet
+;
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+eof-error
+#+begin_src maxima :cmdline --quiet
+x:
+#+end_src
diff --git a/testing/lisp/test-ob-maxima.el b/testing/lisp/test-ob-maxima.el
index ae9fdc775..653ed4041 100644
--- a/testing/lisp/test-ob-maxima.el
+++ b/testing/lisp/test-ob-maxima.el
@@ -66,6 +66,107 @@
      (equal
       '((1 2 3) (2 3 4) (3 4 5)) (org-babel-execute-src-block)))))
 
+
+;; 6 tests to test the :batch header argument
+(ert-deftest ob-maxima/batch+verbatim ()
+  "Exercise the `:batch' header argument.
+Since `--very-quiet' is set, the input and output are printed
+without labels."
+  (org-test-with-temp-text
+      (format "#+begin_src maxima :results verbatim :batch batch
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+    (should (equal (org-babel-execute-src-block)
+                   "(assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n                                 gamma(z + 1)"))))
+
+(ert-deftest ob-maxima/batch+verbatim+quiet ()
+  "Exercise the `:batch' header argument.
+Since `--quiet' is set, the input and output are printed with
+labels."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+    (should (equal (org-babel-execute-src-block)
+                   "(%i1) (assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n(%o1)                            gamma(z + 1)"))))
+
+(ert-deftest ob-maxima/batch+verbatim+:lisp ()
+  "Exercise the `:batch' header argument with `:lisp' reader.
+Since `--quiet' is set, the output is printed (as a lisp form)."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+:lisp
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
+#+end_src
+")
+    (should (equal (org-babel-execute-src-block)
+                   "((%GAMMA SIMP) ((MPLUS SIMP) 1 $Z))"))))
+
+(ert-deftest ob-maxima/batch+verbatim+empty-string-vq ()
+  "Exercise the `:batch' header argument with empty string input.
+Since `--very-quiet' is set, the output is printed."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+empty-string-vq
+#+begin_src maxima :results verbatim :batch batch :cmdline --very-quiet
+\"\";
+#+end_src
+")
+    (should (equal (org-babel-execute-src-block) "\"\"\n "))))
+
+(ert-deftest ob-maxima/batch+verbatim+empty-string ()
+  "Exercise the `:batch' header argument with empty string input.
+Since `--quiet' is set, the input and output are printed with
+labels."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+empty-string
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+\"\";
+#+end_src
+")
+    (should (equal (org-babel-execute-src-block) "(%i1) \"\"\n(%o1) "))))
+
+(ert-deftest ob-maxima/batch+verbatim+whitespace-string ()
+  "Exercise the `:batch' header argument with whitespace input.
+Since `--quiet' is set, the input and output are printed with
+labels."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+whitespace-string
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+\" \";
+#+end_src
+")
+    (should (equal (org-babel-execute-src-block)
+                   "(%i1) \" \"\n(%o1)                                   "))))
+
+(ert-deftest ob-maxima/batch+verbatim+syntax-error ()
+  "Exercise the `:batch' header argument with syntax error.
+Send empty input line to Maxima."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+syntax-error
+#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
+;
+#+end_src
+")
+    (should (string-match "incorrect syntax: Premature termination of input at ;\\."
+                          (org-babel-execute-src-block)))))
+
+(ert-deftest ob-maxima/batch+verbatim+eof-error ()
+  "Exercise the `:batch' header argument with syntax error.
+Send an incomplete expression to Maxima."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+eof-error
+#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
+x:
+#+end_src
+")
+    (should (string-match "end of file while scanning expression\\."
+                          (org-babel-execute-src-block)))))
+
+
+
 (provide 'test-ob-maxima)
 
 ;;; test-ob-maxima.el ends here
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-21 14:03                             ` Leo Butler
@ 2023-09-22  9:43                               ` Ihor Radchenko
  2023-10-02 16:01                                 ` Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-09-22  9:43 UTC (permalink / raw)
  To: Leo Butler; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

>> What is the purpose of this `unwind-protect'?
>> In its current form, it does nothing because no UNWINDFORMS are
>> provided.
>
> I copied the forms from tests I had written for ob-octave, without
> thinking about why those tests were wrapped in an `unwind-protect'
> form. The attached patch removes them, otherwise it is identical to the
> previous patch.

Thanks! Now, may you also add etc/ORG-NEWS entry and update the WORG docs?

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-09-22  9:43                               ` Ihor Radchenko
@ 2023-10-02 16:01                                 ` Leo Butler
  2023-10-04  8:38                                   ` Ihor Radchenko
  0 siblings, 1 reply; 23+ messages in thread
From: Leo Butler @ 2023-10-02 16:01 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 946 bytes --]

On Fri, Sep 22 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>>> What is the purpose of this `unwind-protect'?
>>> In its current form, it does nothing because no UNWINDFORMS are
>>> provided.
>>
>> I copied the forms from tests I had written for ob-octave, without
>> thinking about why those tests were wrapped in an `unwind-protect'
>> form. The attached patch removes them, otherwise it is identical to the
>> previous patch.
>
> Thanks! Now, may you also add etc/ORG-NEWS entry and update the WORG docs?

Attached is:

- my previous patch, rebased against the latest HEAD and only modified
  to include a patch to etc/ORG-NEWS
- a patch to the worg docs that corrects the urls
- a patch to the worg docs that documents the new header arguments and
  provides examples of usage (two new graphics files are included as
  part of that patch).

Best regards,
Leo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lisp-ob-maxima.el-enable-use-of-batch-loader-and-dra.patch --]
[-- Type: text/x-diff; name="0001-lisp-ob-maxima.el-enable-use-of-batch-loader-and-dra.patch", Size: 17918 bytes --]

From 7288eb547aff1ad50c3782d9db22b1e2792d6634 Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Tue, 19 Sep 2023 13:36:06 -0500
Subject: [PATCH] * lisp/ob-maxima.el: enable use of `batch' loader and `draw'

* (org-babel-header-args:maxima): Document the two new header
arguments (batch and graphics-pkg) that are specific to ob-maxima.
* (org-babel-maxima--command-arguments-default): A new variable
storing the default command-line argument(s).  This value was
hard-coded in `org-babel-maxima:execute'.
* (org-babel-maxima--graphic-package-options): A new variable that
stores an alist of Maxima graphics packages and the Maxima code to set
up that package.
* (org-babel-maxima--default-epilogue): A new variable that stores an
alist of the clean-up code that is run at end of a `graphical-output'
or `non-graphical-output' source block.
* (org-babel-maxima--output-filter-regexps): A new variable that
stores a list of regexps to identify "bad" output lines to be removed
from Maxima's output.  Source-code comments document each regexp's
purpose.  Two additional regexps have been added: one filters
un-wanted output from `batch' and the other removes empty input lines
that `batch'-ed output may spuriously produce (actual empty input
lines are syntax errors, see the new tests below).
* (org-babel-maxima--output-filter): A new function that takes a
single line of Maxima output.  It returns nil if the line has zero
length or matches a regexp in
`org-babel-maxima--output-filter-regexps'; otherwise, it returns the
line.  This function and regexp replace the hard-coded filter in
`org-babel-execute:maxima'.
* (org-babel-maxima-expand): Prepare the source block for execution,
depending on whether it is producing graphical output or not.  In case
of graphical output, use the `graphics-pkg' header to set the graphics
package and use `org-babel-maxima--graphic-package-options' to set-up
the package.  Grovel the graphics terminal from the output filename.
* (org-babel-execute:maxima): Use the :batch header argument and
`org-babel-maxima--command-arguments-default' to execute the source
block.  Replace the existing, in-line output filter and its regexps
with `org-babel-maxima--output-filter' and
`org-babel-maxima--output-filter-regexps'.

* testing/examples/ob-maxima-test.org: Add test examples.

Include examples of the batch-related tests from
testing/lisp/test-ob-maxima.el.  Provide an example of the
`:graphics-pkg' header argument with the `draw' package.

* testing/lisp/test-ob-maxima.el: Introduce six new, batch-related
test functions.  Each test exercises the :batch header argument.  The
response to unusual inputs is tested (empty strings, strings with just
whitespace, input with the `:lisp' reader, and two syntax-related
errors).

link: https://list.orgmode.org/87cyz1ivzw.fsf@t14.reltub.ca/
---
 etc/ORG-NEWS                        |  12 +++
 lisp/ob-maxima.el                   | 115 +++++++++++++++++++++-------
 testing/examples/ob-maxima-test.org |  54 +++++++++++++
 testing/lisp/test-ob-maxima.el      | 101 ++++++++++++++++++++++++
 4 files changed, 254 insertions(+), 28 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 252c5a9f9..16f8a1c30 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -596,6 +596,18 @@ return a matplotlib Figure object to plot. For output results, the
 current figure (as returned by =pyplot.gcf()=) is cleared before
 evaluation, and then plotted afterwards.
 
+*** =ob-maxima.el=: Support for ~batch~ and ~draw~
+
+=ob-maxima= has two new header arguments: ~:batch~ and
+~:graphics-pkg~.
+
+The ~:batch~ header argument can be set to one of Maxima's file
+loaders (~batch~, ~load~ or ~batchload~); the default remains
+~batchload~. The ~:graphics-pkg~ header argument can be set to one of
+Maxima's graphics packages (~draw~ or ~plot~); the default remains
+~plot~.  The graphics terminal is now determined from the file-ending
+of the file-name set in the ~:file~ header argument.
+
 ** New functions and changes in function arguments
 *** =TYPES= argument in ~org-element-lineage~ can now be a symbol
 
diff --git a/lisp/ob-maxima.el b/lisp/ob-maxima.el
index 76682b6cb..ca05149e4 100644
--- a/lisp/ob-maxima.el
+++ b/lisp/ob-maxima.el
@@ -37,6 +37,11 @@
 
 (require 'ob)
 
+(defconst org-babel-header-args:maxima
+  '((batch               . (batchload batch load))
+    (graphics-pkg        . (plot draw)))
+  "Maxima-specific header arguments.")
+
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("maxima" . "max"))
 
@@ -48,31 +53,81 @@
   :group 'org-babel
   :type 'string)
 
+(defvar org-babel-maxima--command-arguments-default
+  "--very-quiet"
+  "Command-line arguments sent to Maxima by default.
+If the `:batch' header argument is set to `batchload' or unset,
+then the `:cmdline' header argument is appended to this default;
+otherwise, if the `:cmdline' argument is set, it over-rides this
+default.  See `org-babel-maxima-command' and
+`org-babel-execute:maxima'.")
+
+(defvar org-babel-maxima--graphic-package-options
+  '((plot . "(set_plot_option ('[gnuplot_term, %s]), set_plot_option ('[gnuplot_out_file, %S]))$")
+    (draw . "(load(draw), set_draw_defaults(terminal='%s,file_name=%S))$"))
+  "An alist of graphics packages and Maxima code.
+Each element is a cons (PACKAGE-NAME . FORMAT-STRING).
+FORMAT-STRING contains Maxima code to configure the graphics
+package; it must contain `%s' to set the terminal and `%S' to set
+the filename, in that order.  The default graphics package is
+`plot'; `draw' is also supported.  See
+`org-babel-maxima-expand'.")
+
+(defvar org-babel-maxima--default-epilogue
+  '((graphical-output . "gnuplot_close ()$")
+    (non-graphical-output . ""))
+  "The final Maxima code executed in a source block.
+An alist with the epilogue for graphical and non-graphical
+output.  See `org-babel-maxima-expand'.")
+
 (defun org-babel-maxima-expand (body params)
   "Expand Maxima BODY according to its header arguments from PARAMS."
-  (let ((vars (org-babel--get-vars params))
-	(epilogue (cdr (assq :epilogue params)))
-	(prologue (cdr (assq :prologue params))))
+  (let* ((vars (org-babel--get-vars params))
+         (graphic-file (ignore-errors (org-babel-graphical-output-file params)))
+	 (epilogue (cdr (assq :epilogue params)))
+	 (prologue (cdr (assq :prologue params))))
     (mapconcat 'identity
-	       (list
-		;; Any code from the specified prologue at the start.
-		prologue
-		;; graphic output
-		(let ((graphic-file (ignore-errors (org-babel-graphical-output-file params))))
-		  (if graphic-file
-		      (format
-		       "set_plot_option ([gnuplot_term, png]); set_plot_option ([gnuplot_out_file, %S]);"
-		       graphic-file)
-		    ""))
-		;; variables
-		(mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
-		;; body
-		body
-		;; Any code from the specified epilogue at the end.
-		epilogue
-		"gnuplot_close ()$")
+               (delq nil
+	             (list
+		      ;; Any code from the specified prologue at the start.
+		      prologue
+		      ;; graphic output
+		      (if graphic-file
+                          (let* ((graphics-pkg (intern (or (cdr (assq :graphics-pkg params)) "plot")))
+                                 (graphic-format-string (cdr (assq graphics-pkg org-babel-maxima--graphic-package-options)))
+                                 (graphic-terminal (file-name-extension graphic-file))
+                                 (graphic-file (if (eq graphics-pkg 'plot) graphic-file (file-name-sans-extension graphic-file))))
+                            (format graphic-format-string graphic-terminal graphic-file)))
+		      ;; variables
+		      (mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
+		      ;; body
+		      body
+		      ;; Any code from the specified epilogue at the end.
+		      epilogue
+		      (if graphic-file
+                          (cdr (assq :graphical-output org-babel-maxima--default-epilogue))
+                        (cdr (assq :non-graphical-output org-babel-maxima--default-epilogue)))))
 	       "\n")))
 
+(defvar org-babel-maxima--output-filter-regexps
+  '("batch"                     ;; remove the `batch' or `batchload' line
+    "^rat: replaced .*$"        ;; remove notices from `rat'
+    "^;;; Loading #P"           ;; remove notices from the lisp implementation
+    "^read and interpret"       ;; remove notice from `batch'
+    "^(%\\([i]-?[0-9]+\\))[ ]$" ;; remove empty input lines from `batch'-ing
+    )
+  "Regexps to remove extraneous lines from Maxima's output.
+See `org-babel-maxima--output-filter'.")
+
+(defun org-babel-maxima--output-filter (line)
+  "Filter empty or undesired lines from Maxima output.
+Return nil if LINE is zero-length or it matches a regexp in
+`org-babel-maxima--output-filter'; otherwise, return LINE."
+  (unless (or (= 0 (length line))
+              (cl-some #'(lambda(r) (string-match r line))
+                       org-babel-maxima--output-filter-regexps))
+    line))
+
 (defun org-babel-execute:maxima (body params)
   "Execute Maxima BODY according to PARAMS.
 This function is called by `org-babel-execute-src-block'."
@@ -80,11 +135,20 @@ This function is called by `org-babel-execute-src-block'."
   (let ((result-params (split-string (or (cdr (assq :results params)) "")))
 	(result
 	 (let* ((cmdline (or (cdr (assq :cmdline params)) ""))
+                (batch/load (or (cdr (assq :batch params)) "batchload"))
+                (cmdline (if (or (equal cmdline "") (equal batch/load "batchload"))
+                             ;; legacy behaviour:
+                             ;; ensure that --very-quiet is on command-line by default
+                             (concat cmdline " " org-babel-maxima--command-arguments-default)
+                           ;; if using an alternate loader, :cmdline overwrites default
+                           cmdline))
 		(in-file (org-babel-temp-file "maxima-" ".max"))
-		(cmd (format "%s --very-quiet -r %s %s"
+ 		(cmd (format "%s -r %s %s"
 			     org-babel-maxima-command
                              (shell-quote-argument
-                              (format "batchload(%S)$" in-file))
+                              ;; bind linenum to 0 so the first line
+                              ;; of in-file has line number 1
+                              (format "(linenum:0, %s(%S))$" batch/load in-file))
                              cmdline)))
 	   (with-temp-file in-file (insert (org-babel-maxima-expand body params)))
 	   (message cmd)
@@ -93,12 +157,7 @@ This function is called by `org-babel-execute-src-block'."
              (mapconcat
               #'identity
               (delq nil
-                    (mapcar (lambda (line)
-                              (unless (or (string-match "batch" line)
-                                          (string-match "^rat: replaced .*$" line)
-                                          (string-match "^;;; Loading #P" line)
-                                          (= 0 (length line)))
-                                line))
+                    (mapcar #'org-babel-maxima--output-filter
                             (split-string raw "[\r\n]"))) "\n")))))
     (if (ignore-errors (org-babel-graphical-output-file params))
 	nil
diff --git a/testing/examples/ob-maxima-test.org b/testing/examples/ob-maxima-test.org
index b83114a4f..c7847d959 100644
--- a/testing/examples/ob-maxima-test.org
+++ b/testing/examples/ob-maxima-test.org
@@ -23,6 +23,14 @@ plot2d(sin(a*x), [x, 0, 2*%pi])$
 #+begin_src maxima  :results graphics :file maxima-test-3d.png
 plot3d (2^(-u^2 + v^2), [u, -3, 3], [v, -2, 2])$
 #+end_src
+
+** Use the ~draw~ package
+This test exercises the ~:graphics-pkg~ header argument.
+#+name: ob-maxima/draw
+#+begin_src maxima  :var a=0.5 :results graphics file :file ./maxima-test-cos.png :graphics-pkg draw
+draw2d(explicit(cos(a*x), x, -%pi, %pi))$
+#+end_src
+
 * Output to a file
 Output to a file
 #+begin_src maxima :file maxima-test-ouput.out
@@ -89,3 +97,49 @@ tex(ratsimp(diff(%e^(a*x), x)));
 #+BEGIN_LaTeX
 $$a\,e^{a\,x}$$
 #+END_LaTeX
+
+* Batch
+:PROPERTIES:
+:header-args:maxima: :exports both :results verbatim :batch batch
+:END:
+
+Exercise the ~:batch~ header argument. These tests are also defined in
+~testing/lisp/test-ob-maxima.el~. The test name is name of the ~ert~
+test.
+
+#+name: ob-maxima/batch+verbatim
+#+begin_src maxima
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+quiet
+#+begin_src maxima :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+:lisp
+#+begin_src maxima :cmdline --quiet
+:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+empty-string
+#+begin_src maxima :cmdline --quiet
+"";
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+whitespace-string
+#+begin_src maxima :cmdline --quiet
+" ";
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+syntax-error
+#+begin_src maxima :cmdline --quiet
+;
+#+end_src
+
+#+name: ob-maxima/batch+verbatim+eof-error
+#+begin_src maxima :cmdline --quiet
+x:
+#+end_src
diff --git a/testing/lisp/test-ob-maxima.el b/testing/lisp/test-ob-maxima.el
index ae9fdc775..653ed4041 100644
--- a/testing/lisp/test-ob-maxima.el
+++ b/testing/lisp/test-ob-maxima.el
@@ -66,6 +66,107 @@
      (equal
       '((1 2 3) (2 3 4) (3 4 5)) (org-babel-execute-src-block)))))
 
+
+;; 6 tests to test the :batch header argument
+(ert-deftest ob-maxima/batch+verbatim ()
+  "Exercise the `:batch' header argument.
+Since `--very-quiet' is set, the input and output are printed
+without labels."
+  (org-test-with-temp-text
+      (format "#+begin_src maxima :results verbatim :batch batch
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+    (should (equal (org-babel-execute-src-block)
+                   "(assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n                                 gamma(z + 1)"))))
+
+(ert-deftest ob-maxima/batch+verbatim+quiet ()
+  "Exercise the `:batch' header argument.
+Since `--quiet' is set, the input and output are printed with
+labels."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+(assume(z>0),
+integrate(exp(-t)*t^z, t, 0, inf));
+#+end_src")
+    (should (equal (org-babel-execute-src-block)
+                   "(%i1) (assume(z > 0),integrate(exp(-t)*t^z,t,0,inf))\n(%o1)                            gamma(z + 1)"))))
+
+(ert-deftest ob-maxima/batch+verbatim+:lisp ()
+  "Exercise the `:batch' header argument with `:lisp' reader.
+Since `--quiet' is set, the output is printed (as a lisp form)."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+:lisp
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+:lisp #$(assume(z>0),integrate(exp(-t)*t^z, t, 0, inf));#$
+#+end_src
+")
+    (should (equal (org-babel-execute-src-block)
+                   "((%GAMMA SIMP) ((MPLUS SIMP) 1 $Z))"))))
+
+(ert-deftest ob-maxima/batch+verbatim+empty-string-vq ()
+  "Exercise the `:batch' header argument with empty string input.
+Since `--very-quiet' is set, the output is printed."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+empty-string-vq
+#+begin_src maxima :results verbatim :batch batch :cmdline --very-quiet
+\"\";
+#+end_src
+")
+    (should (equal (org-babel-execute-src-block) "\"\"\n "))))
+
+(ert-deftest ob-maxima/batch+verbatim+empty-string ()
+  "Exercise the `:batch' header argument with empty string input.
+Since `--quiet' is set, the input and output are printed with
+labels."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+empty-string
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+\"\";
+#+end_src
+")
+    (should (equal (org-babel-execute-src-block) "(%i1) \"\"\n(%o1) "))))
+
+(ert-deftest ob-maxima/batch+verbatim+whitespace-string ()
+  "Exercise the `:batch' header argument with whitespace input.
+Since `--quiet' is set, the input and output are printed with
+labels."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+whitespace-string
+#+begin_src maxima :results verbatim :batch batch :cmdline --quiet
+\" \";
+#+end_src
+")
+    (should (equal (org-babel-execute-src-block)
+                   "(%i1) \" \"\n(%o1)                                   "))))
+
+(ert-deftest ob-maxima/batch+verbatim+syntax-error ()
+  "Exercise the `:batch' header argument with syntax error.
+Send empty input line to Maxima."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+syntax-error
+#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
+;
+#+end_src
+")
+    (should (string-match "incorrect syntax: Premature termination of input at ;\\."
+                          (org-babel-execute-src-block)))))
+
+(ert-deftest ob-maxima/batch+verbatim+eof-error ()
+  "Exercise the `:batch' header argument with syntax error.
+Send an incomplete expression to Maxima."
+  (org-test-with-temp-text
+      (format "#+name: ob-maxima/batch+verbatim+eof-error
+#+begin_src maxima  :results verbatim :batch batch :cmdline --quiet
+x:
+#+end_src
+")
+    (should (string-match "end of file while scanning expression\\."
+                          (org-babel-execute-src-block)))))
+
+
+
 (provide 'test-ob-maxima)
 
 ;;; test-ob-maxima.el ends here
-- 
2.40.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0001-org-contrib-babel-languages-ob-doc-maxima.org-correc.patch --]
[-- Type: text/x-diff; name="0001-org-contrib-babel-languages-ob-doc-maxima.org-correc.patch", Size: 1680 bytes --]

From dceb35854fcda3e467c3b1bd8f7f343434f7fb2f Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Tue, 26 Sep 2023 11:04:45 -0500
Subject: [PATCH 1/2] * org-contrib/babel/languages/ob-doc-maxima.org: correct
 urls

The old .net urls have been replaced by .io urls.  These pages are
served over https.

The location of the project banner has moved, so that is updated, too.
---
 org-contrib/babel/languages/ob-doc-maxima.org | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/org-contrib/babel/languages/ob-doc-maxima.org b/org-contrib/babel/languages/ob-doc-maxima.org
index a6b403dc..50438b3a 100644
--- a/org-contrib/babel/languages/ob-doc-maxima.org
+++ b/org-contrib/babel/languages/ob-doc-maxima.org
@@ -14,11 +14,12 @@
 #+begin_export html
   <div id="subtitle" style="float: center; text-align: center;">
   <p>
-  Org Mode support for <a href="http://maxima.sourceforge.net/">Maxima</a>
+  Org Mode support for <a href="https://maxima.sourceforge.io/">Maxima</a>
   </p>
   <p>
-  <a href="http://maxima.sourceforge.net/">
-  <img src="http://maxima.sourceforge.net/i/logo.png"/>
+  <a href="https://maxima.sourceforge.io/">
+  <img width="20%" src="https://maxima.sourceforge.io/img/maxima.svg"/>
+  <img width="70%" src="https://maxima.sourceforge.io/img/maxima-banner.png"/>
   </a>
   </p>
   </div>
@@ -73,7 +74,6 @@ You must activate Maxima by adding a line to
      '((maxima . t))) ; this line activates maxima
 #+END_SRC
 
-
 * Org Mode Features for Maxima Source Code Blocks
 ** Header Arguments
 There are no Maxima-specific default header argument values.
-- 
2.40.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 0002-org-contrib-babel-languages-ob-doc-maxima.org-new-he.patch --]
[-- Type: text/x-diff; name="0002-org-contrib-babel-languages-ob-doc-maxima.org-new-he.patch", Size: 50068 bytes --]

From cd454948bccea9d14a56b81f70562c7892071e77 Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Mon, 2 Oct 2023 10:30:11 -0500
Subject: [PATCH 2/2] * org-contrib/babel/languages/ob-doc-maxima.org: new
 header args

* org-contrib/babel/languages/ob-doc-maxima.org: Document the new
header arguments, `:batch' and `:graphics-pkg'.

Show examples with `:batch' that: (1) use Maxima's `:lisp' reader to print
the internal representation of an object as a sexp; (2) reproduce the
output of `batch'-ed input file, including input/output line
labels; (3) typeset Maxima output in LaTeX.

Show examples with `:graphics-pkg' that: (1) create a `gif' graphics
file using `plot'; (2) create an `svg' graphics file using `draw'.

* org-contrib/babel/languages/images/ob-maxima-plot.gif: New file.
* org-contrib/babel/languages/images/ob-maxima-draw.svg: New file.
Both of these files are created in the `:graphics-pkg' examples.
---
 .../babel/languages/images/ob-maxima-draw.svg | 366 ++++++++++++++++++
 .../babel/languages/images/ob-maxima-plot.gif | Bin 0 -> 4696 bytes
 org-contrib/babel/languages/ob-doc-maxima.org | 333 +++++++++++++++-
 3 files changed, 686 insertions(+), 13 deletions(-)
 create mode 100644 org-contrib/babel/languages/images/ob-maxima-draw.svg
 create mode 100644 org-contrib/babel/languages/images/ob-maxima-plot.gif

diff --git a/org-contrib/babel/languages/images/ob-maxima-draw.svg b/org-contrib/babel/languages/images/ob-maxima-draw.svg
new file mode 100644
index 00000000..476bd8ab
--- /dev/null
+++ b/org-contrib/babel/languages/images/ob-maxima-draw.svg
@@ -0,0 +1,366 @@
+<?xml version="1.0" encoding="utf-8"  standalone="no"?>
+<svg 
+ width="600" height="500"
+ viewBox="0 0 600 500"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+>
+
+<title>Gnuplot</title>
+<desc>Produced by GNUPLOT 5.4 patchlevel 4 </desc>
+
+<g id="gnuplot_canvas">
+
+<rect x="0" y="0" width="600" height="500" fill="none"/>
+<defs>
+
+	<circle id='gpDot' r='0.5' stroke-width='0.5' stroke='currentColor'/>
+	<path id='gpPt0' stroke-width='0.222' stroke='currentColor' d='M-1,0 h2 M0,-1 v2'/>
+	<path id='gpPt1' stroke-width='0.222' stroke='currentColor' d='M-1,-1 L1,1 M1,-1 L-1,1'/>
+	<path id='gpPt2' stroke-width='0.222' stroke='currentColor' d='M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1'/>
+	<rect id='gpPt3' stroke-width='0.222' stroke='currentColor' x='-1' y='-1' width='2' height='2'/>
+	<rect id='gpPt4' stroke-width='0.222' stroke='currentColor' fill='currentColor' x='-1' y='-1' width='2' height='2'/>
+	<circle id='gpPt5' stroke-width='0.222' stroke='currentColor' cx='0' cy='0' r='1'/>
+	<use xlink:href='#gpPt5' id='gpPt6' fill='currentColor' stroke='none'/>
+	<path id='gpPt7' stroke-width='0.222' stroke='currentColor' d='M0,-1.33 L-1.33,0.67 L1.33,0.67 z'/>
+	<use xlink:href='#gpPt7' id='gpPt8' fill='currentColor' stroke='none'/>
+	<use xlink:href='#gpPt7' id='gpPt9' stroke='currentColor' transform='rotate(180)'/>
+	<use xlink:href='#gpPt9' id='gpPt10' fill='currentColor' stroke='none'/>
+	<use xlink:href='#gpPt3' id='gpPt11' stroke='currentColor' transform='rotate(45)'/>
+	<use xlink:href='#gpPt11' id='gpPt12' fill='currentColor' stroke='none'/>
+	<path id='gpPt13' stroke-width='0.222' stroke='currentColor' d='M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z'/>
+	<use xlink:href='#gpPt13' id='gpPt14' fill='currentColor' stroke='none'/>
+	<filter id='textbox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
+	  <feFlood flood-color='white' flood-opacity='1' result='bgnd'/>
+	  <feComposite in='SourceGraphic' in2='bgnd' operator='atop'/>
+	</filter>
+	<filter id='greybox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
+	  <feFlood flood-color='lightgrey' flood-opacity='1' result='grey'/>
+	  <feComposite in='SourceGraphic' in2='grey' operator='atop'/>
+	</filter>
+</defs>
+<g fill="none" color="white" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<g stroke='none' shape-rendering='crispEdges'>
+		<polygon fill = 'rgb(255, 255, 255)' points = '0.00,500.00 599.99,500.00 599.99,0.01 0.00,0.01 '/>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M54.53,426.83 L565.82,426.83  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M54.53,426.83 L63.53,426.83  '/>	<g transform="translate(46.14,430.73)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
+		<text><tspan font-family="Arial" >-1</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M54.53,333.92 L565.82,333.92  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M54.53,333.92 L63.53,333.92  '/>	<g transform="translate(46.14,337.82)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
+		<text><tspan font-family="Arial" >-0.5</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M54.53,241.00 L565.82,241.00  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M54.53,241.00 L63.53,241.00  '/>	<g transform="translate(46.14,244.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
+		<text><tspan font-family="Arial" >0</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M54.53,148.09 L565.82,148.09  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M54.53,148.09 L63.53,148.09  '/>	<g transform="translate(46.14,151.99)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
+		<text><tspan font-family="Arial" >0.5</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M54.53,55.18 L565.82,55.18  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M54.53,55.18 L63.53,55.18  '/>	<g transform="translate(46.14,59.08)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
+		<text><tspan font-family="Arial" >1</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M54.53,464.00 L54.53,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M54.53,464.00 L54.53,455.00  '/>	<g transform="translate(54.53,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >-1</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M116.26,464.00 L116.26,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M116.26,464.00 L116.26,455.00  '/>	<g transform="translate(116.26,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >-0.5</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M177.98,464.00 L177.98,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M177.98,464.00 L177.98,455.00  '/>	<g transform="translate(177.98,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >0</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M239.71,464.00 L239.71,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M239.71,464.00 L239.71,455.00  '/>	<g transform="translate(239.71,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >0.5</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M301.44,464.00 L301.44,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M301.44,464.00 L301.44,455.00  '/>	<g transform="translate(301.44,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >1</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M363.16,464.00 L363.16,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M363.16,464.00 L363.16,455.00  '/>	<g transform="translate(363.16,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >1.5</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M424.89,464.00 L424.89,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M424.89,464.00 L424.89,455.00  '/>	<g transform="translate(424.89,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >2</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M486.61,464.00 L486.61,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M486.61,464.00 L486.61,455.00  '/>	<g transform="translate(486.61,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >2.5</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="gray" stroke="currentColor" stroke-width="0.50" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='gray' stroke-dasharray='2,4' class="gridline"  d='M548.34,464.00 L548.34,27.01 L548.34,18.01  '/></g>
+<g fill="none" color="gray" stroke="gray" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M548.34,464.00 L548.34,455.00  '/>	<g transform="translate(548.34,485.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text><tspan font-family="Arial" >3</tspan></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M54.53,18.01 L54.53,464.00 L565.82,464.00 L565.82,18.01 L54.53,18.01 Z  '/></g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<g transform="translate(10.18,241.01) rotate(270)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<g transform="translate(574.22,241.01) rotate(270)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<g transform="translate(310.17,21.91)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+	<g id="gnuplot_plot_1" ><title>gnuplot_plot_1</title>
+<g fill="none" color="white" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='rgb(  0,   0, 255)'  d='M565.82,426.83 L564.15,426.82 L562.48,426.77 L560.80,426.68 L559.13,426.56 L557.46,426.41 L555.79,426.22 L554.12,426.00
+		L552.45,425.74 L550.77,425.46 L549.10,425.13 L547.43,424.78 L545.76,424.39 L544.09,423.96 L542.42,423.50 L540.74,423.01
+		L539.07,422.49 L537.40,421.93 L535.73,421.34 L534.06,420.72 L532.39,420.06 L530.71,419.37 L529.04,418.65 L527.37,417.89
+		L525.70,417.11 L524.03,416.29 L522.36,415.44 L520.68,414.55 L519.01,413.64 L517.34,412.69 L515.67,411.71 L514.00,410.70
+		L512.33,409.66 L510.65,408.59 L508.98,407.48 L507.31,406.35 L505.64,405.19 L503.97,403.99 L502.29,402.77 L500.62,401.52
+		L498.95,400.23 L497.28,398.92 L495.61,397.58 L493.94,396.21 L492.26,394.81 L490.59,393.39 L488.92,391.93 L487.25,390.45
+		L485.58,388.94 L483.91,387.41 L482.23,385.84 L480.56,384.25 L478.89,382.64 L477.22,380.99 L475.55,379.33 L473.88,377.63
+		L472.20,375.92 L470.53,374.17 L468.86,372.41 L467.19,370.61 L465.52,368.80 L463.85,366.96 L462.17,365.10 L460.50,363.22
+		L458.83,361.31 L457.16,359.38 L455.49,357.43 L453.82,355.46 L452.14,353.46 L450.47,351.45 L448.80,349.42 L447.13,347.36
+		L445.46,345.29 L443.78,343.20 L442.11,341.09 L440.44,338.96 L438.77,336.81 L437.10,334.65 L435.43,332.46 L433.75,330.26
+		L432.08,328.05 L430.41,325.82 L428.74,323.57 L427.07,321.31 L425.40,319.03 L423.72,316.74 L422.05,314.44 L420.38,312.12
+		L418.71,309.79 L417.04,307.44 L415.37,305.09 L413.69,302.72 L412.02,300.34 L410.35,297.95 L408.68,295.55 L407.01,293.14
+		L405.34,290.72 L403.66,288.29 L401.99,285.85 L400.32,283.41 L398.65,280.95 L396.98,278.49 L395.31,276.02 L393.63,273.55
+		L391.96,271.07 L390.29,268.58 L388.62,266.09 L386.95,263.60 L385.27,261.10 L383.60,258.59 L381.93,256.09 L380.26,253.58
+		L378.59,251.07 L376.92,248.55 L375.24,246.04 L373.57,243.52 L371.90,241.00 L370.23,238.49 L368.56,235.97 L366.89,233.46
+		L365.21,230.94 L363.54,228.43 L361.87,225.92 L360.20,223.42 L358.53,220.91 L356.86,218.41 L355.18,215.92 L353.51,213.43
+		L351.84,210.94 L350.17,208.46 L348.50,205.99 L346.83,203.52 L345.15,201.06 L343.48,198.60 L341.81,196.16 L340.14,193.72
+		L338.47,191.29 L336.80,188.87 L335.12,186.46 L333.45,184.06 L331.78,181.67 L330.11,179.29 L328.44,176.92 L326.76,174.57
+		L325.09,172.22 L323.42,169.89 L321.75,167.57 L320.08,165.27 L318.41,162.98 L316.73,160.70 L315.06,158.44 L313.39,156.19
+		L311.72,153.96 L310.05,151.75 L308.38,149.55 L306.70,147.36 L305.03,145.20 L303.36,143.05 L301.69,140.92 L300.02,138.81
+		L298.35,136.72 L296.67,134.65 L295.00,132.59 L293.33,130.56 L291.66,128.55 L289.99,126.55 L288.32,124.58 L286.64,122.63
+		L284.97,120.70 L283.30,118.79 L281.63,116.91 L279.96,115.05 L278.29,113.21 L276.61,111.40 L274.94,109.60 L273.27,107.84
+		L271.60,106.09 L269.93,104.38 L268.26,102.68 L266.58,101.02 L264.91,99.37 L263.24,97.76 L261.57,96.17 L259.90,94.60
+		L258.22,93.07 L256.55,91.56 L254.88,90.08 L253.21,88.62 L251.54,87.20 L249.87,85.80 L248.19,84.43 L246.52,83.09
+		L244.85,81.78 L243.18,80.49 L241.51,79.24 L239.84,78.02 L238.16,76.82 L236.49,75.66 L234.82,74.53 L233.15,73.42
+		L231.48,72.35 L229.81,71.31 L228.13,70.30 L226.46,69.32 L224.79,68.37 L223.12,67.46 L221.45,66.57 L219.78,65.72
+		L218.10,64.90 L216.43,64.12 L214.76,63.36 L213.09,62.64 L211.42,61.95 L209.75,61.29 L208.07,60.67 L206.40,60.08
+		L204.73,59.52 L203.06,59.00 L201.39,58.51 L199.71,58.05 L198.04,57.62 L196.37,57.23 L194.70,56.88 L193.03,56.55
+		L191.36,56.27 L189.68,56.01 L188.01,55.79 L186.34,55.60 L184.67,55.45 L183.83,55.38 L183.00,55.33 L182.16,55.28
+		L181.33,55.24 L180.91,55.23 L180.49,55.21 L180.07,55.20 L179.65,55.19 L179.45,55.19 L179.24,55.19 L179.03,55.18
+		L178.82,55.18 L178.71,55.18 L178.61,55.18 L178.50,55.18 L178.40,55.18 L178.35,55.18 L178.30,55.18 L178.24,55.18
+		L178.19,55.18 L178.17,55.18 L178.14,55.18 L178.11,55.18 L178.09,55.18 L178.07,55.18 L178.06,55.18 L178.05,55.18
+		L178.03,55.18 L178.02,55.18 L178.01,55.18 L178.00,55.18 L177.99,55.18  '/></g>
+	</g>
+	<g id="gnuplot_plot_2" ><title>gnuplot_plot_2</title>
+<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='rgb(  0,   0, 255)'  d='M177.98,241.00 L177.97,241.00 L177.96,241.00 L177.95,241.00 L177.94,241.00 L177.93,241.00 L177.92,241.00 L177.90,241.00
+		L177.88,241.00 L177.87,241.00 L177.85,241.00 L177.82,241.00 L177.78,241.00 L177.75,241.00 L177.72,241.00 L177.65,241.00
+		L177.58,241.00 L177.52,241.00 L177.45,241.00 L177.32,241.00 L177.18,241.00 L177.05,241.00 L176.92,241.00 L176.65,241.00
+		L176.39,241.00 L176.12,241.00 L175.85,241.00 L175.32,241.00 L174.79,241.00 L174.26,241.00 L173.73,241.00 L172.66,241.00
+		L171.60,241.00 L170.53,241.00 L169.47,241.00 L168.40,241.00 L167.34,241.00 L166.28,241.00 L165.21,241.00 L164.15,241.00
+		L163.08,241.00 L162.02,241.00 L160.95,241.00 L159.89,241.00 L158.83,241.00 L157.76,241.00 L156.70,241.00 L155.63,241.00
+		L154.57,241.00 L153.50,241.00 L152.44,241.00 L151.38,241.00 L150.31,241.00 L149.25,241.00 L148.18,241.00 L147.12,241.00
+		L146.06,241.00 L144.99,241.00 L143.93,241.00 L142.86,241.00 L141.80,241.00 L140.73,241.00 L139.67,241.00 L138.61,241.00
+		L137.54,241.00 L136.48,241.00 L135.41,241.00 L134.35,241.00 L133.28,241.00 L132.22,241.00 L131.16,241.00 L130.09,241.00
+		L129.03,241.00 L127.96,241.00 L126.90,241.00 L125.83,241.00 L124.77,241.00 L123.71,241.00 L122.64,241.00 L121.58,241.00
+		L120.51,241.00 L119.45,241.00 L118.38,241.00 L117.32,241.00 L116.26,241.00 L115.19,241.00 L114.13,241.00 L113.06,241.00
+		L112.00,241.00 L110.94,241.00 L109.87,241.00 L108.81,241.00 L107.74,241.00 L106.68,241.00 L105.61,241.00 L104.55,241.00
+		L103.49,241.00 L102.42,241.00 L101.36,241.00 L100.29,241.00 L99.23,241.00 L98.16,241.00 L97.10,241.00 L96.04,241.00
+		L94.97,241.00 L93.91,241.00 L92.84,241.00 L91.78,241.00 L90.71,241.00 L89.65,241.00 L88.59,241.00 L87.52,241.00
+		L86.46,241.00 L85.39,241.00 L84.33,241.00 L83.26,241.00 L82.20,241.00 L81.14,241.00 L80.07,241.00 L79.01,241.00
+		L77.94,241.00 L76.88,241.00 L75.81,241.00 L74.75,241.00 L73.69,241.00 L72.62,241.00 L71.56,241.00 L70.49,241.00
+		L69.43,241.00 L68.37,241.00 L67.30,241.00 L66.24,241.00 L65.17,241.00 L64.11,241.00 L63.04,241.00 L61.98,241.00
+		L60.92,241.00 L59.85,241.00 L58.79,241.00 L57.72,241.00 L56.66,241.00 L55.59,241.00 L54.53,241.00  '/></g>
+	</g>
+	<g id="gnuplot_plot_3" ><title>gnuplot_plot_3</title>
+<g fill="none" color="white" stroke="rgb(  0,   0, 255)" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<g stroke='none' shape-rendering='crispEdges'>
+		<polygon fill = 'rgb(255, 255, 255)' points = '184.16,241.00 184.00,243.07 183.54,245.04 182.81,246.80 181.83,248.27 180.66,249.38 179.36,250.06 177.98,250.30 176.61,250.06 175.30,249.38 174.13,248.27 173.16,246.80 172.42,245.04 171.96,243.07 171.81,241.00 171.96,238.94
+172.42,236.97 173.16,235.21 174.13,233.74 175.30,232.63 176.61,231.95 177.98,231.71 179.36,231.95 180.66,232.63 181.83,233.74 182.81,235.21 183.54,236.97 184.00,238.94 184.16,241.00 177.98,241.00 '/>
+	</g>
+</g>
+	</g>
+	<g id="gnuplot_plot_4" ><title>gnuplot_plot_4</title>
+<g fill="none" color="white" stroke="rgb(255, 255, 255)" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='rgb(  0,   0, 255)'  d='M184.16,241.00 L184.00,243.07 L183.54,245.04 L182.81,246.80 L181.83,248.27 L180.66,249.38 L179.36,250.06 L177.98,250.30
+		L176.61,250.06 L175.30,249.38 L174.13,248.27 L173.16,246.80 L172.42,245.04 L171.96,243.07 L171.81,241.00 L171.96,238.94
+		L172.42,236.97 L173.16,235.21 L174.13,233.74 L175.30,232.63 L176.61,231.95 L177.98,231.71 L179.36,231.95 L180.66,232.63
+		L181.83,233.74 L182.81,235.21 L183.54,236.97 L184.00,238.94 L184.16,241.00  '/></g>
+	</g>
+	<g id="gnuplot_plot_5" ><title>gnuplot_plot_5</title>
+<g fill="none" color="white" stroke="rgb(  0,   0, 255)" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<g stroke='none' shape-rendering='crispEdges'>
+		<polygon fill = 'rgb(  0,   0, 255)' points = '184.16,55.18 184.00,57.24 183.54,59.21 182.81,60.97 181.83,62.44 180.66,63.55 179.36,64.23 177.98,64.47 176.61,64.23 175.30,63.55 174.13,62.44 173.16,60.97 172.42,59.21 171.96,57.24 171.81,55.18 171.96,53.11
+172.42,51.14 173.16,49.38 174.13,47.91 175.30,46.80 176.61,46.12 177.98,45.88 179.36,46.12 180.66,46.80 181.83,47.91 182.81,49.38 183.54,51.14 184.00,53.11 184.16,55.18 177.98,55.18 '/>
+	</g>
+</g>
+	</g>
+	<g id="gnuplot_plot_6" ><title>gnuplot_plot_6</title>
+<g fill="none" color="white" stroke="rgb(  0,   0, 255)" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='rgb(  0,   0, 255)'  d='M184.16,55.18 L184.00,57.24 L183.54,59.21 L182.81,60.97 L181.83,62.44 L180.66,63.55 L179.36,64.23 L177.98,64.47
+		L176.61,64.23 L175.30,63.55 L174.13,62.44 L173.16,60.97 L172.42,59.21 L171.96,57.24 L171.81,55.18 L171.96,53.11
+		L172.42,51.14 L173.16,49.38 L174.13,47.91 L175.30,46.80 L176.61,46.12 L177.98,45.88 L179.36,46.12 L180.66,46.80
+		L181.83,47.91 L182.81,49.38 L183.54,51.14 L184.00,53.11 L184.16,55.18  '/></g>
+	</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="black" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<path stroke='black'  d='M54.53,18.01 L54.53,464.00 L565.82,464.00 L565.82,18.01 L54.53,18.01 Z  '/></g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+	<g transform="translate(310.17,21.91)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
+		<text></text>
+	</g>
+</g>
+<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
+</g>
+</g>
+</svg>
+
diff --git a/org-contrib/babel/languages/images/ob-maxima-plot.gif b/org-contrib/babel/languages/images/ob-maxima-plot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..15ec5a87a6e7b6ab1e851e96fa98cd68e24941fc
GIT binary patch
literal 4696
zcmb_a_d6Sm_YGPNVpFq4wMMKMwfl;_cU!Ziw2GE$ZB=5$j!4x^jaaco)QA<eQ(ILj
zuThjxwbf|y?fdx~zV|uLz0dvO+<VS*uc5Jls>&l6?Gnv806?Wu0RTW@Vc~y;2mrvS
zL;w}AvqOXe1_uG!UdvRXFaQQ6!l)2eSTX<rg#oBAY9#e@DH!~h3SAoi%j4(gS5#Cq
zH#hh2@Q93z%*n~Y<MBiyad>!mZEfxEid_W-<PNgt>-z4!-6bk@XCa!})Lpl;L!J4n
z004OWH%Hz`z9E}z_rE@wkI(O~6aZi(est@95~+aE2`blHYNXXJ3`W%loWWjgW`^yq
zr*t$wYk@Nz9nBZQgsG)~o#>qmz|=zF0@4b4@0lEo3jpKdf<gZR26H9CT&b}C^h2qI
zf8k0k^rI4q)W3eH#F6IwUFvRO(?~b9dxTgYPK6dyg*!Vt7Z(@1y1EJq3beGeTwGj)
zgoOV3{eKMU|7QJn3&0f$3=ka?8wZb1NK8sjNkya~(@}3T-eqQG=j7(0-{%(;7Ga7@
zO3TWz6_r)hHMMp1xCVUVho<J1Rzh2QM`stY`(saUU;n`15b4wK$mrPk#N^cH=`S;1
zXXn1nFZ{c>w7l|tb#48}#wK}d`{&ND-M#&T!=vMq-=}Bi7k?;J03D;CQGH=|43HD-
zJXl}U6VE1Uf;Pfo`jUASz2^sU#RF-=x=Dg+^01+|61J7jLk*>$vLNmxv@yPHBu~|!
zJU@glA1i>yFkUm^5^DuaBW-NKsa{hhRx)arRk$6epW5X;ndT3iyKm_7A?}{Cvcs(V
z(}|!r;G>N>Pl{J^-@EfK<kHrM#^i-IMmeWW7+uUhlU@CCPY&>#{&35lXrKKx)BJGY
zejPK7GNi$*Rnc&?jhG_&HWdG3Dph-H4nl9Xsb6XR3BfDC!>e7#J)J-DdU?mWmGjSz
zdHd3?Q#boHxzUToea9gwm4ePawVDlhwe6yXWt;SNoDC&LyHoSzVAk4^&T_Er!~X6g
z-XzQGcfw9;h#O<oF2S8=8N{cH0l#qyaFb@qU{+WTL{<33<$aE2h4s*trI>PaY%+Yn
z`FCPGuSvg%tSAeen*=vp0^{@(ZJ!hlR=<ytQ9NE*kyPn7vPqq(p(~cwBJ=X5;n@;R
zk<c3y$yJ1Oe(|cbr7Qy~9cRVxB*V(2BI{k9->C`0&RY_dRf8O2%xo=`EYtTmzKzKB
z`q(PwV;&(|E*m^LYn4~I>t&K3Le5Dqz_NiEv%3J`4Q+Vt<VO6c1VKVO4P_%Kjygka
zmH-}rlge|SlajIMV>+_yJW{=~vUJ6tEM9m2V`Xa1j>C`FGsBKmnz*3JXEzCAgl9Tk
zzBbjO-L!AF>$e2+>}x9&o+0tsR(XRB-L6tKYG0c4Q=4X^+k8|P?%T+UtT4XaX<0yP
zB(_CYS4p=~hyo1l`yQrpTE{vozMbTqD$A}keY*NY+O{yMII<vm*KH+W3nI@+(HaJI
zyWX*t|9JI)08tRIoqwsxtD@sG*jK380J)XdpF+A(H*E2#zC)9BSm8tmA4yt5zZxZP
zOFNG-(WWBC8KYCu#tf!@<2tFgAFxbL24Y#KY$8t@>(5=^2WB}<&85w_;B^9n`jO@V
zvp?Y-$#Wol$H?sR9}wI8D<^VLF5U9`V2Oa{ftQPsE}XxGv(6S$R^t3$srp(8^oD#N
zL)dPvD%(<cS`WlxTh}u*S%}32Pgw|x7!}8}mGa`w;7m}>zl2Zh&(4tBcvhd*ugyOY
zX5?a%*tTDRzbMCgJ)Eqqd*PyWn({;yOY8k!!^jf-&*#1!GP9;rZ?-7kX7=wWeUG{R
z&o=Kn%hOY+Z%M@RcF%ri_t-fHHS5}l+{vGs4a>+sZA**bixVvX?T<jLuqzGohSGYU
zP88E)*EGR|u5>7yC#{*Vv1~RTMDdanbk4cra!H3l=SoyDa9QcDCyu=g0+BYeukMBB
zDkLnkUD09S3t3O%tsRfOrvT@r6{d%P<Uw#=I=;gxq3g$Ekbg>Msz`-=+Q>&B<7&(h
z7^p8CoyuFQjS+@>0>M|e6B80wS}eHXfSW*o57&3$;cR)OvWes;V0ykQ?ESmWI8ean
z1;Djp1F!eqY0(>^A|wbL!YdEZ;3@$#Ixw5;B&GTa>IrgFqH<I)K1dYqag9Z(5kQ!O
zJ?}0e%uk8WTGm9f54g(BL<7IYf_aO2eCvtxP=y^cF2Rtim!2dHG*Ew)kZ$G(4ms7;
zEOUe3ZZCqov-!mDZJk5d1}R=%`)L0Bz-d%dUqwJE??sXqIvXOc+Ebyz*ojmjJ9DT%
z(MN|cdgarA5qI2UEseMFsO<|bM!CJQKzgqGbfr)I8P5tMbfSys?_j@ks52zc-o<bR
zmd7=@PaLQ=vR~_vFp#oq(|s>q^7(Y*h81`+J*=vv(ACTI!I^B*KLJpMTL_c7xFWR9
zVA&v9(tPCdU4!3TcDnC+Em&WE&Jhbt<~J`#<dP{lrB|aXE#6deRy0ghcps%ej@D82
z>U>rGrY4UcSl>OUC~Yh&!<uowb>efMZq?bUa{6QNd^^mp{k}}~rD;x=_)B&HGT!y!
z4q&%*^2`cNW=*_LwY!@5w6RR4@v}F*PjI+dB(@Qs@^0HuTVSpq5oA~LGeOtZ$+5jQ
z)1i9WNXz}3W6fxgQ)374AAhHBB|Di9+DivtL~YH4(l^&Neb{{Yddnt2mZ!C|bi+R<
zdE%u74?*eYdLZuGe3Wli+qC|2aJQ5-4<d^|b8R_vDDUB=TAq&O!==}=0*f;vS)Cyn
zFQ#_3&>ed`UC`mB$YlZ7W@cU@2iH;*1A2*4FO%I3T3w700TIv5vp*i;cNb+f(|*6?
z?I9ho@O~7gH}nOv3ype5=v$9uWOQdTw}aPgE)Z)-5rF$wnCKBF{THZ0Kio$!b>Ssi
zUP*!d5oDj?Np-8p7>H}eOfTb+HMe+7NYIyb50SF!+hQuM9R<<yg2uWx<YGoih64I1
zA0S{jA#^APdhpKj$2ERh8^j>P{`RWo2b*yS;0aL?d8+wz#KBNW@44d5J8IehHp2Lp
zz-7cDFFh2qGWL9Zxmbj`%i1%C&6&PWPDpZN#V2<vQp19e*9Qn;^XF>l#q3z5lK*Ij
zPQ+txy;ia&*<w<^eDL`83e4=OKzR-Y2?*;loBm8xwowNR!v*W_p&#9rYJ<xmn#3&}
zNZV!_UtRopnu}!6FKjh>C;ghlhEmM|x!?SXv1^_H;}^DvXHwwqR2wtQuZT3?MZk$l
z7gc5##(A+sXW7!t{csm98otaHtlA?ayO&^lvBEjl(s%pe9>QI4X@B|mz#Z9r)QgMN
zn}(-@cE0-=ZRj=d3$@_~ET61W`o9VchK^dYZ?zNJx(g<o3KEUH3ub;TNHvaDx<qYS
zQtw3@o#Y1w`D$qzJa8{QP!bKSJy3YPM@}aZBsR>0On=Oh$70eQy6BHvYVJJqvFuMn
z*y`7QTiEhES(w+x9X7nBT>IrR)3&5=esG61zb{vMg{Ft^BwNH{Wc516ICh6|LcVM-
z#wmY9^mIk}6aQc+b^r0BK!LzE`rV>}J#m`gyhmavv&<Ku_12&eD+%0WAXO7Rt9HIr
zbDhiQQottXn`789C8UeBPr$JKcg%HanB|X3y@JSOiH<itp*@pF__04hTY)8?4P6eq
zSR<N>yv`TmUylHVLXHI93*Z(@&lj~+a^YR^jm6cbzgS5}T3=4jFW;kHfk8#ZH^d*S
z`HNq%SG~wGr<6zPPQyx&;!J}uDcz{Jz<_IX65O6qti=-7Hlk?hqWQ2<qS(8)vV#~z
zB}F8nzoR5&65bqAXk#Qjqg%MuZ)2n75@NRFtvQS=ZcoQd1;=Qr!i<k%GKInN*f8vo
z4cmsDk-fEr#2XZM9Pt&8nkV!=*1=vPcFhi4-4Kg;>M)Ipa~zb!-+;SI*xx*gy~pd|
zV-$x9ydRB`@@|3qJdySoggWus<@&{kNZcHvO^D(ZjcJJ&`y7v0mr4KzdiEte{C)RL
zf=q0PNAw26JNty=BAFa)qIjHDI`*CsQ1<;s;%DuoRG=P*gly?xtm<Xe3T#pxFuCaW
zy^Ac_8qcH-oNOyLdF`ebE<0>kM6P2axm-J?TO#G?vxR|be1vLB>EDl%h#cO4k79wT
zS0IzBsg&4NiJ=WMpJ2%NB~J@+pjrUOkW$1<LTa16gpOW7_g$b#uU@rs*j9_p?kWOT
zqL06sR#b*KNpS1JruF!}cygFF#Dm-pNqJ)fB8vellnjAhX^fIc(5YG2D%XOtdL)<8
zzjo<YjZ=AzLEptZ`wxvavysAlsG?P|F1B#wA=0ncHvwiU)QUPNGM7DNI`l*)v88Xm
z<WL>5m65cl(gWQw1b#R)P-Z~tRy=KZs{9LRw!Iz(@IwviMOqriXJr}caG5vjnUm-}
zIr$>}8@wd&slB?M;Nr~aU|z`g%omcpFHcilfVy`*vVt9SLLHK&HXr{Zn)Pgm$4r!x
z9aF&*SCMtxtgVm9J|D<_@Fm4*2z7n=HoQWU(<2Abnk}TQoRygKo*`^iCC4sX3$w}W
z;UGo5tWr=B!xyDe!;s5Qlb077TQ?j2#VA)hkUfGkPkBSLMKYe?kUQn?7NLfA=3`I!
zp4Y{|{>dS)NkWr@_B{rRR@Z$$J*zPliXO~CGwrDjhr)3OOv{q_jMnOFUinvW>YEk$
zmqavvI)tD&L3@$~vAP9cXYC8)G>*Iqf)zo3X3-R+CJngofiBPd?E8$++x=FB^aLg5
z+=5Y6yM^zC6bB{t+(Jf^47SRv{DdN=FvTv>qAjC)-`$JCJz3XcFgpyaWJ(W4X6^=$
zE`}!2=76qPeh%WiS0qe8DiDfMv&B(;ER>jH#D-{kcd-t+*n(ERwY9`;y2JvEwwhzu
zyQFOZPG0rXcBm{}CTc$*mj*R(DV=4sbLl*)Ov)_L@tTX6BkK5&%YX(~pP1zSv#R?N
zTs{)Z99mhvY8z?dSlWA94&yJ0J`=g5XZ(f~Vt*wvu(I&X-8h+qy(4P!)}-RTZYeet
z>%1CLd|HA&)6PGu$mOqOh}BpOsL;hqu9s9!4X7sExSAG*jlf&h60%kXWbmX49Jq3G
zTrOKa-R)`R$^jH~Sq`Jk|1meWoku}(QhJKWUyG~m<rlv)RYie&gBTi~<=WL4HpqVE
z$I|H4{ClQ6$5Gpsl(_0xyIv`^G56FMSG!FBH|*CENFYcKVqU%az+3dN=q8mUHwsPr
ziK{l8ts`*=jlQfm7pVhQ-54YY35@HhoYo)H$o&Z6IQm+1HCd#24mS?26+XXzL!%*K
z4=47TMIx_ZH@8MwLqO`hLDq>!;hUhm6TT!Duj(ZDU{3CM1+TQFZi~h1<nb81Zp^dg
z)orVIJlANfQEHV}qIa*M@1#-x*$2C-Mq2@S{fQ3`&p)^dG`VRsJ$7pHc-`b_%B9iP
z^!!_s?|GA-K=Uh&<^WR`b8+VGq~<S|n0xdxKf4BvA}KhnW03KB^D)GG?<;7CP}c|J
zyDM4!vGDmoZ%ZnZ=Qt$I>=JXWGOpz*tMM#o(xeqYN+V=}YKxxy`TaLP&thsFKoTB7
zL&-~Tlad8$osfmc-V;bdRGvTK8|XR%a}JzUfg!{3W!u1b=)|t+I8@i?xNVrNoz7Hm
z2Hw7Ih4OpU(F@~iFa@dIMUch~?<cBXtLW%h;=ilshI!q=Z~PYP-r2p>G68Yh-vT{m
zGycxho*Ijq$}`KhX6@VR9ME7^q3;~s?HaN2VnB6GjAtyHhAXz>wxMnIG+mv<j@)xE
zg$j^L83%nksQ=kj$Hwlx-BxZvW|4MK`G`O!ooQN+9&TC6gQXf|qHG?|ltwGq$-&g~
zY1i!zUrSVfSC~}$dEUFxaRW{by{pnJ!RMgpJmcXde&8$OYk`{as*moH9m3(lj?T>w
zFZx^s``tAAA3OJZg!g-*`@P%ypU?OEUiAA34!qJFP`a(hFliuUHt^iG$E0MS+@GLy
zvpZr~IVf`=M*6v3_+X@>*@Nmq7fwUT?Lmj)_G+o2R|g;KntL<bhtTsw`4>Zlf+UP4
dsl=I77EZ#VNtNxS>UmP_1*zVdB?<u0_&+?K3-<s3

literal 0
HcmV?d00001

diff --git a/org-contrib/babel/languages/ob-doc-maxima.org b/org-contrib/babel/languages/ob-doc-maxima.org
index 50438b3a..fa138767 100644
--- a/org-contrib/babel/languages/ob-doc-maxima.org
+++ b/org-contrib/babel/languages/ob-doc-maxima.org
@@ -9,6 +9,7 @@
 #+HTML_LINK_UP:    index.html
 #+HTML_LINK_HOME:  https://orgmode.org/worg/
 #+EXCLUDE_TAGS: noexport
+#+PROPERTY: header-args:org :exports code :results replace
 
 #+name: banner
 #+begin_export html
@@ -25,7 +26,12 @@
   </div>
 #+end_export
 
-* Template Checklist [8/12]                                        :noexport:
+#+name: ob-doc-maxima-requires-ob-org
+#+begin_src elisp :exports none :results silent
+(require 'ob-org)
+#+end_src
+
+* Template Checklist [9/12]                                        :noexport:
   - [X] Revise #+TITLE:
   - [X] Indicate #+AUTHOR:
   - [X] Add #+EMAIL:
@@ -37,7 +43,7 @@
   - [X] Write an [[Introduction]]
   - [X] Describe [[Requirements and Setup][Requirements and Setup]]
   - [X] Replace "Language" with language name in [[Org Mode Features for Language Source Code Blocks][Org Mode Features for Language Source Code Blocks]]
-  - [ ] Describe [[Header Arguments][Header Arguments]]
+  - [X] Describe [[Header Arguments][Header Arguments]]
   - [ ] Describe support for [[Sessions]]
   - [ ] Describe [[Result Types][Result Types]]
   - [ ] Describe [[Other]] differences from supported languages
@@ -76,7 +82,27 @@ You must activate Maxima by adding a line to
 
 * Org Mode Features for Maxima Source Code Blocks
 ** Header Arguments
-There are no Maxima-specific default header argument values.
+There are no Maxima-specific /default/ header arguments.
+
+There are two Maxima-specific header arguments:
+
+- =:batch= :: This can be set to one of Maxima's source-code loaders:
+  =batch=, =load= or =batchload=.  The default loader is =batchload=.
+- =:graphics-pkg= :: This can set to one of Maxima's graphics
+  packages: =draw= or =plot=.  The default package is =plot=.
+
+If a =:file filename.ext= header argument is provided to a Maxima
+source block, in conjunction with a =:results graphics file= header
+argument, then the graphics device is determined from the file-ending
+=ext=. For the =plot= package, the following graphics devices (gnuplot
+terminals) are supported:
+#+begin_example
+png, pdf, ps, svg.
+#+end_example
+The =draw= package supports these graphics devices:
+#+begin_example
+png, jpg, gif, eps, svg, pdf.
+#+end_example
 
 The header argument, =:cmdline=, can be used to pass command line
 arguments to Maxima.
@@ -201,31 +227,312 @@ HTML export of the result:
 #+RESULTS: tex-maxima
 $${{e^ {- x }}\over{x}}$$
 
-*** Toggle inline display of latex code
+** The =:batch= header argument
+Setting the =:batch= header argument to =batch=:
+- allows the use of the =:lisp= reader;
+- provides a more verbose output;
+- allows one to typeset calculations in LaTeX.
+
+*** An example with the =:lisp= reader
+Sample code block:
+
+#+name: batch-maxima.org
+#+begin_src org :exports code :results replace
+,#+NAME: batch-maxima
+,#+HEADER: :batch batch
+,#+HEADER: :exports results
+,#+HEADER: :results raw
+,#+HEADER: :wrap example
+,#+BEGIN_SRC maxima
+  (assume(z>0), integrate(t^z*exp(-t),t,0,inf));
+  :lisp $%
+,#+END_SRC
+#+end_src
+
+#+RESULTS: batch-maxima.org
+#+NAME: batch-maxima
+#+HEADER: :batch batch
+#+HEADER: :exports results
+#+HEADER: :results raw
+#+HEADER: :wrap example
+#+BEGIN_SRC maxima
+  (assume(z>0), integrate(t^z*exp(-t),t,0,inf));
+  :lisp $%
+#+END_SRC
+
+The first line of input computes the integral \(\int_0^{\infty}
+t^z\,e^{-t}\,dt\), assuming that \(z\) is positive.  The second input
+line uses the =:lisp= reader to print the internal representation of
+that result as a sexp.
+
+HTML export of results:
+
+#+RESULTS: batch-maxima
+#+begin_example
+(assume(z > 0),integrate(t^z*exp(-t),t,0,inf))
+                                 gamma(z + 1)
+((%GAMMA SIMP) ((MPLUS SIMP) 1 $Z))
+#+end_example
+
+*** An example with line numbering
+By default, the command-line option =--very-quiet= is passed to the
+Maxima executable; this option suppresses the output of the start-up
+banner and input/output labels.  That can be modified by setting
+=:cmdline --quiet=, which allows printing of input/output labels.
+
+Sample code block:
+
+#+name: batch-quiet-maxima.org
+#+begin_src org :exports code :results replace
+,#+NAME: batch-quiet-maxima
+,#+HEADER: :batch batch
+,#+HEADER: :exports results
+,#+HEADER: :results raw
+,#+HEADER: :wrap example
+,#+HEADER: :cmdline --quiet
+,#+BEGIN_SRC maxima
+  rat(1/(x+1) + x/(x-1));
+,#+END_SRC
+#+end_src
+
+#+RESULTS: batch-quiet-maxima.org
+#+NAME: batch-quiet-maxima
+#+HEADER: :batch batch
+#+HEADER: :exports results
+#+HEADER: :results raw
+#+HEADER: :wrap example
+#+HEADER: :cmdline --quiet
+#+BEGIN_SRC maxima
+  rat(1/(x+1) + x/(x-1));
+#+END_SRC
+
+HTML export of results:
+
+#+RESULTS: batch-quiet-maxima
+#+begin_example
+(%i1) rat(1/(x+1)+x/(x-1))
+                                  2
+                                 x  + 2 x - 1
+(%o1)/R/                         ------------
+                                     2
+                                    x  - 1
+#+end_example
+
+Maxima's default is to print input in linear (or 1d) fashion, while
+output is printed in 2d.
+
+*** LaTeX output
+
+To produce LaTeX output for an extended computation, one needs to
+set-up a LaTeX printer.  This example uses the ~alt-display~ package
+to do that.  To print output as LaTeX, Maxima's 2d printer is replaced
+with ~org_tex_display~; to ensure input lines are not echoed, its 1d
+printer is replaced with a sink, ~org_no_display~ (see also this
+[[batch-note][Note]]).
+
+Tangle this code block (=C-u C-c C-v t=):
+
+#+comment: Ensure the block is evaluated (C-c C-c) after a change.
+#+comment: Move to the results block and tangle it (C-u C-c C-v t)
+#+name: maxima-initialize.lisp.org
+#+begin_src org
+,#+NAME: maxima-initialize.lisp
+,#+HEADER: :tangle ./maxima-initialize.lisp
+,#+HEADER: :exports none
+,#+HEADER: :eval none
+,#+begin_src maxima
+#$(load("alt-display.mac"),
+define_alt_display(org_no_display(output_form), ""),
+define_alt_display(org_tex_display(output_form),
+  block([],
+  printf(true,"~&#+begin_example~%(~a~d)~%",outchar,linenum),
+  printf(true,"~&#+end_example~%"),
+  tex(second(output_form)))),
+set_alt_display(2,org_tex_display),
+set_alt_display(1,org_no_display));#$
+,#+end_src
+#+end_src
+
+#+RESULTS: maxima-initialize.lisp.org
+#+NAME: maxima-initialize.lisp
+#+HEADER: :tangle ./maxima-initialize.lisp
+#+HEADER: :exports none
+#+HEADER: :eval none
+#+begin_src maxima
+#$(load("alt-display.mac"),
+define_alt_display(org_no_display(output_form), ""),
+define_alt_display(org_tex_display(output_form),
+  block([],
+  printf(true,"~&#+begin_example~%(~a~d)~%",outchar,linenum),
+  printf(true,"~&#+end_example~%"),
+  tex(second(output_form)))),
+set_alt_display(2,org_tex_display),
+set_alt_display(1,org_no_display));#$
+#+end_src
+
+Next, write a Maxima code block that sets the =:cmdline= header to
+read in the initialization code that was just tangled.
+
+#+name: batch-latex-maxima.org
+#+begin_src org
+,#+NAME: batch-latex-maxima
+,#+HEADER: :batch batch
+,#+HEADER: :exports results
+,#+HEADER: :results raw
+,#+HEADER: :wrap maximablock
+,#+HEADER: :cmdline --quiet --preload-lisp ./maxima-initialize.lisp
+,#+BEGIN_SRC maxima
+  (assume(z>0), 'integrate(t^z*exp(-t),t,0,inf) = integrate(t^z*exp(-t),t,0,inf));
+  diff(%,z);
+,#+END_SRC
+#+end_src
+
+#+RESULTS: batch-latex-maxima.org
+#+NAME: batch-latex-maxima
+#+HEADER: :batch batch
+#+HEADER: :exports results
+#+HEADER: :results raw
+#+HEADER: :wrap maximablock
+#+HEADER: :cmdline --quiet --preload-lisp ./maxima-initialize.lisp
+#+BEGIN_SRC maxima
+  (assume(z>0), 'integrate(t^z*exp(-t),t,0,inf) = integrate(t^z*exp(-t),t,0,inf));
+  diff(%,z);
+#+END_SRC
+
+HTML export of the results:
+
+#+RESULTS: batch-latex-maxima
+#+begin_maximablock
+#+begin_example
+(%o1)
+#+end_example
+$$\int_{0}^{\infty }{t^{z}\,e^ {- t }\;dt}=\Gamma\left(z+1\right)$$
+#+begin_example
+(%o2)
+#+end_example
+$$\int_{0}^{\infty }{t^{z}\,e^ {- t }\,\log t\;dt}=\psi_{0}(z+1)\,
+ \Gamma\left(z+1\right)$$
+#+end_maximablock
+
+*** <<batch-note>> Note
+Prior to version =5.47=, Maxima could only pre-load a lisp
+file; to get around this constraint, the Maxima code is written into a
+lisp file, and the =#$= reader macro is used to read the Maxima code.
+In versions 5.47 and higher, the Maxima code can be put in a =.mac=
+file and pre-loaded without the need for such tricks.
+
+** The =:graphics-pkg= header argument
+The =:graphics-pkg= header argument can be set to use either Maxima's
+built-in =plot= package (the default), or the =draw= package.
+
+*** The =plot= package
+The =plot= package is the default package that provides a simplified
+interface to =gnuplot=. Here is an example that creates a =gif= file.
+
+#+name: graphics-pkg--plot.org
+#+begin_src org
+,#+NAME: graphics-pkg--plot
+,#+HEADER: :graphics-pkg plot
+,#+HEADER: :file images/ob-maxima-plot.gif
+,#+HEADER: :results graphics file
+,#+HEADER: :exports both
+,#+begin_src maxima
+plot2d( sin(x), [x,0,2*%pi]);
+,#+end_src
+#+end_src
+
+#+RESULTS: graphics-pkg--plot.org
+#+NAME: graphics-pkg--plot
+#+HEADER: :graphics-pkg plot
+#+HEADER: :file images/ob-maxima-plot.gif
+#+HEADER: :results graphics file
+#+HEADER: :exports both
+#+begin_src maxima
+plot2d( sin(x), [x,0,2*%pi]);
+#+end_src
+
+HTML export of the results:
+
+#+CAPTION: The graph of /sin(x)/ created with =plot=.
+#+RESULTS: graphics-pkg--plot
+[[file:images/ob-maxima-plot.gif]]
+
+*** The =draw= package
+The =draw= package has more features than =plot=, including an
+object-oriented interface to several graphics engines, including
+=gnuplot=. Here is an example that creates an =svg= file containing
+the graph of a discontinuous function.
+
+#+name: graphics-pkg--draw.org
+#+begin_src org
+,#+NAME: graphics-pkg--draw
+,#+HEADER: :graphics-pkg draw
+,#+HEADER: :file images/ob-maxima-draw.svg
+,#+HEADER: :results graphics file
+,#+HEADER: :exports both
+,#+begin_src maxima
+f(x) := if x>0 then cos(x) else if x<0 then 0;
+draw2d(
+  line_width=2, grid=true, yrange=[-1.2,1.2],
+  explicit(f,x,0,%pi), explicit(f,x,-1,0),
+  fill_color=white, ellipse(0,0,0.05,0.05,0,360),
+  fill_color=blue , ellipse(0,1,0.05,0.05,0,360));
+,#+end_src
+#+end_src
+
+#+RESULTS: graphics-pkg--draw.org
+#+NAME: graphics-pkg--draw
+#+HEADER: :graphics-pkg draw
+#+HEADER: :file images/ob-maxima-draw.svg
+#+HEADER: :results graphics file
+#+HEADER: :exports both
+#+begin_src maxima
+f(x) := if x>0 then cos(x) else if x<0 then 0;
+draw2d(
+  line_width=2, grid=true, yrange=[-1.2,1.2],
+  explicit(f,x,0,%pi), explicit(f,x,-1,0),
+  fill_color=white, ellipse(0,0,0.05,0.05,0,360),
+  fill_color=blue , ellipse(0,1,0.05,0.05,0,360));
+#+end_src
+
+HTML export of the results:
+
+#+CAPTION: A discontinuous function plotted with =draw=.
+#+RESULTS: graphics-pkg--draw
+[[file:images/ob-maxima-draw.svg]]
+
+**** Note
+Internally, =ob-maxima= uses the function =set_draw_defaults=.
+Because this function _overwrites_ the existing defaults, using it in
+code blocks with the =:graphics-pkg draw= header argument will cause
+the source block evaluation to fail silently.
+
+* Additional Notes
+
+** Toggle inline display of latex code
     Latex code in org mode can be displayed inline by 'C-c C-x
     C-l'. To remove the inline display 'C-c C-c' is used. This is
     described further in the manual [fn:2].
-*** Set scale of output
+** Set scale of output
     If the inline display of the equations are illegible, the scale
     can be set by customising the variable 'org-format-latex-options',
     by setting the :scale variable to a value >1.
-*** Export
-    This exports nicely to both html (C-c C-e b) and pdf (C-c C-e
-    d). See [fn:3] and [fn:4] in the manual.
-*** Noweb expansion
+** Export
+    This exports nicely to both html (C-c C-e h h) and pdf (C-c C-e l
+    p). See [fn:3] and [fn:4] in the manual.
+** Noweb expansion
     _NOTE:_ I have not tested this yet, but as Eric Schulte noted on
     the mailing list: "Alternately, if you really want to get fancy
     you could use noweb expansion [fn:5] to insert the results of the
     imaxima code block into a latex code block, and then use the
     existing latex code block functionality to convert the imaxima
     output to images of different types depending on the export
-    target."
+    target." [fn:6]
 
-*** Footnotes
+** Footnotes
 [fn:1] (info "(org)Library of Babel")
 [fn:2] (info "(org)Previewing LaTeX fragments")
 [fn:3] (info "(org)Exporting code blocks")
 [fn:4] (info "(org)The export dispatcher")
 [fn:5] (info "(org)noweb")
-
-
+[fn:6] [[https://lists.gnu.org/archive/html/emacs-orgmode/2013-11/msg00893.html][Re: imaxima babel]]
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-10-02 16:01                                 ` Leo Butler
@ 2023-10-04  8:38                                   ` Ihor Radchenko
  2023-10-04 13:07                                     ` Leo Butler
  0 siblings, 1 reply; 23+ messages in thread
From: Ihor Radchenko @ 2023-10-04  8:38 UTC (permalink / raw)
  To: Leo Butler; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

> Attached is:
>
> - my previous patch, rebased against the latest HEAD and only modified
>   to include a patch to etc/ORG-NEWS
> - a patch to the worg docs that corrects the urls
> - a patch to the worg docs that documents the new header arguments and
>   provides examples of usage (two new graphics files are included as
>   part of that patch).

Thanks!
Applied, onto main.
https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=2ba45fcb7

Updated Worg as well:
https://git.sr.ht/~bzg/worg/commit/16ef094a
https://git.sr.ht/~bzg/worg/commit/525a1355

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom)
  2023-10-04  8:38                                   ` Ihor Radchenko
@ 2023-10-04 13:07                                     ` Leo Butler
  0 siblings, 0 replies; 23+ messages in thread
From: Leo Butler @ 2023-10-04 13:07 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Bastien, Lockywolf, emacs-orgmode@gnu.org

On Wed, Oct 04 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>> Attached is:
>>
>> - my previous patch, rebased against the latest HEAD and only modified
>>   to include a patch to etc/ORG-NEWS
>> - a patch to the worg docs that corrects the urls
>> - a patch to the worg docs that documents the new header arguments and
>>   provides examples of usage (two new graphics files are included as
>>   part of that patch).
>
> Thanks!
> Applied, onto main.
> https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=2ba45fcb7
>
> Updated Worg as well:
> https://git.sr.ht/~bzg/worg/commit/16ef094a
> https://git.sr.ht/~bzg/worg/commit/525a1355

Thanks, Ihor, for your time and feedback.

Leo

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2023-10-04 13:09 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-01  4:35 [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)] Lockywolf
2023-09-01 18:33 ` Leo Butler
2023-09-02  7:19   ` Ihor Radchenko
2023-09-02 18:12     ` Leo Butler
2023-09-05 10:57       ` [MAINTENANCE] On how much we can expose internals into defcustom (was: [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)]) Ihor Radchenko
2023-09-06 19:39         ` [MAINTENANCE] On how much we can expose internals into defcustom Leo Butler
2023-09-07 11:35           ` Ihor Radchenko
2023-09-12 21:09             ` [PATCH] ob-maxima.el, etc. (was Re: [MAINTENANCE] On how much we can expose internals into defcustom) Leo Butler
2023-09-15  9:41               ` Ihor Radchenko
2023-09-15 15:13                 ` Leo Butler
2023-09-16  9:04                   ` Ihor Radchenko
2023-09-19 19:25                     ` Leo Butler
2023-09-20  9:17                       ` Ihor Radchenko
2023-09-20 15:02                         ` Leo Butler
2023-09-21  9:18                           ` Ihor Radchenko
2023-09-21 14:03                             ` Leo Butler
2023-09-22  9:43                               ` Ihor Radchenko
2023-10-02 16:01                                 ` Leo Butler
2023-10-04  8:38                                   ` Ihor Radchenko
2023-10-04 13:07                                     ` Leo Butler
2023-09-02  7:06 ` [BUG] Consider replacing bachload with batch in ob-maxima. [9.6.6 (release_9.6.6 @ /usr/share/emacs/30.0.50/lisp/org/)] Ihor Radchenko
2023-09-02 18:20   ` Leo Butler
2023-09-03  5:25     ` Vladimir Nikishkin

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).