patch ob-core to allow function as header-args and add function for latex src blocks for tikz pictures

This commit is contained in:
2021-03-05 23:29:30 +01:00
parent e46e3678dd
commit 94d501f5a0
6 changed files with 3502 additions and 25 deletions

6
lisp/0patches/notes Normal file
View File

@@ -0,0 +1,6 @@
org-ob-core.el-add-ability-to-use-closures-as-default-header-args.patch
- patch -d "$HOME/.config/emacs/lisp/org" -p1 -i $HOME/.config/emacs/lisp/0patches/org-ob-core.el-add-ability-to-use-closures-as-default-header-args.patch
- patch -R -d "$HOME/.config/emacs/lisp/org" -p1 -i $HOME/.config/emacs/lisp/0patches/org-ob-core.el-add-ability-to-use-closures-as-default-header-args.patch
- https://orgmode.org/list/87ftflikkc.fsf@gmail.com/t/
- https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/msg00464.html
- https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/txtzi_PffIaG1.txt

View File

@@ -0,0 +1,102 @@
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 578622232..bef34d7c0 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -473,7 +473,35 @@ For the format of SAFE-LIST, see `org-babel-safe-header-args'."
(defvar org-babel-default-header-args
'((:session . "none") (:results . "replace") (:exports . "code")
(:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "no"))
- "Default arguments to use when evaluating a source block.")
+ "Default arguments to use when evaluating a source block.
+
+This is a list in which each element is an alist. Each key
+corresponds to a header argument, and each value to that header's
+value. The value can either be a string or a closure that
+evaluates to a string. The closure is evaluated when the source
+block is being evaluated (e.g. during execution or export), with
+point at the source block. It is not possible to use an
+arbitrary function symbol (e.g. 'some-func), since org uses
+lexical binding. To achieve the same functionality, call the
+function within a closure (e.g. (lambda () (some-func))).
+
+To understand how closures can be used as default header
+arguments, imagine you'd like to set the file name output of a
+latex source block to a sha1 of its contents. We could achieve
+this with:
+
+(defun org-src-sha ()
+ (let ((elem (org-element-at-point)))
+ (concat (sha1 (org-element-property :value elem)) \".svg\")))
+
+(setq org-babel-default-header-args:latex
+ `((:results . \"file link replace\")
+ (:file . (lambda () (org-src-sha)))))
+
+Because the closure is evaluated with point at the source block,
+the call to `org-element-at-point' above will always retrieve
+information about the current source block.")
+
(put 'org-babel-default-header-args 'safe-local-variable
(org-babel-header-args-safe-fn org-babel-safe-header-args))
@@ -584,6 +612,19 @@ the outer-most code block.")
(defvar *this*)
+(defun org-babel-eval-headers (headers)
+ "Compute header list set with HEADERS.
+
+Evaluate all header arguments set to functions prior to returning
+the list of header arguments."
+ (let ((lst nil))
+ (dolist (elem headers)
+ (if (and (cdr elem)
+ (functionp (cdr elem)))
+ (push `(,(car elem) . ,(funcall (cdr elem))) lst)
+ (push elem lst)))
+ lst))
+
(defun org-babel-get-src-block-info (&optional light datum)
"Extract information from a source block or inline source block.
@@ -2704,12 +2745,21 @@ parameters when merging lists."
results-exclusive-groups
results
(split-string
- (if (stringp value) value (eval value t))))))
+ (if (stringp value)
+ value
+ (if (functionp value)
+ (funcall value)
+ (eval value t)))))))
(`(:exports . ,value)
(setq exports (funcall merge
exports-exclusive-groups
exports
- (split-string (or value "")))))
+ (split-string (or
+ (if value
+ (if (functionp value)
+ (funcall value)
+ value)
+ ""))))))
;; Regular keywords: any value overwrites the previous one.
(_ (setq params (cons pair (assq-delete-all (car pair) params)))))))
;; Handle `:var' and clear out colnames and rownames for replaced
@@ -2724,14 +2774,14 @@ parameters when merging lists."
(cdr (assq param params))))
(setq params
(cl-remove-if (lambda (pair) (and (equal (car pair) param)
- (null (cdr pair))))
+ (null (cdr pair))))
params)))))
;; Handle other special keywords, which accept multiple values.
(setq params (nconc (list (cons :results (mapconcat #'identity results " "))
(cons :exports (mapconcat #'identity exports " ")))
params))
;; Return merged params.
- params))
+ (org-babel-eval-headers params)))
(defun org-babel-noweb-p (params context)
"Check if PARAMS require expansion in CONTEXT.

View File

@@ -17,23 +17,70 @@
;;; Code:
(require 'ox-latex)
(require 'ob-latex)
(require 'ob-gnuplot)
;;(setq org-babel-latex-htlatex "htlualatex")
;;(setq org-babel-latex-htlatex "htlatex")
;; (executable-find org-babel-latex-htlatex)
;; PROPERTY src block header arguments
;; PROPERTY src block header arguments https://orgmode.org/manual/Property-Syntax.html
;; https://orgmode.org/manual/Using-Header-Arguments.html
;; on src block C-c C-v I - org-babel-view-src-block-info this will eval as org backend
;; LaTeX
(add-to-list
'org-global-properties
'("header-args:latex" .
":headers (if (org-export-derived-backend-p org-export-current-backend 'latex) nil '(\"\\usepackage{xcolor}\\definecolor{color0}{HTML}{ffffff}\\definecolor{color1}{HTML}{0071bc} \\usepackage{pgfplots} \\tikzset{every path/.style={color=white}} \\usetikzlibrary{arrows.meta,calc}\\makeatletter\\tikzset{clip/.code={\\let\\tikz@mode=\\pgfutil@empty\\let\\tikz@preactions=\\pgfutil@empty\\let\\tikz@postactions=\\pgfutil@empty\\let\\tikz@options=\\pgfutil@empty\\tikz@addmode{\\tikz@mode@cliptrue}},}\\makeatother\") )"))
(add-to-list
'org-global-properties
'("header-args:latex+" .
":packages '(\"\\usepackage{xcolor}\\definecolor{color0}{HTML}{ffffff}\\definecolor{color1}{HTML}{0071bc} \\usepackage{svg} \\usepackage{tikz} \\usepackage{pgfplots} \\pgfplotsset{compat=newest, axis line style={white}, every axis label/.append style ={white}, every tick label/.append style={white},color0/.style={color=white}}\")"))
(setq org-babel-default-header-args:latex
`((:results . "latex")
(:exports . "results")
(:prologue . (lambda ()
(concat (by-backend
(latex gnuplot-init-light)
(article-latex gnuplot-init-light)
(t gnuplot-init-dark)))))
(:headers . (lambda ()
(if (org-export-derived-backend-p org-export-current-backend 'latex)
""
"
\\usepackage{xcolor}
\\definecolor{color0}{HTML}{ffffff}
\\definecolor{color1}{HTML}{0071bc}
\\usepackage{pgfplots}
\\usepgflibrary{shapes.geometric}
\\usetikzlibrary{
arrows.meta,
arrows,
calc,
positioning,
shapes.multipart,
decorations.pathmorphing,
backgrounds,
pgfplotsclickable,
shadows,
shadows.blur,
mindmap,
}
\\tikzset{every path/.style={color=white}}
\\makeatletter
\\tikzset{clip/.code={\\let\\tikz@mode=\\pgfutil@empty\\let\\tikz@preactions=\\pgfutil@empty\\let\\tikz@postactions=\\pgfutil@empty\\let\\tikz@options=\\pgfutil@empty\\tikz@addmode{\\tikz@mode@cliptrue}},}
\\makeatother")))
(:packages . "\\usepackage{xcolor}
\\definecolor{color0}{HTML}{ffffff}
\\definecolor{color1}{HTML}{0071bc}
\\usepackage{svg}
\\usepackage{tikz}
\\usepackage{pgfplots}
\\pgfplotsset{compat=newest, axis line style={white}, every axis label/.append style ={white}, every tick label/.append style={white},color0/.style={color=white}}"
)))
;; Gnuplot
(add-to-list
'org-global-properties
'("header-args:gnuplot" .
":prologue (by-backend (latex gnuplot-init-light) (t gnuplot-init-dark))"))
(setq org-babel-default-header-args:gnuplot
`((:results . "file")
(:exports . "results")
(:session)
(:prologue . (lambda ()
(concat (by-backend
(latex gnuplot-init-light)
(article-latex gnuplot-init-light)
(t gnuplot-init-dark)))))))
;; MACRO https://orgmode.org/manual/Macro-Replacement.html
(add-to-list

View File

@@ -472,7 +472,35 @@ For the format of SAFE-LIST, see `org-babel-safe-header-args'."
(defvar org-babel-default-header-args
'((:session . "none") (:results . "replace") (:exports . "code")
(:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "no"))
"Default arguments to use when evaluating a source block.")
"Default arguments to use when evaluating a source block.
This is a list in which each element is an alist. Each key
corresponds to a header argument, and each value to that header's
value. The value can either be a string or a closure that
evaluates to a string. The closure is evaluated when the source
block is being evaluated (e.g. during execution or export), with
point at the source block. It is not possible to use an
arbitrary function symbol (e.g. 'some-func), since org uses
lexical binding. To achieve the same functionality, call the
function within a closure (e.g. (lambda () (some-func))).
To understand how closures can be used as default header
arguments, imagine you'd like to set the file name output of a
latex source block to a sha1 of its contents. We could achieve
this with:
(defun org-src-sha ()
(let ((elem (org-element-at-point)))
(concat (sha1 (org-element-property :value elem)) \".svg\")))
(setq org-babel-default-header-args:latex
`((:results . \"file link replace\")
(:file . (lambda () (org-src-sha)))))
Because the closure is evaluated with point at the source block,
the call to `org-element-at-point' above will always retrieve
information about the current source block.")
(put 'org-babel-default-header-args 'safe-local-variable
(org-babel-header-args-safe-fn org-babel-safe-header-args))
@@ -583,6 +611,19 @@ the outer-most code block.")
(defvar *this*)
(defun org-babel-eval-headers (headers)
"Compute header list set with HEADERS.
Evaluate all header arguments set to functions prior to returning
the list of header arguments."
(let ((lst nil))
(dolist (elem headers)
(if (and (cdr elem)
(functionp (cdr elem)))
(push `(,(car elem) . ,(funcall (cdr elem))) lst)
(push elem lst)))
lst))
(defun org-babel-get-src-block-info (&optional light datum)
"Extract information from a source block or inline source block.
@@ -2707,12 +2748,21 @@ parameters when merging lists."
results-exclusive-groups
results
(split-string
(if (stringp value) value (eval value t))))))
(if (stringp value)
value
(if (functionp value)
(funcall value)
(eval value t)))))))
(`(:exports . ,value)
(setq exports (funcall merge
exports-exclusive-groups
exports
(split-string (or value "")))))
(split-string (or
(if value
(if (functionp value)
(funcall value)
value)
""))))))
;; Regular keywords: any value overwrites the previous one.
(_ (setq params (cons pair (assq-delete-all (car pair) params)))))))
;; Handle `:var' and clear out colnames and rownames for replaced
@@ -2727,14 +2777,14 @@ parameters when merging lists."
(cdr (assq param params))))
(setq params
(cl-remove-if (lambda (pair) (and (equal (car pair) param)
(null (cdr pair))))
(null (cdr pair))))
params)))))
;; Handle other special keywords, which accept multiple values.
(setq params (nconc (list (cons :results (mapconcat #'identity results " "))
(cons :exports (mapconcat #'identity exports " ")))
params))
;; Return merged params.
params))
(org-babel-eval-headers params)))
(defun org-babel-noweb-p (params context)
"Check if PARAMS require expansion in CONTEXT.

File diff suppressed because it is too large Load Diff

View File

@@ -481,7 +481,12 @@ Updating an old preamble.org should remove this warning."))
'((name . "obsolete")))
;; TODO: still useful?
(defun svg-fname (filename) (concat filename (by-backend (latex "_light") (t "_dark")) ".svg")))
(defun svg-fname (filename)
(concat filename (by-backend
(latex "_light")
(article-latex "_light")
(t "_dark"))
".svg")))
(use-package ob-gnuplot
:defer t
@@ -539,7 +544,7 @@ usage: #+HEADER: :file (gpl-file \"ledger-income\")
See also: http://www.gnuplot.info/docs_5.2/Gnuplot_5.2.pdf#section*.519
"
;;(concat filename (by-backend (latex ".tex") (t ".svg")) )
(concat filename (by-backend (latex ".tikz") (t ".svg")) )
(concat filename (by-backend (latex ".tikz") (article-latex ".tikz") (t ".svg")) )
;;(by-backend (latex "") (t (concat filename ".svg")))
)
(defun gpl-term (lsize osize)
@@ -555,11 +560,42 @@ usage: #+HEADER: :term (gpl-term \"15cm,12cm\" \"380,300\")
"
(concat
;;(by-backend (latex "epslatex size ") (t "svg size "))
(by-backend (latex "lua tikz size ") (t "svg size "))
(by-backend (latex lsize) (t osize))
(by-backend (latex " color") (t " mouse standalone background '#11000000'"))))
(by-backend (latex "lua tikz size ") (article-latex "lua tikz size ") (t "svg size "))
(by-backend (latex lsize) (article-latex lsize) (t osize))
(by-backend (latex " color") (article-latex " color") (t " mouse standalone background '#11000000'"))))
)
(use-package ob-latex
:defer t
:config
;; tikz config for own org export projects
(defun tpl-file (filename)
"\
FILENAME: the file name
returns: file name with extension for the org src header :file
- for LaTeX export it is set to: nil
- for other export it is set to: FILENAME.svg
usage: #+HEADER: :file (tpl-file \"ledger-income\")
"
(by-backend (latex nil)
(article-latex nil)
(t (concat filename ".svg"))))
(defun tpl-results ()
"\
TikZ
returns: result type for the org src header :results
- for LaTeX export it is set to: raw
- for other export it is set to: raw file
usage: #+HEADER: :results (tpl-results)
"
(by-backend (latex "raw")
(article-latex "raw")
(t "raw file"))))
(use-package ob-python
:defer t
:config
@@ -573,7 +609,7 @@ returns: file name varible with extension for the org src header :var
usage: #+HEADER: :var fname=(mpl-var \"ledger-income\")
"
(concat filename (by-backend (latex ".pgf") (t ".svg"))))
(concat filename (by-backend (latex ".pgf") (article-latex ".pgf") (t ".svg"))))
(defun mpl-prologue ()
"\
Matplotlib
@@ -584,7 +620,9 @@ returns: style settings for a org src python matplotlib code block
usage: #+HEADER: :prologue (mpl-prologue)
"
(by-backend (latex "") (t "import matplotlib.pyplot as plt;plt.style.use('dark_background');"))))
(by-backend (latex "")
(article-latex "")
(t "import matplotlib.pyplot as plt;plt.style.use('dark_background');"))))
(use-package ob-ditaa
:defer t