emacs/lisp/org/ob-calc.el

138 lines
4.7 KiB
EmacsLisp
Raw Normal View History

;;; ob-calc.el --- Babel Functions for Calc -*- lexical-binding: t; -*-
2010-11-11 22:10:19 -06:00
2024-01-02 09:47:10 +08:00
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
2010-11-11 22:10:19 -06:00
;; Author: Eric Schulte
2021-09-29 18:48:59 -04:00
;; Maintainer: Tom Gillespie <tgbugs@gmail.com>
2010-11-11 22:10:19 -06:00
;; Keywords: literate programming, reproducible research
2022-11-29 23:05:53 -05:00
;; URL: https://orgmode.org
2010-11-11 22:10:19 -06:00
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
2010-11-11 22:10:19 -06:00
;;; Commentary:
;; Org-Babel support for evaluating calc code
;;; Code:
2022-11-29 23:05:53 -05:00
(require 'org-macs)
(org-assert-version)
2010-11-11 22:10:19 -06:00
(require 'ob)
2019-12-03 23:27:04 +01:00
(require 'org-macs)
2010-11-11 22:10:19 -06:00
(require 'calc)
(require 'calc-trail)
(require 'calc-store)
2010-11-11 22:10:19 -06:00
2012-01-03 18:27:21 +01:00
(declare-function calc-store-into "calc-store" (&optional var))
(declare-function calc-recall "calc-store" (&optional var))
(declare-function math-evaluate-expr "calc-ext" (x))
2010-11-11 22:10:19 -06:00
(defvar org-babel-default-header-args:calc nil
"Default arguments for evaluating a calc source block.")
2010-11-11 22:10:19 -06:00
2024-06-09 13:06:28 -04:00
(defun org-babel-expand-body:calc (body params)
"Expand BODY according to PARAMS, return the expanded body."
(let ((prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n")))))
2010-11-11 22:10:19 -06:00
Address some byte-compiler warnings. * lisp/org/ob-abc.el (org-babel-expand-body:abc): Use dolist. (org-babel-execute:abc): Fix regexp quoting. * lisp/org/ob-calc.el (org--var-syms): Rename from `var-syms'. * lisp/org/ob-lilypond.el (ly-compile-lilyfile): Remove redundant let-binding. * lisp/org/ob-table.el (sbe): Move debug declaration. * lisp/org/org-clock.el (org--msg-extra): Rename from `msg-extra'. * lisp/org/org.el (org-version): Avoid var name starting with _. (org-inhibit-startup, org-called-with-limited-levels) (org-link-search-inhibit-query, org-time-was-given) (org-end-time-was-given, org-def, org-defdecode, org-with-time): * lisp/org/org-colview.el (org-agenda-overriding-columns-format): * lisp/org/org-agenda.el (org-agenda-multi, org-depend-tag-blocked) (org-agenda-show-log-scoped): * lisp/org/ob-python.el (py-which-bufname, python-shell-buffer-name): * lisp/org/ob-haskell.el (org-export-copy-to-kill-ring): * lisp/org/ob-exp.el (org-link-search-inhibit-query): * lisp/org/ob-R.el (ess-eval-visibly-p): * lisp/org/ob-core.el (org-src-window-setup): Declare before use. (org-babel-expand-noweb-references): Remove unused `blocks-in-buffer'. * lisp/org/ox-odt.el (org-odt-hfy-face-to-css): * lisp/org/org-src.el (org-src-associate-babel-session, org-src-get-lang-mode): * lisp/org/org-bibtex.el (org-bibtex-get, org-bibtex-ask, org-bibtex) (org-bibtex-check): * lisp/org/ob-tangle.el (org-babel-tangle, org-babel-spec-to-string) (org-babel-tangle-single-block, org-babel-tangle-comment-links): * ob-table.el (sbe): * lisp/org/ob-sqlite.el (org-babel-sqlite-expand-vars): * lisp/org/ob-sql.el (org-babel-sql-expand-vars): * lisp/org/ob-shen.el (org-babel-execute:shen): * lisp/org/ob-sh.el (org-babel-execute:sh, org-babel-sh-evaluate): * lisp/org/ob-scala.el (org-babel-scala-evaluate): * lisp/org/ob-ruby.el (org-babel-ruby-table-or-string) (org-babel-ruby-evaluate): * ob-python.el (org-babel-python-table-or-string) (org-babel-python-evaluate-external-process) (org-babel-python-evaluate-session): * lisp/org/ob-picolisp.el (org-babel-execute:picolisp): * lisp/org/ob-perl.el (org-babel-perl-evaluate): * lisp/org/ob-maxima.el (org-babel-execute:maxima): * lisp/org/ob-lisp.el (org-babel-execute:lisp): * lisp/org/ob-java.el (org-babel-execute:java): * lisp/org/ob-io.el (org-babel-io-evaluate): * ob-haskell.el (org-babel-execute:haskell): * lisp/org/ob-fortran.el (org-babel-execute:fortran): * ob-exp.el (org-babel-exp-code): * lisp/org/ob-emacs-lisp.el (org-babel-execute:emacs-lisp): * lisp/org/ob-ditaa.el (org-babel-execute:ditaa): * ob-core.el (org-babel-execute-src-block, org-babel-sha1-hash) (org-babel-parse-header-arguments, org-babel-reassemble-table) (org-babel-goto-src-block-head, org-babel-mark-block) (org-babel-expand-noweb-references, org-babel-script-escape) (org-babel-process-file-name): * lisp/org/ob-clojure.el (org-babel-execute:clojure): * ob-calc.el (org-babel-execute:calc): * lisp/org/ob-awk.el (org-babel-execute:awk): * ob-abc.el (org-babel-execute:abc): * ob-R.el (org-babel-expand-body:R): * lisp/org/ob-C.el (org-babel-C-execute): Avoid deprecated ((lambda) ...).
2013-11-12 14:11:22 -05:00
(defvar org--var-syms) ; Dynamically scoped from org-babel-execute:calc
2010-11-11 22:10:19 -06:00
(defun org-babel-execute:calc (body params)
2024-06-09 13:06:28 -04:00
"Execute BODY of calc code with Babel using PARAMS."
2010-12-11 17:42:53 +01:00
(unless (get-buffer "*Calculator*")
(save-window-excursion (calc) (calc-quit)))
(let* ((vars (org-babel--get-vars params))
Address some byte-compiler warnings. * lisp/org/ob-abc.el (org-babel-expand-body:abc): Use dolist. (org-babel-execute:abc): Fix regexp quoting. * lisp/org/ob-calc.el (org--var-syms): Rename from `var-syms'. * lisp/org/ob-lilypond.el (ly-compile-lilyfile): Remove redundant let-binding. * lisp/org/ob-table.el (sbe): Move debug declaration. * lisp/org/org-clock.el (org--msg-extra): Rename from `msg-extra'. * lisp/org/org.el (org-version): Avoid var name starting with _. (org-inhibit-startup, org-called-with-limited-levels) (org-link-search-inhibit-query, org-time-was-given) (org-end-time-was-given, org-def, org-defdecode, org-with-time): * lisp/org/org-colview.el (org-agenda-overriding-columns-format): * lisp/org/org-agenda.el (org-agenda-multi, org-depend-tag-blocked) (org-agenda-show-log-scoped): * lisp/org/ob-python.el (py-which-bufname, python-shell-buffer-name): * lisp/org/ob-haskell.el (org-export-copy-to-kill-ring): * lisp/org/ob-exp.el (org-link-search-inhibit-query): * lisp/org/ob-R.el (ess-eval-visibly-p): * lisp/org/ob-core.el (org-src-window-setup): Declare before use. (org-babel-expand-noweb-references): Remove unused `blocks-in-buffer'. * lisp/org/ox-odt.el (org-odt-hfy-face-to-css): * lisp/org/org-src.el (org-src-associate-babel-session, org-src-get-lang-mode): * lisp/org/org-bibtex.el (org-bibtex-get, org-bibtex-ask, org-bibtex) (org-bibtex-check): * lisp/org/ob-tangle.el (org-babel-tangle, org-babel-spec-to-string) (org-babel-tangle-single-block, org-babel-tangle-comment-links): * ob-table.el (sbe): * lisp/org/ob-sqlite.el (org-babel-sqlite-expand-vars): * lisp/org/ob-sql.el (org-babel-sql-expand-vars): * lisp/org/ob-shen.el (org-babel-execute:shen): * lisp/org/ob-sh.el (org-babel-execute:sh, org-babel-sh-evaluate): * lisp/org/ob-scala.el (org-babel-scala-evaluate): * lisp/org/ob-ruby.el (org-babel-ruby-table-or-string) (org-babel-ruby-evaluate): * ob-python.el (org-babel-python-table-or-string) (org-babel-python-evaluate-external-process) (org-babel-python-evaluate-session): * lisp/org/ob-picolisp.el (org-babel-execute:picolisp): * lisp/org/ob-perl.el (org-babel-perl-evaluate): * lisp/org/ob-maxima.el (org-babel-execute:maxima): * lisp/org/ob-lisp.el (org-babel-execute:lisp): * lisp/org/ob-java.el (org-babel-execute:java): * lisp/org/ob-io.el (org-babel-io-evaluate): * ob-haskell.el (org-babel-execute:haskell): * lisp/org/ob-fortran.el (org-babel-execute:fortran): * ob-exp.el (org-babel-exp-code): * lisp/org/ob-emacs-lisp.el (org-babel-execute:emacs-lisp): * lisp/org/ob-ditaa.el (org-babel-execute:ditaa): * ob-core.el (org-babel-execute-src-block, org-babel-sha1-hash) (org-babel-parse-header-arguments, org-babel-reassemble-table) (org-babel-goto-src-block-head, org-babel-mark-block) (org-babel-expand-noweb-references, org-babel-script-escape) (org-babel-process-file-name): * lisp/org/ob-clojure.el (org-babel-execute:clojure): * ob-calc.el (org-babel-execute:calc): * lisp/org/ob-awk.el (org-babel-execute:awk): * ob-abc.el (org-babel-execute:abc): * ob-R.el (org-babel-expand-body:R): * lisp/org/ob-C.el (org-babel-C-execute): Avoid deprecated ((lambda) ...).
2013-11-12 14:11:22 -05:00
(org--var-syms (mapcar #'car vars))
(var-names (mapcar #'symbol-name org--var-syms)))
2010-12-11 17:42:53 +01:00
(mapc
(lambda (pair)
2024-06-09 13:06:28 -04:00
(let ((val (cdr pair)))
(calc-push-list
(list
(cond
;; For a vector, Calc follows the format (vec 1 2 3 ...) so
;; a matrix becomes (vec (vec 1 2 3) (vec 4 5 6) ...). See
;; the comments in "Arithmetic routines." section of
;; calc.el.
((listp val)
(cons 'vec
(if (null (cdr val))
(car val)
(mapcar (lambda (x) (if (listp x) (cons 'vec x) x))
val))))
((numberp val)
(math-read-number (number-to-string val)))
(t val)))))
2010-12-11 17:42:53 +01:00
(calc-store-into (car pair)))
vars)
(mapc
(lambda (line)
(when (> (length line) 0)
(cond
;; simple variable name
((member line var-names) (calc-recall (intern line)))
;; stack operation
((string= "'" (substring line 0 1))
(funcall (lookup-key calc-mode-map (substring line 1)) nil))
;; complex expression
(t
(calc-push-list
Address some byte-compiler warnings. * lisp/org/ob-abc.el (org-babel-expand-body:abc): Use dolist. (org-babel-execute:abc): Fix regexp quoting. * lisp/org/ob-calc.el (org--var-syms): Rename from `var-syms'. * lisp/org/ob-lilypond.el (ly-compile-lilyfile): Remove redundant let-binding. * lisp/org/ob-table.el (sbe): Move debug declaration. * lisp/org/org-clock.el (org--msg-extra): Rename from `msg-extra'. * lisp/org/org.el (org-version): Avoid var name starting with _. (org-inhibit-startup, org-called-with-limited-levels) (org-link-search-inhibit-query, org-time-was-given) (org-end-time-was-given, org-def, org-defdecode, org-with-time): * lisp/org/org-colview.el (org-agenda-overriding-columns-format): * lisp/org/org-agenda.el (org-agenda-multi, org-depend-tag-blocked) (org-agenda-show-log-scoped): * lisp/org/ob-python.el (py-which-bufname, python-shell-buffer-name): * lisp/org/ob-haskell.el (org-export-copy-to-kill-ring): * lisp/org/ob-exp.el (org-link-search-inhibit-query): * lisp/org/ob-R.el (ess-eval-visibly-p): * lisp/org/ob-core.el (org-src-window-setup): Declare before use. (org-babel-expand-noweb-references): Remove unused `blocks-in-buffer'. * lisp/org/ox-odt.el (org-odt-hfy-face-to-css): * lisp/org/org-src.el (org-src-associate-babel-session, org-src-get-lang-mode): * lisp/org/org-bibtex.el (org-bibtex-get, org-bibtex-ask, org-bibtex) (org-bibtex-check): * lisp/org/ob-tangle.el (org-babel-tangle, org-babel-spec-to-string) (org-babel-tangle-single-block, org-babel-tangle-comment-links): * ob-table.el (sbe): * lisp/org/ob-sqlite.el (org-babel-sqlite-expand-vars): * lisp/org/ob-sql.el (org-babel-sql-expand-vars): * lisp/org/ob-shen.el (org-babel-execute:shen): * lisp/org/ob-sh.el (org-babel-execute:sh, org-babel-sh-evaluate): * lisp/org/ob-scala.el (org-babel-scala-evaluate): * lisp/org/ob-ruby.el (org-babel-ruby-table-or-string) (org-babel-ruby-evaluate): * ob-python.el (org-babel-python-table-or-string) (org-babel-python-evaluate-external-process) (org-babel-python-evaluate-session): * lisp/org/ob-picolisp.el (org-babel-execute:picolisp): * lisp/org/ob-perl.el (org-babel-perl-evaluate): * lisp/org/ob-maxima.el (org-babel-execute:maxima): * lisp/org/ob-lisp.el (org-babel-execute:lisp): * lisp/org/ob-java.el (org-babel-execute:java): * lisp/org/ob-io.el (org-babel-io-evaluate): * ob-haskell.el (org-babel-execute:haskell): * lisp/org/ob-fortran.el (org-babel-execute:fortran): * ob-exp.el (org-babel-exp-code): * lisp/org/ob-emacs-lisp.el (org-babel-execute:emacs-lisp): * lisp/org/ob-ditaa.el (org-babel-execute:ditaa): * ob-core.el (org-babel-execute-src-block, org-babel-sha1-hash) (org-babel-parse-header-arguments, org-babel-reassemble-table) (org-babel-goto-src-block-head, org-babel-mark-block) (org-babel-expand-noweb-references, org-babel-script-escape) (org-babel-process-file-name): * lisp/org/ob-clojure.el (org-babel-execute:clojure): * ob-calc.el (org-babel-execute:calc): * lisp/org/ob-awk.el (org-babel-execute:awk): * ob-abc.el (org-babel-execute:abc): * ob-R.el (org-babel-expand-body:R): * lisp/org/ob-C.el (org-babel-C-execute): Avoid deprecated ((lambda) ...).
2013-11-12 14:11:22 -05:00
(list (let ((res (calc-eval line)))
(cond
((numberp res) res)
((math-read-number res) (math-read-number res))
((listp res) (error "Calc error \"%s\" on input \"%s\""
(cadr res) line))
(t (replace-regexp-in-string
"'" ""
(calc-eval
(math-evaluate-expr
;; resolve user variables, calc built in
;; variables are handled automatically
;; upstream by calc
(mapcar #'org-babel-calc-maybe-resolve-var
;; parse line into calc objects
(car (math-read-exprs line)))))))))
))))))
(mapcar #'org-trim
2010-12-11 17:42:53 +01:00
(split-string (org-babel-expand-body:calc body params) "[\n\r]"))))
2010-11-11 22:10:19 -06:00
(save-excursion
; Simplify (with-current-buffer (get-buffer ...) ...) There's no need to call 'get-buffer', since 'with-current-buffer' does that internally. * lisp/calendar/todo-mode.el (todo-merge-category): * lisp/comint.el (comint-dynamic-list-completions): * lisp/emacs-lisp/checkdoc.el (checkdoc-error): * lisp/emacs-lisp/debug.el (debug, debugger-record-expression): * lisp/emacs-lisp/eieio-opt.el (eieio-browse): * lisp/emacs-lisp/re-builder.el (reb-restart-font-lock): * lisp/erc/erc-dcc.el (erc-dcc-do-LIST-command): * lisp/eshell/em-unix.el (eshell-poor-mans-grep): * lisp/gnus/gnus-group.el (gnus-add-mark): * lisp/net/eww.el (eww-next-bookmark, eww-previous-bookmark): * lisp/net/sieve.el (sieve-upload): * lisp/net/tramp-cmds.el (tramp-cleanup-some-buffers): * lisp/obsolete/quickurl.el (quickurl-list-populate-buffer): * lisp/org/ob-calc.el: (org-babel-execute:calc): * lisp/org/org-agenda.el (org-agenda-use-sticky-p): * lisp/pcomplete.el (pcomplete-show-completions): * lisp/progmodes/bug-reference.el (bug-reference--try-setup-gnus-article): * lisp/progmodes/idlw-help.el (idlwave-highlight-linked-completions): * lisp/progmodes/verilog-mode.el (verilog-preprocess): * lisp/replace.el (occur-1): * lisp/term.el (term-dynamic-list-completions): * lisp/time.el (world-clock-update): * lisp/url/url-cache.el (url-store-in-cache): * lisp/vc/vc-cvs.el (vc-cvs-merge, vc-cvs-merge-news): * lisp/vc/vc-rcs.el (vc-rcs-system-release): * lisp/vc/vc-svn.el (vc-svn-merge, vc-svn-merge-news): * test/lisp/calendar/icalendar-tests.el (icalendar-tests--get-error-string-for-export): * test/lisp/erc/erc-dcc-tests.el (pcomplete/erc-mode/DCC--get-1flag) (pcomplete/erc-mode/DCC--get-2flags) (pcomplete/erc-mode/DCC--get-2flags-reverse): * test/lisp/erc/erc-networks-tests.el (erc-networks--rename-server-buffer--existing--noreuse): * test/lisp/erc/erc-scenarios-services-misc.el (erc-scenarios-services-misc--reconnect-retry-nick): * test/lisp/erc/erc-tests.el (erc--refresh-prompt): Replace (with-current-buffer (get-buffer ...) ...) with (with-current-buffer ...).
2024-03-12 00:21:06 +00:00
(with-current-buffer "*Calculator*"
(prog1
2021-09-29 18:48:59 -04:00
(calc-eval (calc-top 1))
(calc-pop 1)))))
2010-11-11 22:10:19 -06:00
(defun org-babel-calc-maybe-resolve-var (el)
2024-06-09 13:06:28 -04:00
"Resolve user variables in EL.
EL is taken from the output of `math-read-exprs'."
(if (consp el)
(if (and (eq 'var (car el)) (member (cadr el) org--var-syms))
(progn
(calc-recall (cadr el))
(prog1 (calc-top 1)
(calc-pop 1)))
(mapcar #'org-babel-calc-maybe-resolve-var el))
el))
2010-11-11 22:10:19 -06:00
(provide 'ob-calc)
;;; ob-calc.el ends here