doomemacs/modules/lang/org/+babel.el
Henrik Lissner f6dc6ac74e
Refactor out map.el usage
After some profiling, it turns out map-put and map-delete are 5-7x
slower (more on Emacs 25) than delq, setf/alist-get and add-to-list for
small lists (under 250 items), which is exactly how I've been using
them.

The only caveat is alist-get's signature is different on Emacs 25, thus
a polyfill is necessary in core-lib.
2018-06-23 19:53:54 +02:00

97 lines
3.7 KiB
EmacsLisp

;;; lang/org/+babel.el -*- lexical-binding: t; -*-
(add-hook 'org-load-hook #'+org|init-babel)
(defvar +org-babel-mode-alist
'((cpp . C)
(C++ . C)
(D . C)
(sh . shell)
(bash . shell)
(matlab . octave))
"An alist that maps languages to babel libraries. This is necessary for babel
libraries (ob-*.el) that don't match the name of the language.")
(defvar +org-babel-load-functions ()
"A list of functions that are used to try to load the current executing src
block. They take one argument (the language specified in the src block, as
string). Stops at the first function to return non-nil.")
(defun +org|init-babel ()
(setq org-src-fontify-natively t ; make code pretty
org-src-preserve-indentation t ; use native major-mode indentation
org-src-tab-acts-natively t
org-src-window-setup 'current-window
org-confirm-babel-evaluate nil) ; you don't need my permission
(defun +org*babel-lazy-load-library (orig-fn info)
"Load babel libraries as needed when babel blocks are executed."
(when (funcall orig-fn info)
(let* ((lang (nth 0 info))
(lang (if (symbolp lang) lang (intern lang))))
(when (and (not (cdr (assq lang org-babel-load-languages)))
(or (run-hook-with-args-until-success '+org-babel-load-functions lang)
(require
(intern (format "ob-%s"
(or (cdr (assq lang +org-babel-mode-alist))
lang)))
nil t)))
(add-to-list 'org-babel-load-languages (cons lang t)))
t)))
(advice-add #'org-babel-confirm-evaluate :around #'+org*babel-lazy-load-library)
;; I prefer C-c C-c for confirming over the default C-c '
(define-key org-src-mode-map (kbd "C-c C-c") #'org-edit-src-exit)
;; In a recent update, `org-babel-get-header' was removed from org-mode, which
;; is something a fair number of babel plugins use. So until those plugins
;; update, this polyfill will do:
(defun org-babel-get-header (params key &optional others)
(cl-loop with fn = (if others #'not #'identity)
for p in params
if (funcall fn (eq (car p) key))
collect p)))
;;
;; Plugins
;;
(def-package! ob-ipython
:when (featurep! +ipython)
:defer t
:init
(defvar +ob-ipython-local-runtime-dir nil
"TODO")
(setq ob-ipython-resources-dir ".ob-ipython-resrc")
(defun +org|babel-load-ipython (lang)
(and (string-match-p "^jupyter-" (symbol-name lang))
(require 'ob-ipython nil t)))
(add-hook '+org-babel-load-functions #'+org|babel-load-ipython)
:config
(set-popup-rules!
'(("^\\*Org Src"
:side right :size 100 :height 0.6 :slot -1
:quit nil :select t)
("^\\*Python"
:slot 0 :side right :size 100
:select nil :quit nil :ttl nil)
("\\*ob-ipython.*"
:slot 2 :side right :size 100 :height 0.2
:select nil :quit nil :transient nil)
("\\*Python:.*"
:slot 0 :side right :size 100
:select nil :quit nil :transient nil)))
;; TODO Add more popup styles
;; advices for remote kernel and org-src-edit
(advice-add 'org-babel-edit-prep:ipython :override #'+org*org-babel-edit-prep:ipython)
(advice-add 'org-babel-ipython-initiate-session :override #'+org*org-babel-ipython-initiate-session)
(advice-add 'ob-ipython--create-repl :override #'+org*ob-ipython--create-repl)
(advice-add 'org-babel-execute:ipython :override #'+org*org-babel-execute:ipython)
;; retina resolution image hack
(when (eq window-system 'ns)
(advice-add 'ob-ipython--write-base64-string :around #'+org*ob-ipython--write-base64-string)))