Provide a uniform way to inform users about missing third-party packages

* lisp/org-macs.el (org-require-package): New macro trying to load a
library and displaying custom error message or warning on failure.
The actual package (not library) name can be provided as optional
argument.

* lisp/ob-R.el (org-babel-R-initiate-session):
* lisp/ob-clojure.el (ob-clojure-eval-with-inf-clojure):
(ob-clojure-eval-with-cider):
(ob-clojure-eval-with-slime):
* lisp/ob-forth.el (org-babel-forth-session-execute):
* lisp/ob-gnuplot.el (org-babel-execute:gnuplot):
(org-babel-gnuplot-initiate-session):
* lisp/ob-haskell.el (org-babel-interpret-haskell):
(org-babel-haskell-initiate-session):
* lisp/ob-js.el (org-babel-execute:js):
(org-babel-js-initiate-session):
* lisp/ob-julia.el (org-babel-julia-initiate-session):
* lisp/ob-lisp.el (org-babel-execute:lisp):
* lisp/ob-ocaml.el (org-babel-prep-session:ocaml):
* lisp/ob-octave.el (org-babel-octave-initiate-session):
* lisp/ob-processing.el (org-babel-processing-view-sketch):
* lisp/ob-ruby.el (org-babel-execute:ruby):
(org-babel-ruby-initiate-session):
* lisp/ol-bbdb.el (org-bbdb-open):
(org-bbdb-complete-link):
(org-bbdb-anniv-export-ical):
* lisp/org-agenda.el:
* lisp/org-plot.el (org-plot/gnuplot):
* lisp/org.el:
* lisp/ox-ascii.el (org-ascii-table):
* lisp/ox-html.el (org-html-htmlize-generate-css):
* lisp/ox-org.el: Use the new macro.

* lisp/oc-csl.el: Add FIXME. oc-csl uses a custom function doing
similar job.

* lisp/ob-js.el (org-babel-js-initiate-session): Add FIXME noting that
the third-party package is outdated.
This commit is contained in:
Ihor Radchenko 2023-01-23 18:06:46 +03:00
parent 18a146a9d5
commit fe92a3cedb
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
21 changed files with 48 additions and 39 deletions

View File

