From d2934b38a28a8593554af69622be5b11bc13406d Mon Sep 17 00:00:00 2001 From: Leo Butler 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