feat(org): add native :async support

ob-comint (included with org) added native :async support. It only works
for python currently, but unlike ob-async supports :session for :async
python blocks. In fact, it *requires* :session, so we still fall back to
ob-async in its absence, failing that, it ultimately falls back to
synchronous execution.
This commit is contained in:
Henrik Lissner 2021-07-28 15:00:35 -04:00
parent c48c01ebab
commit 7b274c7dbe

View file

@ -1,5 +1,8 @@
;;; lang/org/config.el -*- lexical-binding: t; -*- ;;; lang/org/config.el -*- lexical-binding: t; -*-
(defvar +org-babel-native-async-langs '(python)
"Languages that will use `ob-comint' instead of `ob-async' for `:async'.")
(defvar +org-babel-mode-alist (defvar +org-babel-mode-alist
'((c . C) '((c . C)
(cpp . C) (cpp . C)
@ -215,12 +218,16 @@ Is relative to `org-directory', unless it is absolute. Is used in Doom's default
(after! ob (after! ob
(add-to-list 'org-babel-default-lob-header-args '(:sync))) (add-to-list 'org-babel-default-lob-header-args '(:sync)))
(defadvice! +org-babel-disable-async-if-needed-a (orig-fn &optional fn arg info params) (defadvice! +org-babel-disable-async-maybe-a (orig-fn &optional fn arg info params)
"Disable ob-async when leaving it on would cause errors or issues. "Use ob-comint where supported, disable async altogether where it isn't.
Such as when exporting org documents or executing babel blocks with :session We have access to two async backends: ob-comint or ob-async, which have
parameters (which ob-async does not support), in which case this advice forces different requirements. This advice tries to pick the best option between them,
these blocks to run synchronously. falling back to synchronous execution otherwise. Without this advice, they die
with an error; terrible UX!
Note: ob-comint support will only kick in for languages listed in
`+org-babel-native-async-langs'.
Also adds support for a `:sync' parameter to override `:async'." Also adds support for a `:sync' parameter to override `:async'."
:around #'ob-async-org-babel-execute-src-block :around #'ob-async-org-babel-execute-src-block
@ -228,14 +235,24 @@ Also adds support for a `:sync' parameter to override `:async'."
(funcall orig-fn fn arg info params) (funcall orig-fn fn arg info params)
(let* ((info (or info (org-babel-get-src-block-info))) (let* ((info (or info (org-babel-get-src-block-info)))
(params (org-babel-merge-params (nth 2 info) params))) (params (org-babel-merge-params (nth 2 info) params)))
(cond ((or (assq :sync params) (if (or (assq :sync params)
(not (assq :async params)) (not (assq :async params))
(member (car info) ob-async-no-async-languages-alist)) (member (car info) ob-async-no-async-languages-alist)
(funcall fn arg info params)) ;; ob-comint requires a :session, ob-async does not, so fall
((not (member (cdr (assq :session params)) '("none" nil))) ;; back to ob-async if no :session is provided.
(message "Org babel :: :session is incompatible with :async. Executing synchronously!") (unless (member (alist-get :session params) '("none" nil))
nil) (unless (memq (let* ((lang (nth 0 info))
((funcall orig-fn fn arg info params)))))) (lang (cond ((symbolp lang) lang)
((stringp lang) (intern lang)))))
(or (alist-get lang +org-babel-mode-alist)
lang))
+org-babel-native-async-langs)
(message "Org babel: %s :session is incompatible with :async. Executing synchronously!"
(car info))
(sleep-for 0.2))
t))
(funcall fn arg info params)
(funcall orig-fn fn arg info params)))))
(defadvice! +org-fix-newline-and-indent-in-src-blocks-a (&optional indent _arg _interactive) (defadvice! +org-fix-newline-and-indent-in-src-blocks-a (&optional indent _arg _interactive)
"Mimic `newline-and-indent' in src blocks w/ lang-appropriate indentation." "Mimic `newline-and-indent' in src blocks w/ lang-appropriate indentation."