@ -276,7 +276,7 @@ This function is called by `org-babel-execute-src-block'."
(when (get-buffer session)
;; Session buffer exists, but with dead process
(set-buffer session))
(require 'ess) (R)
(org-require-package 'ess "ESS") (R)
(let ((R-proc (get-process (or ess-local-process-name
ess-current-process-name))))
(while (process-get R-proc 'callbacks)

View File

@ -186,8 +186,7 @@ or set the `:backend' header argument"))))
(defvar inf-clojure-comint-prompt-regexp)
(defun ob-clojure-eval-with-inf-clojure (expanded params)
"Evaluate EXPANDED code block with PARAMS using inf-clojure."
(condition-case nil (require 'inf-clojure)
(user-error "inf-clojure not available"))
(org-require-package 'inf-clojure)
;; Maybe initiate the inf-clojure session
(unless (and inf-clojure-buffer
(buffer-live-p (get-buffer inf-clojure-buffer)))
@ -228,8 +227,7 @@ or set the `:backend' header argument"))))
(defun ob-clojure-eval-with-cider (expanded params)
"Evaluate EXPANDED code block with PARAMS using cider."
(condition-case nil (require 'cider)
(user-error "cider not available"))
(org-require-package 'cider "Cider")
(let ((connection (cider-current-connection (cdr (assq :target params))))
(result-params (cdr (assq :result-params params)))
result0)
@ -256,8 +254,7 @@ or set the `:backend' header argument"))))
(defun ob-clojure-eval-with-slime (expanded params)
"Evaluate EXPANDED code block with PARAMS using slime."
(condition-case nil (require 'slime)
(user-error "slime not available"))
(org-require-package 'slime "SLIME")
(with-temp-buffer
(insert expanded)
(slime-eval

View File

@ -55,7 +55,7 @@ This function is called by `org-babel-execute-src-block'."
(car (last all-results))))))
(defun org-babel-forth-session-execute (body params)
(require 'forth-mode)
(org-require-package 'forth-mode)
(let ((proc (forth-proc))
(rx " \\(\n:\\|compiled\n\\|ok\n\\)")
(result-start))

View File

@ -198,7 +198,7 @@ code."
(defun org-babel-execute:gnuplot (body params)
"Execute a block of Gnuplot code.
This function is called by `org-babel-execute-src-block'."
(require 'gnuplot)
(org-require-package 'gnuplot)
(let ((session (cdr (assq :session params)))
(result-type (cdr (assq :results params)))
(body (org-babel-expand-body:gnuplot body params))
@ -262,7 +262,7 @@ This function is called by `org-babel-execute-src-block'."
If there is not a current inferior-process-buffer in SESSION
then create one. Return the initialized session. The current
`gnuplot-mode' doesn't provide support for multiple sessions."
(require 'gnuplot)
(org-require-package 'gnuplot)
(unless (string= session "none")
(save-window-excursion
(gnuplot-send-string-to-gnuplot "" "line")

View File

@ -122,7 +122,7 @@ a parameter, such as \"ghc -v\"."
(cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))))
(defun org-babel-interpret-haskell (body params)
(require 'inf-haskell)
(org-require-package 'inf-haskell "haskell-mode")
(add-hook 'inferior-haskell-hook
(lambda ()
(setq-local comint-prompt-regexp
@ -167,7 +167,7 @@ a parameter, such as \"ghc -v\"."
"Initiate a haskell session.
If there is not a current inferior-process-buffer in SESSION
then create one. Return the initialized session."
(require 'inf-haskell)
(org-require-package 'inf-haskell "haskell-mode")
(or (get-buffer "*haskell*")
(save-window-excursion (run-haskell) (sleep-for 0.25) (current-buffer))))

View File

@ -96,7 +96,7 @@ This function is called by `org-babel-execute-src-block'."
;; Indium Node REPL. Separate case because Indium
;; REPL is not inherited from Comint mode.
((string= session "*JS REPL*")
(require 'indium-repl)
(org-require-package 'indium-repl "indium")
(unless (get-buffer session)
(indium-run-node org-babel-js-cmd))
(indium-eval full-body))
@ -168,7 +168,7 @@ Return the initialized session."
((string= session "none")
(warn "Session evaluation of ob-js is not supported"))
((string= "*skewer-repl*" session)
(require 'skewer-repl)
(org-require-package 'skewer-repl "skewer-mode")
(let ((session-buffer (get-buffer "*skewer-repl*")))
(if (and session-buffer
(org-babel-comint-buffer-livep (get-buffer session-buffer))
@ -180,7 +180,7 @@ Return the initialized session."
(skewer-repl)
session-buffer)))
((string= "*Javascript REPL*" session)
(require 'js-comint)
(org-require-package 'js-comint)
(let ((session-buffer "*Javascript REPL*"))
(if (and (org-babel-comint-buffer-livep (get-buffer session-buffer))
(comint-check-proc session-buffer))
@ -189,7 +189,9 @@ Return the initialized session."
(sit-for .5)
session-buffer)))
((string= "mozrepl" org-babel-js-cmd)
(require 'moz)
;; FIXME: According to https://github.com/bard/mozrepl, this REPL
;; is outdated and does not work for Firefox >54.
(org-require-package 'moz "mozrepl")
(let ((session-buffer (save-window-excursion
(run-mozilla nil)
(rename-buffer session)

View File

@ -196,7 +196,8 @@ end"
(when (get-buffer session)
;; Session buffer exists, but with dead process
(set-buffer session))
(require 'ess) (set-buffer (julia))
(org-require-package 'ess "ESS")
(set-buffer (julia))
(rename-buffer
(if (bufferp session)
(buffer-name session)

View File

@ -90,9 +90,9 @@ current directory string."
"Execute a block of Common Lisp code with Babel.
BODY is the contents of the block, as a string. PARAMS is
a property list containing the parameters of the block."
(require (pcase org-babel-lisp-eval-fn
(`slime-eval 'slime)
(`sly-eval 'sly)))
(pcase org-babel-lisp-eval-fn
(`slime-eval (org-require-package 'slime "SLIME"))
(`sly-eval (org-require-package 'sly "SLY")))
(org-babel-reassemble-table
(let ((result
(funcall (if (member "output" (cdr (assq :result-params params)))

View File

@ -109,7 +109,7 @@
(defvar tuareg-interactive-buffer-name)
(defun org-babel-prep-session:ocaml (session _params)
"Prepare SESSION according to the header arguments in PARAMS."
(require 'tuareg)
(org-require-package 'tuareg)
(let ((tuareg-interactive-buffer-name (if (and (not (string= session "none"))
(not (string= session "default"))
(stringp session))

View File

@ -154,8 +154,10 @@ create. Return the initialized session."
"Create an octave inferior process buffer.
If there is not a current inferior-process-buffer in SESSION then
create. Return the initialized session."
(if matlabp (require 'matlab) (or (require 'octave-inf nil 'noerror)
(require 'octave)))
(if matlabp
(org-require-package 'matlab "matlab-mode")
(or (require 'octave-inf nil 'noerror)
(require 'octave)))
(unless (string= session "none")
(let ((session (or session
(if matlabp "*Inferior Matlab*" "*Inferior Octave*"))))

View File

@ -78,7 +78,7 @@
(defun org-babel-processing-view-sketch ()
"Show the sketch of the Processing block under point in an external viewer."
(interactive)
(require 'processing-mode)
(org-require-package 'processing-mode)
(let ((info (org-babel-get-src-block-info)))
(if (string= (nth 0 info) "processing")
(let* ((body (nth 1 info))

View File

@ -86,7 +86,7 @@ This function is called by `org-babel-execute-src-block'."
body params (org-babel-variable-assignments:ruby params)))
(result (if (member "xmp" result-params)
(with-temp-buffer
(require 'rcodetools)
(org-require-package 'rcodetools "rcodetools (gem package)")
(insert full-body)
(xmp (cdr (assq :xmp-option params)))
(buffer-string))
@ -161,7 +161,7 @@ Emacs-lisp table, otherwise return the results as a string."
If there is not a current inferior-process-buffer in SESSION
then create one. Return the initialized session."
(unless (string= session "none")
(require 'inf-ruby)
(org-require-package 'inf-ruby)
(let* ((command (cdr (or (assq :ruby params)
(assoc inf-ruby-default-implementation
inf-ruby-implementations))))

View File

@ -417,6 +417,7 @@ Label is in match group 1.")
;;; Internal functions
;; FIXME: We use `org-require-package' in other places.
(defun org-cite-csl--barf-without-citeproc ()
"Raise an error if Citeproc library is not loaded."
(unless (featurep 'citeproc)

View File

@ -255,7 +255,7 @@ italicized, in all other cases it is left unchanged."
(defun org-bbdb-open (name _)
"Follow a BBDB link to NAME."
(require 'bbdb-com)
(org-require-package 'bbdb-com "bbdb")
(let ((inhibit-redisplay (not debug-on-error)))
(if (fboundp 'bbdb-name)
(org-bbdb-open-old name)
@ -369,7 +369,7 @@ This is used by Org to re-create the anniversary hash table."
"Extract anniversaries from BBDB for display in the agenda.
When called programmatically, this function expects the `date'
variable to be globally bound."
(require 'bbdb)
(org-require-package 'bbdb)
(require 'diary-lib)
(unless (hash-table-p org-bbdb-anniv-hash)
(setq org-bbdb-anniv-hash
@ -500,7 +500,7 @@ must be positive"))
(defun org-bbdb-complete-link ()
"Read a bbdb link with name completion."
(require 'bbdb-com)
(org-require-package 'bbdb-com "bbdb")
(let ((rec (bbdb-completing-read-record "Name: ")))
(concat "bbdb:"
(bbdb-record-name (if (listp rec)
@ -509,7 +509,7 @@ must be positive"))
(defun org-bbdb-anniv-export-ical ()
"Extract anniversaries from BBDB and convert them to icalendar format."
(require 'bbdb)
(org-require-package 'bbdb)
(require 'diary-lib)
(unless (hash-table-p org-bbdb-anniv-hash)
(setq org-bbdb-anniv-hash

View File

@ -3635,8 +3635,7 @@ the agenda to write."
(kill-buffer (current-buffer))
(message "Org file written to %s" file)))
((member extension '("html" "htm"))
(or (require 'htmlize nil t)
(error "Please install htmlize from https://github.com/hniksic/emacs-htmlize"))
(org-require-package 'htmlize)
(declare-function htmlize-buffer "htmlize" (&optional buffer))
(set-buffer (htmlize-buffer (current-buffer)))
(when org-agenda-export-html-style

View File

@ -107,6 +107,15 @@ Version mismatch is commonly encountered in the following situations:
;;; Macros
(defmacro org-require-package (symbol &optional name noerror)
"Try to load library SYMBOL and display error otherwise.
With optional parameter NAME, use NAME as package name instead of
SYMBOL. Show warning instead of error when NOERROR is non-nil."
`(unless (require ,symbol nil t)
(,(if noerror 'warn 'user-error)
"`%s' failed to load required package \"%s\""
this-command ,(or name symbol))))
(defmacro org-with-gensyms (symbols &rest body)
(declare (debug (sexp body)) (indent 1))
`(let ,(mapcar (lambda (s)

View File

@ -641,7 +641,7 @@ manner suitable for prepending to a user-specified script."
If not given options will be taken from the +PLOT
line directly before or after the table."
(interactive)
(require 'gnuplot)
(org-require-package 'gnuplot)
(save-window-excursion
(delete-other-windows)
(when (get-buffer "*gnuplot*") ; reset *gnuplot* if it already running

View File

@ -15449,7 +15449,7 @@ in Org mode.
\\{org-cdlatex-mode-map}"
:lighter " OCDL"
(when org-cdlatex-mode
(require 'cdlatex)
(org-require-package 'cdlatex)
(run-hooks 'cdlatex-mode-hook)
(cdlatex-compute-tables))
(unless org-cdlatex-texmathp-advice-is-done

View File

@ -1856,7 +1856,7 @@ contextual information."
(cond ((eq (org-element-property :type table) 'org) contents)
((and (plist-get info :ascii-table-use-ascii-art)
(eq (plist-get info :ascii-charset) 'utf-8)
(require 'ascii-art-to-unicode nil t))
(org-require-package 'ascii-art-to-unicode nil 'noerror))
(with-temp-buffer
(insert (org-remove-indentation
(org-element-property :value table)))

View File

@ -1823,8 +1823,7 @@ If you then set `org-html-htmlize-output-type' to `css', calls
to the function `org-html-htmlize-region-for-paste' will
produce code that uses these same face definitions."
(interactive)
(unless (require 'htmlize nil t)
(error "htmlize library missing. Aborting"))
(org-require-package 'htmlize)
(and (get-buffer "*html*") (kill-buffer "*html*"))
(with-temp-buffer
(let ((fl (face-list))

View File

@ -320,8 +320,7 @@ publishing directory.
Return output file name."
(org-publish-org-to 'org filename ".org" plist pub-dir)
(when (plist-get plist :htmlized-source)
(or (require 'htmlize nil t)
(error "Please install htmlize from https://github.com/hniksic/emacs-htmlize"))
(org-require-package 'htmlize)
(require 'ox-html)
(let* ((org-inhibit-startup t)
(htmlize-output-type 'css)