commit | author | age
|
76bbd0
|
1 |
;;; ob-core.el --- Working with Code Blocks -*- lexical-binding: t; -*- |
C |
2 |
|
|
3 |
;; Copyright (C) 2009-2018 Free Software Foundation, Inc. |
|
4 |
|
|
5 |
;; Authors: Eric Schulte |
|
6 |
;; Dan Davison |
|
7 |
;; Keywords: literate programming, reproducible research |
|
8 |
;; Homepage: https://orgmode.org |
|
9 |
|
|
10 |
;; This file is part of GNU Emacs. |
|
11 |
|
|
12 |
;; GNU Emacs is free software: you can redistribute it and/or modify |
|
13 |
;; it under the terms of the GNU General Public License as published by |
|
14 |
;; the Free Software Foundation, either version 3 of the License, or |
|
15 |
;; (at your option) any later version. |
|
16 |
|
|
17 |
;; GNU Emacs is distributed in the hope that it will be useful, |
|
18 |
;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
19 |
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
20 |
;; GNU General Public License for more details. |
|
21 |
|
|
22 |
;; You should have received a copy of the GNU General Public License |
|
23 |
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. |
|
24 |
|
|
25 |
;;; Code: |
|
26 |
(require 'cl-lib) |
|
27 |
(require 'ob-eval) |
|
28 |
(require 'org-macs) |
|
29 |
(require 'org-compat) |
|
30 |
|
|
31 |
(defconst org-babel-exeext |
|
32 |
(if (memq system-type '(windows-nt cygwin)) |
|
33 |
".exe" |
|
34 |
nil)) |
|
35 |
|
|
36 |
(defvar org-babel-library-of-babel) |
|
37 |
(defvar org-edit-src-content-indentation) |
|
38 |
(defvar org-src-lang-modes) |
|
39 |
(defvar org-src-preserve-indentation) |
|
40 |
|
|
41 |
(declare-function org-at-item-p "org-list" ()) |
|
42 |
(declare-function org-at-table-p "org" (&optional table-type)) |
|
43 |
(declare-function org-babel-lob-execute-maybe "ob-lob" ()) |
|
44 |
(declare-function org-babel-ref-goto-headline-id "ob-ref" (id)) |
|
45 |
(declare-function org-babel-ref-headline-body "ob-ref" ()) |
|
46 |
(declare-function org-babel-ref-parse "ob-ref" (assignment)) |
|
47 |
(declare-function org-babel-ref-resolve "ob-ref" (ref)) |
|
48 |
(declare-function org-babel-ref-split-args "ob-ref" (arg-string)) |
|
49 |
(declare-function org-babel-tangle-comment-links "ob-tangle" (&optional info)) |
|
50 |
(declare-function org-completing-read "org" (&rest args)) |
|
51 |
(declare-function org-current-level "org" ()) |
|
52 |
(declare-function org-cycle "org" (&optional arg)) |
|
53 |
(declare-function org-do-remove-indentation "org" (&optional n)) |
|
54 |
(declare-function org-edit-src-code "org-src" (&optional code edit-buffer-name)) |
|
55 |
(declare-function org-edit-src-exit "org-src" ()) |
|
56 |
(declare-function org-element-at-point "org-element" ()) |
|
57 |
(declare-function org-element-context "org-element" (&optional element)) |
|
58 |
(declare-function org-element-normalize-string "org-element" (s)) |
|
59 |
(declare-function org-element-property "org-element" (property element)) |
|
60 |
(declare-function org-element-type "org-element" (element)) |
|
61 |
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil)) |
|
62 |
(declare-function org-escape-code-in-region "org-src" (beg end)) |
|
63 |
(declare-function org-get-indentation "org" (&optional line)) |
|
64 |
(declare-function org-get-indentation "org" (&optional line)) |
|
65 |
(declare-function org-in-regexp "org" (regexp &optional nlines visually)) |
|
66 |
(declare-function org-indent-line "org" ()) |
|
67 |
(declare-function org-list-get-list-end "org-list" (item struct prevs)) |
|
68 |
(declare-function org-list-prevs-alist "org-list" (struct)) |
|
69 |
(declare-function org-list-struct "org-list" ()) |
|
70 |
(declare-function org-list-to-generic "org-list" (LIST PARAMS)) |
|
71 |
(declare-function org-list-to-lisp "org-list" (&optional delete)) |
|
72 |
(declare-function org-macro-escape-arguments "org-macro" (&rest args)) |
|
73 |
(declare-function org-make-options-regexp "org" (kwds &optional extra)) |
|
74 |
(declare-function org-mark-ring-push "org" (&optional pos buffer)) |
|
75 |
(declare-function org-narrow-to-subtree "org" ()) |
|
76 |
(declare-function org-next-block "org" (arg &optional backward block-regexp)) |
|
77 |
(declare-function org-open-at-point "org" (&optional in-emacs reference-buffer)) |
|
78 |
(declare-function org-outline-overlay-data "org" (&optional use-markers)) |
|
79 |
(declare-function org-previous-block "org" (arg &optional block-regexp)) |
|
80 |
(declare-function org-remove-indentation "org" (code &optional n)) |
|
81 |
(declare-function org-reverse-string "org" (string)) |
|
82 |
(declare-function org-set-outline-overlay-data "org" (data)) |
|
83 |
(declare-function org-show-context "org" (&optional key)) |
|
84 |
(declare-function org-src-coderef-format "org-src" (&optional element)) |
|
85 |
(declare-function org-src-coderef-regexp "org-src" (fmt &optional label)) |
|
86 |
(declare-function org-table-align "org-table" ()) |
|
87 |
(declare-function org-table-end "org-table" (&optional table-type)) |
|
88 |
(declare-function org-table-import "org-table" (file arg)) |
|
89 |
(declare-function org-table-to-lisp "org-table" (&optional txt)) |
|
90 |
(declare-function org-trim "org" (s &optional keep-lead)) |
|
91 |
(declare-function org-unescape-code-in-string "org-src" (s)) |
|
92 |
(declare-function org-uniquify "org" (list)) |
|
93 |
(declare-function orgtbl-to-generic "org-table" (table params)) |
|
94 |
(declare-function orgtbl-to-orgtbl "org-table" (table params)) |
|
95 |
(declare-function outline-show-all "outline" ()) |
|
96 |
(declare-function tramp-compat-make-temp-file "tramp-compat" (filename &optional dir-flag)) |
|
97 |
|
|
98 |
(defgroup org-babel nil |
|
99 |
"Code block evaluation and management in `org-mode' documents." |
|
100 |
:tag "Babel" |
|
101 |
:group 'org) |
|
102 |
|
|
103 |
(defcustom org-confirm-babel-evaluate t |
|
104 |
"Confirm before evaluation. |
|
105 |
\\<org-mode-map>\ |
|
106 |
Require confirmation before interactively evaluating code |
|
107 |
blocks in Org buffers. The default value of this variable is t, |
|
108 |
meaning confirmation is required for any code block evaluation. |
|
109 |
This variable can be set to nil to inhibit any future |
|
110 |
confirmation requests. This variable can also be set to a |
|
111 |
function which takes two arguments the language of the code block |
|
112 |
and the body of the code block. Such a function should then |
|
113 |
return a non-nil value if the user should be prompted for |
|
114 |
execution or nil if no prompt is required. |
|
115 |
|
|
116 |
Warning: Disabling confirmation may result in accidental |
|
117 |
evaluation of potentially harmful code. It may be advisable |
|
118 |
remove code block execution from `\\[org-ctrl-c-ctrl-c]' \ |
|
119 |
as further protection |
|
120 |
against accidental code block evaluation. The |
|
121 |
`org-babel-no-eval-on-ctrl-c-ctrl-c' variable can be used to |
|
122 |
remove code block execution from the `\\[org-ctrl-c-ctrl-c]' keybinding." |
|
123 |
:group 'org-babel |
|
124 |
:version "24.1" |
|
125 |
:type '(choice boolean function)) |
|
126 |
;; don't allow this variable to be changed through file settings |
|
127 |
(put 'org-confirm-babel-evaluate 'safe-local-variable (lambda (x) (eq x t))) |
|
128 |
|
|
129 |
(defcustom org-babel-no-eval-on-ctrl-c-ctrl-c nil |
|
130 |
"\\<org-mode-map>\ |
|
131 |
Remove code block evaluation from the `\\[org-ctrl-c-ctrl-c]' key binding." |
|
132 |
:group 'org-babel |
|
133 |
:version "24.1" |
|
134 |
:type 'boolean) |
|
135 |
|
|
136 |
(defcustom org-babel-results-keyword "RESULTS" |
|
137 |
"Keyword used to name results generated by code blocks. |
|
138 |
It should be \"RESULTS\". However any capitalization may be |
|
139 |
used." |
|
140 |
:group 'org-babel |
|
141 |
:version "24.4" |
|
142 |
:package-version '(Org . "8.0") |
|
143 |
:type 'string |
|
144 |
:safe (lambda (v) |
|
145 |
(and (stringp v) |
|
146 |
(eq (compare-strings "RESULTS" nil nil v nil nil t) |
|
147 |
t)))) |
|
148 |
|
|
149 |
(defcustom org-babel-noweb-wrap-start "<<" |
|
150 |
"String used to begin a noweb reference in a code block. |
|
151 |
See also `org-babel-noweb-wrap-end'." |
|
152 |
:group 'org-babel |
|
153 |
:type 'string) |
|
154 |
|
|
155 |
(defcustom org-babel-noweb-wrap-end ">>" |
|
156 |
"String used to end a noweb reference in a code block. |
|
157 |
See also `org-babel-noweb-wrap-start'." |
|
158 |
:group 'org-babel |
|
159 |
:type 'string) |
|
160 |
|
|
161 |
(defcustom org-babel-inline-result-wrap "=%s=" |
|
162 |
"Format string used to wrap inline results. |
|
163 |
This string must include a \"%s\" which will be replaced by the results." |
|
164 |
:group 'org-babel |
|
165 |
:type 'string) |
|
166 |
(put 'org-babel-inline-result-wrap |
|
167 |
'safe-local-variable |
|
168 |
(lambda (value) |
|
169 |
(and (stringp value) |
|
170 |
(string-match-p "%s" value)))) |
|
171 |
|
|
172 |
(defcustom org-babel-hash-show-time nil |
|
173 |
"Non-nil means show the time the code block was evaluated in the result hash." |
|
174 |
:group 'org-babel |
|
175 |
:type 'boolean |
|
176 |
:version "26.1" |
|
177 |
:package-version '(Org . "9.0") |
|
178 |
:safe #'booleanp) |
|
179 |
|
|
180 |
(defcustom org-babel-uppercase-example-markers nil |
|
181 |
"When non-nil, begin/end example markers will be inserted in upper case." |
|
182 |
:group 'org-babel |
|
183 |
:type 'boolean |
|
184 |
:version "26.1" |
|
185 |
:package-version '(Org . "9.1") |
|
186 |
:safe #'booleanp) |
|
187 |
|
|
188 |
(defun org-babel-noweb-wrap (&optional regexp) |
|
189 |
(concat org-babel-noweb-wrap-start |
|
190 |
(or regexp "\\([^ \t\n].+?[^ \t]\\|[^ \t\n]\\)") |
|
191 |
org-babel-noweb-wrap-end)) |
|
192 |
|
|
193 |
(defvar org-babel-src-name-regexp |
|
194 |
"^[ \t]*#\\+name:[ \t]*" |
|
195 |
"Regular expression used to match a source name line.") |
|
196 |
|
|
197 |
(defvar org-babel-multi-line-header-regexp |
|
198 |
"^[ \t]*#\\+headers?:[ \t]*\\([^\n]*\\)$" |
|
199 |
"Regular expression used to match multi-line header arguments.") |
|
200 |
|
|
201 |
(defvar org-babel-src-block-regexp |
|
202 |
(concat |
|
203 |
;; (1) indentation (2) lang |
|
204 |
"^\\([ \t]*\\)#\\+begin_src[ \t]+\\([^ \f\t\n\r\v]+\\)[ \t]*" |
|
205 |
;; (3) switches |
|
206 |
"\\([^\":\n]*\"[^\"\n*]*\"[^\":\n]*\\|[^\":\n]*\\)" |
|
207 |
;; (4) header arguments |
|
208 |
"\\([^\n]*\\)\n" |
|
209 |
;; (5) body |
|
210 |
"\\([^\000]*?\n\\)??[ \t]*#\\+end_src") |
|
211 |
"Regexp used to identify code blocks.") |
|
212 |
|
|
213 |
(defun org-babel--get-vars (params) |
|
214 |
"Return the babel variable assignments in PARAMS. |
|
215 |
|
|
216 |
PARAMS is a quasi-alist of header args, which may contain |
|
217 |
multiple entries for the key `:var'. This function returns a |
|
218 |
list of the cdr of all the `:var' entries." |
|
219 |
(mapcar #'cdr |
|
220 |
(cl-remove-if-not (lambda (x) (eq (car x) :var)) params))) |
|
221 |
|
|
222 |
(defvar org-babel-exp-reference-buffer nil |
|
223 |
"Buffer containing original contents of the exported buffer. |
|
224 |
This is used by Babel to resolve references in source blocks. |
|
225 |
Its value is dynamically bound during export.") |
|
226 |
|
|
227 |
(defun org-babel-check-confirm-evaluate (info) |
|
228 |
"Check whether INFO allows code block evaluation. |
|
229 |
|
|
230 |
Returns nil if evaluation is disallowed, t if it is |
|
231 |
unconditionally allowed, and the symbol `query' if the user |
|
232 |
should be asked whether to allow evaluation." |
|
233 |
(let* ((headers (nth 2 info)) |
|
234 |
(eval (or (cdr (assq :eval headers)) |
|
235 |
(when (assq :noeval headers) "no"))) |
|
236 |
(eval-no (member eval '("no" "never"))) |
|
237 |
(export org-babel-exp-reference-buffer) |
|
238 |
(eval-no-export (and export (member eval '("no-export" "never-export")))) |
|
239 |
(noeval (or eval-no eval-no-export)) |
|
240 |
(query (or (equal eval "query") |
|
241 |
(and export (equal eval "query-export")) |
|
242 |
(if (functionp org-confirm-babel-evaluate) |
|
243 |
(funcall org-confirm-babel-evaluate |
|
244 |
;; Language, code block body. |
|
245 |
(nth 0 info) (nth 1 info)) |
|
246 |
org-confirm-babel-evaluate)))) |
|
247 |
(cond |
|
248 |
(noeval nil) |
|
249 |
(query 'query) |
|
250 |
(t t)))) |
|
251 |
|
|
252 |
(defun org-babel-check-evaluate (info) |
|
253 |
"Check if code block INFO should be evaluated. |
|
254 |
Do not query the user, but do display an informative message if |
|
255 |
evaluation is blocked. Returns non-nil if evaluation is not blocked." |
|
256 |
(let ((confirmed (org-babel-check-confirm-evaluate info))) |
|
257 |
(unless confirmed |
|
258 |
(message "Evaluation of this %s code block%sis disabled." |
|
259 |
(nth 0 info) |
|
260 |
(let ((name (nth 4 info))) |
|
261 |
(if name (format " (%s) " name) " ")))) |
|
262 |
confirmed)) |
|
263 |
|
|
264 |
;; Dynamically scoped for asynchronous export. |
|
265 |
(defvar org-babel-confirm-evaluate-answer-no) |
|
266 |
|
|
267 |
(defun org-babel-confirm-evaluate (info) |
|
268 |
"Confirm evaluation of the code block INFO. |
|
269 |
|
|
270 |
This query can also be suppressed by setting the value of |
|
271 |
`org-confirm-babel-evaluate' to nil, in which case all future |
|
272 |
interactive code block evaluations will proceed without any |
|
273 |
confirmation from the user. |
|
274 |
|
|
275 |
Note disabling confirmation may result in accidental evaluation |
|
276 |
of potentially harmful code. |
|
277 |
|
|
278 |
The variable `org-babel-confirm-evaluate-answer-no' is used by |
|
279 |
the async export process, which requires a non-interactive |
|
280 |
environment, to override this check." |
|
281 |
(let* ((evalp (org-babel-check-confirm-evaluate info)) |
|
282 |
(lang (nth 0 info)) |
|
283 |
(name (nth 4 info)) |
|
284 |
(name-string (if name (format " (%s) " name) " "))) |
|
285 |
(pcase evalp |
|
286 |
(`nil nil) |
|
287 |
(`t t) |
|
288 |
(`query (or |
|
289 |
(and (not (bound-and-true-p |
|
290 |
org-babel-confirm-evaluate-answer-no)) |
|
291 |
(yes-or-no-p |
|
292 |
(format "Evaluate this %s code block%son your system? " |
|
293 |
lang name-string))) |
|
294 |
(progn |
|
295 |
(message "Evaluation of this %s code block%sis aborted." |
|
296 |
lang name-string) |
|
297 |
nil))) |
|
298 |
(x (error "Unexpected value `%s' from `org-babel-check-confirm-evaluate'" x))))) |
|
299 |
|
|
300 |
;;;###autoload |
|
301 |
(defun org-babel-execute-safely-maybe () |
|
302 |
(unless org-babel-no-eval-on-ctrl-c-ctrl-c |
|
303 |
(org-babel-execute-maybe))) |
|
304 |
|
|
305 |
;;;###autoload |
|
306 |
(defun org-babel-execute-maybe () |
|
307 |
(interactive) |
|
308 |
(or (org-babel-execute-src-block-maybe) |
|
309 |
(org-babel-lob-execute-maybe))) |
|
310 |
|
|
311 |
(defmacro org-babel-when-in-src-block (&rest body) |
|
312 |
"Execute BODY if point is in a source block and return t. |
|
313 |
|
|
314 |
Otherwise do nothing and return nil." |
|
315 |
`(if (memq (org-element-type (org-element-context)) |
|
316 |
'(inline-src-block src-block)) |
|
317 |
(progn |
|
318 |
,@body |
|
319 |
t) |
|
320 |
nil)) |
|
321 |
|
|
322 |
(defun org-babel-execute-src-block-maybe () |
|
323 |
"Conditionally execute a source block. |
|
324 |
Detect if this is context for a Babel src-block and if so |
|
325 |
then run `org-babel-execute-src-block'." |
|
326 |
(interactive) |
|
327 |
(org-babel-when-in-src-block |
|
328 |
(org-babel-eval-wipe-error-buffer) |
|
329 |
(org-babel-execute-src-block current-prefix-arg))) |
|
330 |
|
|
331 |
;;;###autoload |
|
332 |
(defun org-babel-view-src-block-info () |
|
333 |
"Display information on the current source block. |
|
334 |
This includes header arguments, language and name, and is largely |
|
335 |
a window into the `org-babel-get-src-block-info' function." |
|
336 |
(interactive) |
|
337 |
(let ((info (org-babel-get-src-block-info 'light)) |
|
338 |
(full (lambda (it) (> (length it) 0))) |
|
339 |
(printf (lambda (fmt &rest args) (princ (apply #'format fmt args))))) |
|
340 |
(when info |
|
341 |
(with-help-window (help-buffer) |
|
342 |
(let ((name (nth 4 info)) |
|
343 |
(lang (nth 0 info)) |
|
344 |
(switches (nth 3 info)) |
|
345 |
(header-args (nth 2 info))) |
|
346 |
(when name (funcall printf "Name: %s\n" name)) |
|
347 |
(when lang (funcall printf "Lang: %s\n" lang)) |
|
348 |
(funcall printf "Properties:\n") |
|
349 |
(funcall printf "\t:header-args \t%s\n" (org-entry-get (point) "header-args" t)) |
|
350 |
(funcall printf "\t:header-args:%s \t%s\n" lang (org-entry-get (point) (concat "header-args:" lang) t)) |
|
351 |
|
|
352 |
(when (funcall full switches) (funcall printf "Switches: %s\n" switches)) |
|
353 |
(funcall printf "Header Arguments:\n") |
|
354 |
(dolist (pair (sort header-args |
|
355 |
(lambda (a b) (string< (symbol-name (car a)) |
|
356 |
(symbol-name (car b)))))) |
|
357 |
(when (funcall full (format "%s" (cdr pair))) |
|
358 |
(funcall printf "\t%S%s\t%s\n" |
|
359 |
(car pair) |
|
360 |
(if (> (length (format "%S" (car pair))) 7) "" "\t") |
|
361 |
(cdr pair))))))))) |
|
362 |
|
|
363 |
;;;###autoload |
|
364 |
(defun org-babel-expand-src-block-maybe () |
|
365 |
"Conditionally expand a source block. |
|
366 |
Detect if this is context for an org-babel src-block and if so |
|
367 |
then run `org-babel-expand-src-block'." |
|
368 |
(interactive) |
|
369 |
(org-babel-when-in-src-block |
|
370 |
(org-babel-expand-src-block current-prefix-arg))) |
|
371 |
|
|
372 |
;;;###autoload |
|
373 |
(defun org-babel-load-in-session-maybe () |
|
374 |
"Conditionally load a source block in a session. |
|
375 |
Detect if this is context for an org-babel src-block and if so |
|
376 |
then run `org-babel-load-in-session'." |
|
377 |
(interactive) |
|
378 |
(org-babel-when-in-src-block |
|
379 |
(org-babel-load-in-session current-prefix-arg))) |
|
380 |
|
|
381 |
(add-hook 'org-metaup-hook 'org-babel-load-in-session-maybe) |
|
382 |
|
|
383 |
;;;###autoload |
|
384 |
(defun org-babel-pop-to-session-maybe () |
|
385 |
"Conditionally pop to a session. |
|
386 |
Detect if this is context for an org-babel src-block and if so |
|
387 |
then run `org-babel-switch-to-session'." |
|
388 |
(interactive) |
|
389 |
(org-babel-when-in-src-block |
|
390 |
(org-babel-switch-to-session current-prefix-arg))) |
|
391 |
|
|
392 |
(add-hook 'org-metadown-hook 'org-babel-pop-to-session-maybe) |
|
393 |
|
|
394 |
(defconst org-babel-common-header-args-w-values |
|
395 |
'((cache . ((no yes))) |
|
396 |
(cmdline . :any) |
|
397 |
(colnames . ((nil no yes))) |
|
398 |
(comments . ((no link yes org both noweb))) |
|
399 |
(dir . :any) |
|
400 |
(eval . ((yes no no-export strip-export never-export eval never |
|
401 |
query))) |
|
402 |
(exports . ((code results both none))) |
|
403 |
(epilogue . :any) |
|
404 |
(file . :any) |
|
405 |
(file-desc . :any) |
|
406 |
(file-ext . :any) |
|
407 |
(hlines . ((no yes))) |
|
408 |
(mkdirp . ((yes no))) |
|
409 |
(no-expand) |
|
410 |
(noeval) |
|
411 |
(noweb . ((yes no tangle no-export strip-export))) |
|
412 |
(noweb-ref . :any) |
|
413 |
(noweb-sep . :any) |
|
414 |
(output-dir . :any) |
|
415 |
(padline . ((yes no))) |
|
416 |
(post . :any) |
|
417 |
(prologue . :any) |
|
418 |
(results . ((file list vector table scalar verbatim) |
|
419 |
(raw html latex org code pp drawer) |
|
420 |
(replace silent none append prepend) |
|
421 |
(output value))) |
|
422 |
(rownames . ((no yes))) |
|
423 |
(sep . :any) |
|
424 |
(session . :any) |
|
425 |
(shebang . :any) |
|
426 |
(tangle . ((tangle yes no :any))) |
|
427 |
(tangle-mode . ((#o755 #o555 #o444 :any))) |
|
428 |
(var . :any) |
|
429 |
(wrap . :any))) |
|
430 |
|
|
431 |
(defconst org-babel-header-arg-names |
|
432 |
(mapcar #'car org-babel-common-header-args-w-values) |
|
433 |
"Common header arguments used by org-babel. |
|
434 |
Note that individual languages may define their own language |
|
435 |
specific header arguments as well.") |
|
436 |
|
|
437 |
(defconst org-babel-safe-header-args |
|
438 |
'(:cache :colnames :comments :exports :epilogue :hlines :noeval |
|
439 |
:noweb :noweb-ref :noweb-sep :padline :prologue :rownames |
|
440 |
:sep :session :tangle :wrap |
|
441 |
(:eval . ("never" "query")) |
|
442 |
(:results . (lambda (str) (not (string-match "file" str))))) |
|
443 |
"A list of safe header arguments for babel source blocks. |
|
444 |
|
|
445 |
The list can have entries of the following forms: |
|
446 |
- :ARG -> :ARG is always a safe header arg |
|
447 |
- (:ARG . (VAL1 VAL2 ...)) -> :ARG is safe as a header arg if it is |
|
448 |
`equal' to one of the VALs. |
|
449 |
- (:ARG . FN) -> :ARG is safe as a header arg if the function FN |
|
450 |
returns non-nil. FN is passed one |
|
451 |
argument, the value of the header arg |
|
452 |
(as a string).") |
|
453 |
|
|
454 |
(defmacro org-babel-header-args-safe-fn (safe-list) |
|
455 |
"Return a function that determines whether a list of header args are safe. |
|
456 |
|
|
457 |
Intended usage is: |
|
458 |
\(put \\='org-babel-default-header-args \\='safe-local-variable |
|
459 |
(org-babel-header-args-safe-p org-babel-safe-header-args) |
|
460 |
|
|
461 |
This allows org-babel languages to extend the list of safe values for |
|
462 |
their `org-babel-default-header-args:foo' variable. |
|
463 |
|
|
464 |
For the format of SAFE-LIST, see `org-babel-safe-header-args'." |
|
465 |
`(lambda (value) |
|
466 |
(and (listp value) |
|
467 |
(cl-every |
|
468 |
(lambda (pair) |
|
469 |
(and (consp pair) |
|
470 |
(org-babel-one-header-arg-safe-p pair ,safe-list))) |
|
471 |
value)))) |
|
472 |
|
|
473 |
(defvar org-babel-default-header-args |
|
474 |
'((:session . "none") (:results . "replace") (:exports . "code") |
|
475 |
(:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "no")) |
|
476 |
"Default arguments to use when evaluating a source block.") |
|
477 |
(put 'org-babel-default-header-args 'safe-local-variable |
|
478 |
(org-babel-header-args-safe-fn org-babel-safe-header-args)) |
|
479 |
|
|
480 |
(defvar org-babel-default-inline-header-args |
|
481 |
'((:session . "none") (:results . "replace") |
|
482 |
(:exports . "results") (:hlines . "yes")) |
|
483 |
"Default arguments to use when evaluating an inline source block.") |
|
484 |
(put 'org-babel-default-inline-header-args 'safe-local-variable |
|
485 |
(org-babel-header-args-safe-fn org-babel-safe-header-args)) |
|
486 |
|
|
487 |
(defconst org-babel-name-regexp |
|
488 |
(format "^[ \t]*#\\+%s:[ \t]*" |
|
489 |
;; FIXME: TBLNAME is for backward compatibility. |
|
490 |
(regexp-opt '("NAME" "TBLNAME"))) |
|
491 |
"Regexp matching a NAME keyword.") |
|
492 |
|
|
493 |
(defconst org-babel-result-regexp |
|
494 |
(format "^[ \t]*#\\+%s\\(?:\\[\\(?:%s \\)?\\([[:alnum:]]+\\)\\]\\)?:[ \t]*" |
|
495 |
org-babel-results-keyword |
|
496 |
;; <%Y-%m-%d %H:%M:%S> |
|
497 |
"<\\(?:[0-9]\\{4\\}-[0-1][0-9]-[0-3][0-9] \ |
|
498 |
[0-2][0-9]\\(?::[0-5][0-9]\\)\\{2\\}\\)>") |
|
499 |
"Regular expression used to match result lines. |
|
500 |
If the results are associated with a hash key then the hash will |
|
501 |
be saved in match group 1.") |
|
502 |
|
|
503 |
(defconst org-babel-result-w-name-regexp |
|
504 |
(concat org-babel-result-regexp "\\(?9:[^ \t\n\r\v\f]+\\)") |
|
505 |
"Regexp matching a RESULTS keyword with a name. |
|
506 |
Name is saved in match group 9.") |
|
507 |
|
|
508 |
(defvar org-babel-min-lines-for-block-output 10 |
|
509 |
"The minimum number of lines for block output. |
|
510 |
If number of lines of output is equal to or exceeds this |
|
511 |
value, the output is placed in a #+begin_example...#+end_example |
|
512 |
block. Otherwise the output is marked as literal by inserting |
|
513 |
colons at the starts of the lines. This variable only takes |
|
514 |
effect if the :results output option is in effect.") |
|
515 |
|
|
516 |
(defvar org-babel-noweb-error-all-langs nil |
|
517 |
"Raise errors when noweb references don't resolve. |
|
518 |
Also see `org-babel-noweb-error-langs' to control noweb errors on |
|
519 |
a language by language bases.") |
|
520 |
|
|
521 |
(defvar org-babel-noweb-error-langs nil |
|
522 |
"Languages for which Babel will raise literate programming errors. |
|
523 |
List of languages for which errors should be raised when the |
|
524 |
source code block satisfying a noweb reference in this language |
|
525 |
can not be resolved. Also see `org-babel-noweb-error-all-langs' |
|
526 |
to raise errors for all languages.") |
|
527 |
|
|
528 |
(defvar org-babel-hash-show 4 |
|
529 |
"Number of initial characters to show of a hidden results hash.") |
|
530 |
|
|
531 |
(defvar org-babel-after-execute-hook nil |
|
532 |
"Hook for functions to be called after `org-babel-execute-src-block'") |
|
533 |
|
|
534 |
(defun org-babel-named-src-block-regexp-for-name (&optional name) |
|
535 |
"This generates a regexp used to match a src block named NAME. |
|
536 |
If NAME is nil, match any name. Matched name is then put in |
|
537 |
match group 9. Other match groups are defined in |
|
538 |
`org-babel-src-block-regexp'." |
|
539 |
(concat org-babel-src-name-regexp |
|
540 |
(concat (if name (regexp-quote name) "\\(?9:.*?\\)") "[ \t]*" ) |
|
541 |
"\\(?:\n[ \t]*#\\+\\S-+:.*\\)*?" |
|
542 |
"\n" |
|
543 |
(substring org-babel-src-block-regexp 1))) |
|
544 |
|
|
545 |
(defun org-babel-named-data-regexp-for-name (name) |
|
546 |
"This generates a regexp used to match data named NAME." |
|
547 |
(concat org-babel-name-regexp (regexp-quote name) "[ \t]*$")) |
|
548 |
|
|
549 |
(defun org-babel--normalize-body (datum) |
|
550 |
"Normalize body for element or object DATUM. |
|
551 |
DATUM is a source block element or an inline source block object. |
|
552 |
Remove final newline character and spurious indentation." |
|
553 |
(let* ((value (org-element-property :value datum)) |
|
554 |
(body (if (string-suffix-p "\n" value) |
|
555 |
(substring value 0 -1) |
|
556 |
value))) |
|
557 |
(cond ((eq (org-element-type datum) 'inline-src-block) |
|
558 |
;; Newline characters and indentation in an inline |
|
559 |
;; src-block are not meaningful, since they could come from |
|
560 |
;; some paragraph filling. Treat them as a white space. |
|
561 |
(replace-regexp-in-string "\n[ \t]*" " " body)) |
|
562 |
((or org-src-preserve-indentation |
|
563 |
(org-element-property :preserve-indent datum)) |
|
564 |
body) |
|
565 |
(t (org-remove-indentation body))))) |
|
566 |
|
|
567 |
;;; functions |
|
568 |
(defvar org-babel-current-src-block-location nil |
|
569 |
"Marker pointing to the src block currently being executed. |
|
570 |
This may also point to a call line or an inline code block. If |
|
571 |
multiple blocks are being executed (e.g., in chained execution |
|
572 |
through use of the :var header argument) this marker points to |
|
573 |
the outer-most code block.") |
|
574 |
|
|
575 |
(defvar *this*) |
|
576 |
|
|
577 |
(defun org-babel-get-src-block-info (&optional light datum) |
|
578 |
"Extract information from a source block or inline source block. |
|
579 |
|
|
580 |
Optional argument LIGHT does not resolve remote variable |
|
581 |
references; a process which could likely result in the execution |
|
582 |
of other code blocks. |
|
583 |
|
|
584 |
By default, consider the block at point. However, when optional |
|
585 |
argument DATUM is provided, extract information from that parsed |
|
586 |
object instead. |
|
587 |
|
|
588 |
Return nil if point is not on a source block. Otherwise, return |
|
589 |
a list with the following pattern: |
|
590 |
|
|
591 |
(language body arguments switches name start coderef)" |
|
592 |
(let* ((datum (or datum (org-element-context))) |
|
593 |
(type (org-element-type datum)) |
|
594 |
(inline (eq type 'inline-src-block))) |
|
595 |
(when (memq type '(inline-src-block src-block)) |
|
596 |
(let* ((lang (org-element-property :language datum)) |
|
597 |
(lang-headers (intern |
|
598 |
(concat "org-babel-default-header-args:" lang))) |
|
599 |
(name (org-element-property :name datum)) |
|
600 |
(info |
|
601 |
(list |
|
602 |
lang |
|
603 |
(org-babel--normalize-body datum) |
|
604 |
(apply #'org-babel-merge-params |
|
605 |
(if inline org-babel-default-inline-header-args |
|
606 |
org-babel-default-header-args) |
|
607 |
(and (boundp lang-headers) (eval lang-headers t)) |
|
608 |
(append |
|
609 |
;; If DATUM is provided, make sure we get node |
|
610 |
;; properties applicable to its location within |
|
611 |
;; the document. |
|
612 |
(org-with-point-at (org-element-property :begin datum) |
|
613 |
(org-babel-params-from-properties lang)) |
|
614 |
(mapcar #'org-babel-parse-header-arguments |
|
615 |
(cons (org-element-property :parameters datum) |
|
616 |
(org-element-property :header datum))))) |
|
617 |
(or (org-element-property :switches datum) "") |
|
618 |
name |
|
619 |
(org-element-property (if inline :begin :post-affiliated) |
|
620 |
datum) |
|
621 |
(and (not inline) (org-src-coderef-format datum))))) |
|
622 |
(unless light |
|
623 |
(setf (nth 2 info) (org-babel-process-params (nth 2 info)))) |
|
624 |
(setf (nth 2 info) (org-babel-generate-file-param name (nth 2 info))) |
|
625 |
info)))) |
|
626 |
|
|
627 |
;;;###autoload |
|
628 |
(defun org-babel-execute-src-block (&optional arg info params) |
|
629 |
"Execute the current source code block. |
|
630 |
Insert the results of execution into the buffer. Source code |
|
631 |
execution and the collection and formatting of results can be |
|
632 |
controlled through a variety of header arguments. |
|
633 |
|
|
634 |
With prefix argument ARG, force re-execution even if an existing |
|
635 |
result cached in the buffer would otherwise have been returned. |
|
636 |
|
|
637 |
Optionally supply a value for INFO in the form returned by |
|
638 |
`org-babel-get-src-block-info'. |
|
639 |
|
|
640 |
Optionally supply a value for PARAMS which will be merged with |
|
641 |
the header arguments specified at the front of the source code |
|
642 |
block." |
|
643 |
(interactive) |
|
644 |
(let* ((org-babel-current-src-block-location |
|
645 |
(or org-babel-current-src-block-location |
|
646 |
(nth 5 info) |
|
647 |
(org-babel-where-is-src-block-head))) |
|
648 |
(info (if info (copy-tree info) (org-babel-get-src-block-info)))) |
|
649 |
;; Merge PARAMS with INFO before considering source block |
|
650 |
;; evaluation since both could disagree. |
|
651 |
(cl-callf org-babel-merge-params (nth 2 info) params) |
|
652 |
(when (org-babel-check-evaluate info) |
|
653 |
(cl-callf org-babel-process-params (nth 2 info)) |
|
654 |
(let* ((params (nth 2 info)) |
|
655 |
(cache (let ((c (cdr (assq :cache params)))) |
|
656 |
(and (not arg) c (string= "yes" c)))) |
|
657 |
(new-hash (and cache (org-babel-sha1-hash info))) |
|
658 |
(old-hash (and cache (org-babel-current-result-hash))) |
|
659 |
(current-cache (and new-hash (equal new-hash old-hash)))) |
|
660 |
(cond |
|
661 |
(current-cache |
|
662 |
(save-excursion ;Return cached result. |
|
663 |
(goto-char (org-babel-where-is-src-block-result nil info)) |
|
664 |
(forward-line) |
|
665 |
(skip-chars-forward " \t") |
|
666 |
(let ((result (org-babel-read-result))) |
|
667 |
(message (replace-regexp-in-string "%" "%%" (format "%S" result))) |
|
668 |
result))) |
|
669 |
((org-babel-confirm-evaluate info) |
|
670 |
(let* ((lang (nth 0 info)) |
|
671 |
(result-params (cdr (assq :result-params params))) |
|
672 |
;; Expand noweb references in BODY and remove any |
|
673 |
;; coderef. |
|
674 |
(body |
|
675 |
(let ((coderef (nth 6 info)) |
|
676 |
(expand |
|
677 |
(if (org-babel-noweb-p params :eval) |
|
678 |
(org-babel-expand-noweb-references info) |
|
679 |
(nth 1 info)))) |
|
680 |
(if (not coderef) expand |
|
681 |
(replace-regexp-in-string |
|
682 |
(org-src-coderef-regexp coderef) "" expand nil nil 1)))) |
|
683 |
(dir (cdr (assq :dir params))) |
|
684 |
(default-directory |
|
685 |
(or (and dir (file-name-as-directory (expand-file-name dir))) |
|
686 |
default-directory)) |
|
687 |
(cmd (intern (concat "org-babel-execute:" lang))) |
|
688 |
result) |
|
689 |
(unless (fboundp cmd) |
|
690 |
(error "No org-babel-execute function for %s!" lang)) |
|
691 |
(message "executing %s code block%s..." |
|
692 |
(capitalize lang) |
|
693 |
(let ((name (nth 4 info))) |
|
694 |
(if name (format " (%s)" name) ""))) |
|
695 |
(if (member "none" result-params) |
|
696 |
(progn (funcall cmd body params) |
|
697 |
(message "result silenced")) |
|
698 |
(setq result |
|
699 |
(let ((r (funcall cmd body params))) |
|
700 |
(if (and (eq (cdr (assq :result-type params)) 'value) |
|
701 |
(or (member "vector" result-params) |
|
702 |
(member "table" result-params)) |
|
703 |
(not (listp r))) |
|
704 |
(list (list r)) |
|
705 |
r))) |
|
706 |
(let ((file (cdr (assq :file params)))) |
|
707 |
;; If non-empty result and :file then write to :file. |
|
708 |
(when file |
|
709 |
(when result |
|
710 |
(with-temp-file file |
|
711 |
(insert (org-babel-format-result |
|
712 |
result (cdr (assq :sep params)))))) |
|
713 |
(setq result file)) |
|
714 |
;; Possibly perform post process provided its |
|
715 |
;; appropriate. Dynamically bind "*this*" to the |
|
716 |
;; actual results of the block. |
|
717 |
(let ((post (cdr (assq :post params)))) |
|
718 |
(when post |
|
719 |
(let ((*this* (if (not file) result |
|
720 |
(org-babel-result-to-file |
|
721 |
file |
|
722 |
(let ((desc (assq :file-desc params))) |
|
723 |
(and desc (or (cdr desc) result))))))) |
|
724 |
(setq result (org-babel-ref-resolve post)) |
|
725 |
(when file |
|
726 |
(setq result-params (remove "file" result-params)))))) |
|
727 |
(org-babel-insert-result |
|
728 |
result result-params info new-hash lang))) |
|
729 |
(run-hooks 'org-babel-after-execute-hook) |
|
730 |
result))))))) |
|
731 |
|
|
732 |
(defun org-babel-expand-body:generic (body params &optional var-lines) |
|
733 |
"Expand BODY with PARAMS. |
|
734 |
Expand a block of code with org-babel according to its header |
|
735 |
arguments. This generic implementation of body expansion is |
|
736 |
called for languages which have not defined their own specific |
|
737 |
org-babel-expand-body:lang function." |
|
738 |
(let ((pro (cdr (assq :prologue params))) |
|
739 |
(epi (cdr (assq :epilogue params)))) |
|
740 |
(mapconcat #'identity |
|
741 |
(append (when pro (list pro)) |
|
742 |
var-lines |
|
743 |
(list body) |
|
744 |
(when epi (list epi))) |
|
745 |
"\n"))) |
|
746 |
|
|
747 |
;;;###autoload |
|
748 |
(defun org-babel-expand-src-block (&optional _arg info params) |
|
749 |
"Expand the current source code block. |
|
750 |
Expand according to the source code block's header |
|
751 |
arguments and pop open the results in a preview buffer." |
|
752 |
(interactive) |
|
753 |
(let* ((info (or info (org-babel-get-src-block-info))) |
|
754 |
(lang (nth 0 info)) |
|
755 |
(params (setf (nth 2 info) |
|
756 |
(sort (org-babel-merge-params (nth 2 info) params) |
|
757 |
(lambda (el1 el2) (string< (symbol-name (car el1)) |
|
758 |
(symbol-name (car el2))))))) |
|
759 |
(body (setf (nth 1 info) |
|
760 |
(if (org-babel-noweb-p params :eval) |
|
761 |
(org-babel-expand-noweb-references info) (nth 1 info)))) |
|
762 |
(expand-cmd (intern (concat "org-babel-expand-body:" lang))) |
|
763 |
(assignments-cmd (intern (concat "org-babel-variable-assignments:" |
|
764 |
lang))) |
|
765 |
(expanded |
|
766 |
(if (fboundp expand-cmd) (funcall expand-cmd body params) |
|
767 |
(org-babel-expand-body:generic |
|
768 |
body params (and (fboundp assignments-cmd) |
|
769 |
(funcall assignments-cmd params)))))) |
|
770 |
(if (called-interactively-p 'any) |
|
771 |
(org-edit-src-code |
|
772 |
expanded (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*")) |
|
773 |
expanded))) |
|
774 |
|
|
775 |
(defun org-babel-edit-distance (s1 s2) |
|
776 |
"Return the edit (levenshtein) distance between strings S1 S2." |
|
777 |
(let* ((l1 (length s1)) |
|
778 |
(l2 (length s2)) |
|
779 |
(dist (vconcat (mapcar (lambda (_) (make-vector (1+ l2) nil)) |
|
780 |
(number-sequence 1 (1+ l1))))) |
|
781 |
(in (lambda (i j) (aref (aref dist i) j)))) |
|
782 |
(setf (aref (aref dist 0) 0) 0) |
|
783 |
(dolist (j (number-sequence 1 l2)) |
|
784 |
(setf (aref (aref dist 0) j) j)) |
|
785 |
(dolist (i (number-sequence 1 l1)) |
|
786 |
(setf (aref (aref dist i) 0) i) |
|
787 |
(dolist (j (number-sequence 1 l2)) |
|
788 |
(setf (aref (aref dist i) j) |
|
789 |
(min |
|
790 |
(1+ (funcall in (1- i) j)) |
|
791 |
(1+ (funcall in i (1- j))) |
|
792 |
(+ (if (equal (aref s1 (1- i)) (aref s2 (1- j))) 0 1) |
|
793 |
(funcall in (1- i) (1- j))))))) |
|
794 |
(funcall in l1 l2))) |
|
795 |
|
|
796 |
(defun org-babel-combine-header-arg-lists (original &rest others) |
|
797 |
"Combine a number of lists of header argument names and arguments." |
|
798 |
(let ((results (copy-sequence original))) |
|
799 |
(dolist (new-list others) |
|
800 |
(dolist (arg-pair new-list) |
|
801 |
(let ((header (car arg-pair))) |
|
802 |
(setq results |
|
803 |
(cons arg-pair (cl-remove-if |
|
804 |
(lambda (pair) (equal header (car pair))) |
|
805 |
results)))))) |
|
806 |
results)) |
|
807 |
|
|
808 |
;;;###autoload |
|
809 |
(defun org-babel-check-src-block () |
|
810 |
"Check for misspelled header arguments in the current code block." |
|
811 |
(interactive) |
|
812 |
;; TODO: report malformed code block |
|
813 |
;; TODO: report incompatible combinations of header arguments |
|
814 |
;; TODO: report uninitialized variables |
|
815 |
(let ((too-close 2) ;; <- control closeness to report potential match |
|
816 |
(names (mapcar #'symbol-name org-babel-header-arg-names))) |
|
817 |
(dolist (header (mapcar (lambda (arg) (substring (symbol-name (car arg)) 1)) |
|
818 |
(and (org-babel-where-is-src-block-head) |
|
819 |
(org-babel-parse-header-arguments |
|
820 |
(org-no-properties |
|
821 |
(match-string 4)))))) |
|
822 |
(dolist (name names) |
|
823 |
(when (and (not (string= header name)) |
|
824 |
(<= (org-babel-edit-distance header name) too-close) |
|
825 |
(not (member header names))) |
|
826 |
(error "Supplied header \"%S\" is suspiciously close to \"%S\"" |
|
827 |
header name)))) |
|
828 |
(message "No suspicious header arguments found."))) |
|
829 |
|
|
830 |
;;;###autoload |
|
831 |
(defun org-babel-insert-header-arg (&optional header-arg value) |
|
832 |
"Insert a header argument selecting from lists of common args and values." |
|
833 |
(interactive) |
|
834 |
(let* ((info (org-babel-get-src-block-info 'light)) |
|
835 |
(lang (car info)) |
|
836 |
(begin (nth 5 info)) |
|
837 |
(lang-headers (intern (concat "org-babel-header-args:" lang))) |
|
838 |
(headers (org-babel-combine-header-arg-lists |
|
839 |
org-babel-common-header-args-w-values |
|
840 |
(when (boundp lang-headers) (eval lang-headers t)))) |
|
841 |
(header-arg (or header-arg |
|
842 |
(completing-read |
|
843 |
"Header Arg: " |
|
844 |
(mapcar |
|
845 |
(lambda (header-spec) (symbol-name (car header-spec))) |
|
846 |
headers)))) |
|
847 |
(vals (cdr (assoc (intern header-arg) headers))) |
|
848 |
(value (or value |
|
849 |
(cond |
|
850 |
((eq vals :any) |
|
851 |
(read-from-minibuffer "value: ")) |
|
852 |
((listp vals) |
|
853 |
(mapconcat |
|
854 |
(lambda (group) |
|
855 |
(let ((arg (completing-read |
|
856 |
"Value: " |
|
857 |
(cons "default" |
|
858 |
(mapcar #'symbol-name group))))) |
|
859 |
(if (and arg (not (string= "default" arg))) |
|
860 |
(concat arg " ") |
|
861 |
""))) |
|
862 |
vals "")))))) |
|
863 |
(save-excursion |
|
864 |
(goto-char begin) |
|
865 |
(goto-char (point-at-eol)) |
|
866 |
(unless (= (char-before (point)) ?\ ) (insert " ")) |
|
867 |
(insert ":" header-arg) (when value (insert " " value))))) |
|
868 |
|
|
869 |
;; Add support for completing-read insertion of header arguments after ":" |
|
870 |
(defun org-babel-header-arg-expand () |
|
871 |
"Call `org-babel-enter-header-arg-w-completion' in appropriate contexts." |
|
872 |
(when (and (equal (char-before) ?\:) (org-babel-where-is-src-block-head)) |
|
873 |
(org-babel-enter-header-arg-w-completion (match-string 2)))) |
|
874 |
|
|
875 |
(defun org-babel-enter-header-arg-w-completion (&optional lang) |
|
876 |
"Insert header argument appropriate for LANG with completion." |
|
877 |
(let* ((lang-headers-var (intern (concat "org-babel-header-args:" lang))) |
|
878 |
(lang-headers (when (boundp lang-headers-var) (eval lang-headers-var t))) |
|
879 |
(headers-w-values (org-babel-combine-header-arg-lists |
|
880 |
org-babel-common-header-args-w-values lang-headers)) |
|
881 |
(headers (mapcar #'symbol-name (mapcar #'car headers-w-values))) |
|
882 |
(header (org-completing-read "Header Arg: " headers)) |
|
883 |
(args (cdr (assoc (intern header) headers-w-values))) |
|
884 |
(arg (when (and args (listp args)) |
|
885 |
(org-completing-read |
|
886 |
(format "%s: " header) |
|
887 |
(mapcar #'symbol-name (apply #'append args)))))) |
|
888 |
(insert (concat header " " (or arg ""))) |
|
889 |
(cons header arg))) |
|
890 |
|
|
891 |
(add-hook 'org-tab-first-hook 'org-babel-header-arg-expand) |
|
892 |
|
|
893 |
;;;###autoload |
|
894 |
(defun org-babel-load-in-session (&optional _arg info) |
|
895 |
"Load the body of the current source-code block. |
|
896 |
Evaluate the header arguments for the source block before |
|
897 |
entering the session. After loading the body this pops open the |
|
898 |
session." |
|
899 |
(interactive) |
|
900 |
(let* ((info (or info (org-babel-get-src-block-info))) |
|
901 |
(lang (nth 0 info)) |
|
902 |
(params (nth 2 info)) |
|
903 |
(body (if (not info) |
|
904 |
(user-error "No src code block at point") |
|
905 |
(setf (nth 1 info) |
|
906 |
(if (org-babel-noweb-p params :eval) |
|
907 |
(org-babel-expand-noweb-references info) |
|
908 |
(nth 1 info))))) |
|
909 |
(session (cdr (assq :session params))) |
|
910 |
(dir (cdr (assq :dir params))) |
|
911 |
(default-directory |
|
912 |
(or (and dir (file-name-as-directory dir)) default-directory)) |
|
913 |
(cmd (intern (concat "org-babel-load-session:" lang)))) |
|
914 |
(unless (fboundp cmd) |
|
915 |
(error "No org-babel-load-session function for %s!" lang)) |
|
916 |
(pop-to-buffer (funcall cmd session body params)) |
|
917 |
(end-of-line 1))) |
|
918 |
|
|
919 |
;;;###autoload |
|
920 |
(defun org-babel-initiate-session (&optional arg info) |
|
921 |
"Initiate session for current code block. |
|
922 |
If called with a prefix argument then resolve any variable |
|
923 |
references in the header arguments and assign these variables in |
|
924 |
the session. Copy the body of the code block to the kill ring." |
|
925 |
(interactive "P") |
|
926 |
(let* ((info (or info (org-babel-get-src-block-info (not arg)))) |
|
927 |
(lang (nth 0 info)) |
|
928 |
(body (nth 1 info)) |
|
929 |
(params (nth 2 info)) |
|
930 |
(session (cdr (assq :session params))) |
|
931 |
(dir (cdr (assq :dir params))) |
|
932 |
(default-directory |
|
933 |
(or (and dir (file-name-as-directory dir)) default-directory)) |
|
934 |
(init-cmd (intern (format "org-babel-%s-initiate-session" lang))) |
|
935 |
(prep-cmd (intern (concat "org-babel-prep-session:" lang)))) |
|
936 |
(when (and (stringp session) (string= session "none")) |
|
937 |
(error "This block is not using a session!")) |
|
938 |
(unless (fboundp init-cmd) |
|
939 |
(error "No org-babel-initiate-session function for %s!" lang)) |
|
940 |
(with-temp-buffer (insert (org-trim body)) |
|
941 |
(copy-region-as-kill (point-min) (point-max))) |
|
942 |
(when arg |
|
943 |
(unless (fboundp prep-cmd) |
|
944 |
(error "No org-babel-prep-session function for %s!" lang)) |
|
945 |
(funcall prep-cmd session params)) |
|
946 |
(funcall init-cmd session params))) |
|
947 |
|
|
948 |
;;;###autoload |
|
949 |
(defun org-babel-switch-to-session (&optional arg info) |
|
950 |
"Switch to the session of the current code block. |
|
951 |
Uses `org-babel-initiate-session' to start the session. If called |
|
952 |
with a prefix argument then this is passed on to |
|
953 |
`org-babel-initiate-session'." |
|
954 |
(interactive "P") |
|
955 |
(pop-to-buffer (org-babel-initiate-session arg info)) |
|
956 |
(end-of-line 1)) |
|
957 |
|
|
958 |
(defalias 'org-babel-pop-to-session 'org-babel-switch-to-session) |
|
959 |
|
|
960 |
(defvar org-src-window-setup) |
|
961 |
|
|
962 |
;;;###autoload |
|
963 |
(defun org-babel-switch-to-session-with-code (&optional arg _info) |
|
964 |
"Switch to code buffer and display session." |
|
965 |
(interactive "P") |
|
966 |
(let ((swap-windows |
|
967 |
(lambda () |
|
968 |
(let ((other-window-buffer (window-buffer (next-window)))) |
|
969 |
(set-window-buffer (next-window) (current-buffer)) |
|
970 |
(set-window-buffer (selected-window) other-window-buffer)) |
|
971 |
(other-window 1))) |
|
972 |
(info (org-babel-get-src-block-info)) |
|
973 |
(org-src-window-setup 'reorganize-frame)) |
|
974 |
(save-excursion |
|
975 |
(org-babel-switch-to-session arg info)) |
|
976 |
(org-edit-src-code) |
|
977 |
(funcall swap-windows))) |
|
978 |
|
|
979 |
;;;###autoload |
|
980 |
(defmacro org-babel-do-in-edit-buffer (&rest body) |
|
981 |
"Evaluate BODY in edit buffer if there is a code block at point. |
|
982 |
Return t if a code block was found at point, nil otherwise." |
|
983 |
(declare (debug (body))) |
|
984 |
`(let* ((element (org-element-at-point)) |
|
985 |
;; This function is not supposed to move point. However, |
|
986 |
;; `org-edit-src-code' always moves point back into the |
|
987 |
;; source block. It is problematic if the point was before |
|
988 |
;; the code, e.g., on block's opening line. In this case, |
|
989 |
;; we want to restore this location after executing BODY. |
|
990 |
(outside-position |
|
991 |
(and (<= (line-beginning-position) |
|
992 |
(org-element-property :post-affiliated element)) |
|
993 |
(point-marker))) |
|
994 |
(org-src-window-setup 'switch-invisibly)) |
|
995 |
(when (and (org-babel-where-is-src-block-head element) |
|
996 |
(org-edit-src-code)) |
|
997 |
(unwind-protect (progn ,@body) |
|
998 |
(org-edit-src-exit) |
|
999 |
(when outside-position (goto-char outside-position))) |
|
1000 |
t))) |
|
1001 |
|
|
1002 |
(defun org-babel-do-key-sequence-in-edit-buffer (key) |
|
1003 |
"Read key sequence and execute the command in edit buffer. |
|
1004 |
Enter a key sequence to be executed in the language major-mode |
|
1005 |
edit buffer. For example, TAB will alter the contents of the |
|
1006 |
Org code block according to the effect of TAB in the language |
|
1007 |
major mode buffer. For languages that support interactive |
|
1008 |
sessions, this can be used to send code from the Org buffer |
|
1009 |
to the session for evaluation using the native major mode |
|
1010 |
evaluation mechanisms." |
|
1011 |
(interactive "kEnter key-sequence to execute in edit buffer: ") |
|
1012 |
(org-babel-do-in-edit-buffer |
|
1013 |
(call-interactively |
|
1014 |
(key-binding (or key (read-key-sequence nil)))))) |
|
1015 |
|
|
1016 |
(defvar org-bracket-link-regexp) |
|
1017 |
|
|
1018 |
(defun org-babel-active-location-p () |
|
1019 |
(memq (org-element-type (save-match-data (org-element-context))) |
|
1020 |
'(babel-call inline-babel-call inline-src-block src-block))) |
|
1021 |
|
|
1022 |
;;;###autoload |
|
1023 |
(defun org-babel-open-src-block-result (&optional re-run) |
|
1024 |
"If `point' is on a src block then open the results of the |
|
1025 |
source code block, otherwise return nil. With optional prefix |
|
1026 |
argument RE-RUN the source-code block is evaluated even if |
|
1027 |
results already exist." |
|
1028 |
(interactive "P") |
|
1029 |
(let ((info (org-babel-get-src-block-info 'light))) |
|
1030 |
(when info |
|
1031 |
(save-excursion |
|
1032 |
;; go to the results, if there aren't any then run the block |
|
1033 |
(goto-char (or (and (not re-run) (org-babel-where-is-src-block-result)) |
|
1034 |
(progn (org-babel-execute-src-block) |
|
1035 |
(org-babel-where-is-src-block-result)))) |
|
1036 |
(end-of-line 1) |
|
1037 |
(while (looking-at "[\n\r\t\f ]") (forward-char 1)) |
|
1038 |
;; open the results |
|
1039 |
(if (looking-at org-bracket-link-regexp) |
|
1040 |
;; file results |
|
1041 |
(org-open-at-point) |
|
1042 |
(let ((r (org-babel-format-result |
|
1043 |
(org-babel-read-result) (cdr (assq :sep (nth 2 info)))))) |
|
1044 |
(pop-to-buffer (get-buffer-create "*Org-Babel Results*")) |
|
1045 |
(delete-region (point-min) (point-max)) |
|
1046 |
(insert r))) |
|
1047 |
t)))) |
|
1048 |
|
|
1049 |
;;;###autoload |
|
1050 |
(defmacro org-babel-map-src-blocks (file &rest body) |
|
1051 |
"Evaluate BODY forms on each source-block in FILE. |
|
1052 |
If FILE is nil evaluate BODY forms on source blocks in current |
|
1053 |
buffer. During evaluation of BODY the following local variables |
|
1054 |
are set relative to the currently matched code block. |
|
1055 |
|
|
1056 |
full-block ------- string holding the entirety of the code block |
|
1057 |
beg-block -------- point at the beginning of the code block |
|
1058 |
end-block -------- point at the end of the matched code block |
|
1059 |
lang ------------- string holding the language of the code block |
|
1060 |
beg-lang --------- point at the beginning of the lang |
|
1061 |
end-lang --------- point at the end of the lang |
|
1062 |
switches --------- string holding the switches |
|
1063 |
beg-switches ----- point at the beginning of the switches |
|
1064 |
end-switches ----- point at the end of the switches |
|
1065 |
header-args ------ string holding the header-args |
|
1066 |
beg-header-args -- point at the beginning of the header-args |
|
1067 |
end-header-args -- point at the end of the header-args |
|
1068 |
body ------------- string holding the body of the code block |
|
1069 |
beg-body --------- point at the beginning of the body |
|
1070 |
end-body --------- point at the end of the body" |
|
1071 |
(declare (indent 1)) |
|
1072 |
(let ((tempvar (make-symbol "file"))) |
|
1073 |
`(let* ((case-fold-search t) |
|
1074 |
(,tempvar ,file) |
|
1075 |
(visited-p (or (null ,tempvar) |
|
1076 |
(get-file-buffer (expand-file-name ,tempvar)))) |
|
1077 |
(point (point)) to-be-removed) |
|
1078 |
(save-window-excursion |
|
1079 |
(when ,tempvar (find-file ,tempvar)) |
|
1080 |
(setq to-be-removed (current-buffer)) |
|
1081 |
(goto-char (point-min)) |
|
1082 |
(while (re-search-forward org-babel-src-block-regexp nil t) |
|
1083 |
(when (org-babel-active-location-p) |
|
1084 |
(goto-char (match-beginning 0)) |
|
1085 |
(let ((full-block (match-string 0)) |
|
1086 |
(beg-block (match-beginning 0)) |
|
1087 |
(end-block (match-end 0)) |
|
1088 |
(lang (match-string 2)) |
|
1089 |
(beg-lang (match-beginning 2)) |
|
1090 |
(end-lang (match-end 2)) |
|
1091 |
(switches (match-string 3)) |
|
1092 |
(beg-switches (match-beginning 3)) |
|
1093 |
(end-switches (match-end 3)) |
|
1094 |
(header-args (match-string 4)) |
|
1095 |
(beg-header-args (match-beginning 4)) |
|
1096 |
(end-header-args (match-end 4)) |
|
1097 |
(body (match-string 5)) |
|
1098 |
(beg-body (match-beginning 5)) |
|
1099 |
(end-body (match-end 5))) |
|
1100 |
;; Silence byte-compiler in case `body' doesn't use all |
|
1101 |
;; those variables. |
|
1102 |
(ignore full-block beg-block end-block lang |
|
1103 |
beg-lang end-lang switches beg-switches |
|
1104 |
end-switches header-args beg-header-args |
|
1105 |
end-header-args body beg-body end-body) |
|
1106 |
,@body |
|
1107 |
(goto-char end-block))))) |
|
1108 |
(unless visited-p (kill-buffer to-be-removed)) |
|
1109 |
(goto-char point)))) |
|
1110 |
(def-edebug-spec org-babel-map-src-blocks (form body)) |
|
1111 |
|
|
1112 |
;;;###autoload |
|
1113 |
(defmacro org-babel-map-inline-src-blocks (file &rest body) |
|
1114 |
"Evaluate BODY forms on each inline source block in FILE. |
|
1115 |
If FILE is nil evaluate BODY forms on source blocks in current |
|
1116 |
buffer." |
|
1117 |
(declare (indent 1) (debug (form body))) |
|
1118 |
(org-with-gensyms (datum end point tempvar to-be-removed visitedp) |
|
1119 |
`(let* ((case-fold-search t) |
|
1120 |
(,tempvar ,file) |
|
1121 |
(,visitedp (or (null ,tempvar) |
|
1122 |
(get-file-buffer (expand-file-name ,tempvar)))) |
|
1123 |
(,point (point)) |
|
1124 |
,to-be-removed) |
|
1125 |
(save-window-excursion |
|
1126 |
(when ,tempvar (find-file ,tempvar)) |
|
1127 |
(setq ,to-be-removed (current-buffer)) |
|
1128 |
(goto-char (point-min)) |
|
1129 |
(while (re-search-forward "src_\\S-" nil t) |
|
1130 |
(let ((,datum (save-match-data (org-element-context)))) |
|
1131 |
(when (eq (org-element-type ,datum) 'inline-src-block) |
|
1132 |
(goto-char (match-beginning 0)) |
|
1133 |
(let ((,end (copy-marker (org-element-property :end ,datum)))) |
|
1134 |
,@body |
|
1135 |
(goto-char ,end) |
|
1136 |
(set-marker ,end nil)))))) |
|
1137 |
(unless ,visitedp (kill-buffer ,to-be-removed)) |
|
1138 |
(goto-char ,point)))) |
|
1139 |
|
|
1140 |
;;;###autoload |
|
1141 |
(defmacro org-babel-map-call-lines (file &rest body) |
|
1142 |
"Evaluate BODY forms on each call line in FILE. |
|
1143 |
If FILE is nil evaluate BODY forms on source blocks in current |
|
1144 |
buffer." |
|
1145 |
(declare (indent 1) (debug (form body))) |
|
1146 |
(org-with-gensyms (datum end point tempvar to-be-removed visitedp) |
|
1147 |
`(let* ((case-fold-search t) |
|
1148 |
(,tempvar ,file) |
|
1149 |
(,visitedp (or (null ,tempvar) |
|
1150 |
(get-file-buffer (expand-file-name ,tempvar)))) |
|
1151 |
(,point (point)) |
|
1152 |
,to-be-removed) |
|
1153 |
(save-window-excursion |
|
1154 |
(when ,tempvar (find-file ,tempvar)) |
|
1155 |
(setq ,to-be-removed (current-buffer)) |
|
1156 |
(goto-char (point-min)) |
|
1157 |
(while (re-search-forward "call_\\S-\\|^[ \t]*#\\+CALL:" nil t) |
|
1158 |
(let ((,datum (save-match-data (org-element-context)))) |
|
1159 |
(when (memq (org-element-type ,datum) |
|
1160 |
'(babel-call inline-babel-call)) |
|
1161 |
(goto-char (match-beginning 0)) |
|
1162 |
(let ((,end (copy-marker (org-element-property :end ,datum)))) |
|
1163 |
,@body |
|
1164 |
(goto-char ,end) |
|
1165 |
(set-marker ,end nil)))))) |
|
1166 |
(unless ,visitedp (kill-buffer ,to-be-removed)) |
|
1167 |
(goto-char ,point)))) |
|
1168 |
|
|
1169 |
;;;###autoload |
|
1170 |
(defmacro org-babel-map-executables (file &rest body) |
|
1171 |
"Evaluate BODY forms on each active Babel code in FILE. |
|
1172 |
If FILE is nil evaluate BODY forms on source blocks in current |
|
1173 |
buffer." |
|
1174 |
(declare (indent 1) (debug (form body))) |
|
1175 |
(org-with-gensyms (datum end point tempvar to-be-removed visitedp) |
|
1176 |
`(let* ((case-fold-search t) |
|
1177 |
(,tempvar ,file) |
|
1178 |
(,visitedp (or (null ,tempvar) |
|
1179 |
(get-file-buffer (expand-file-name ,tempvar)))) |
|
1180 |
(,point (point)) |
|
1181 |
,to-be-removed) |
|
1182 |
(save-window-excursion |
|
1183 |
(when ,tempvar (find-file ,tempvar)) |
|
1184 |
(setq ,to-be-removed (current-buffer)) |
|
1185 |
(goto-char (point-min)) |
|
1186 |
(while (re-search-forward |
|
1187 |
"\\(call\\|src\\)_\\|^[ \t]*#\\+\\(BEGIN_SRC\\|CALL:\\)" nil t) |
|
1188 |
(let ((,datum (save-match-data (org-element-context)))) |
|
1189 |
(when (memq (org-element-type ,datum) |
|
1190 |
'(babel-call inline-babel-call inline-src-block |
|
1191 |
src-block)) |
|
1192 |
(goto-char (match-beginning 0)) |
|
1193 |
(let ((,end (copy-marker (org-element-property :end ,datum)))) |
|
1194 |
,@body |
|
1195 |
(goto-char ,end) |
|
1196 |
(set-marker ,end nil)))))) |
|
1197 |
(unless ,visitedp (kill-buffer ,to-be-removed)) |
|
1198 |
(goto-char ,point)))) |
|
1199 |
|
|
1200 |
;;;###autoload |
|
1201 |
(defun org-babel-execute-buffer (&optional arg) |
|
1202 |
"Execute source code blocks in a buffer. |
|
1203 |
Call `org-babel-execute-src-block' on every source block in |
|
1204 |
the current buffer." |
|
1205 |
(interactive "P") |
|
1206 |
(org-babel-eval-wipe-error-buffer) |
|
1207 |
(org-save-outline-visibility t |
|
1208 |
(org-babel-map-executables nil |
|
1209 |
(if (memq (org-element-type (org-element-context)) |
|
1210 |
'(babel-call inline-babel-call)) |
|
1211 |
(org-babel-lob-execute-maybe) |
|
1212 |
(org-babel-execute-src-block arg))))) |
|
1213 |
|
|
1214 |
;;;###autoload |
|
1215 |
(defun org-babel-execute-subtree (&optional arg) |
|
1216 |
"Execute source code blocks in a subtree. |
|
1217 |
Call `org-babel-execute-src-block' on every source block in |
|
1218 |
the current subtree." |
|
1219 |
(interactive "P") |
|
1220 |
(save-restriction |
|
1221 |
(save-excursion |
|
1222 |
(org-narrow-to-subtree) |
|
1223 |
(org-babel-execute-buffer arg) |
|
1224 |
(widen)))) |
|
1225 |
|
|
1226 |
;;;###autoload |
|
1227 |
(defun org-babel-sha1-hash (&optional info) |
|
1228 |
"Generate an sha1 hash based on the value of info." |
|
1229 |
(interactive) |
|
1230 |
(let ((print-level nil) |
|
1231 |
(info (or info (org-babel-get-src-block-info)))) |
|
1232 |
(setf (nth 2 info) |
|
1233 |
(sort (copy-sequence (nth 2 info)) |
|
1234 |
(lambda (a b) (string< (car a) (car b))))) |
|
1235 |
(let* ((rm (lambda (lst) |
|
1236 |
(dolist (p '("replace" "silent" "none" |
|
1237 |
"append" "prepend")) |
|
1238 |
(setq lst (remove p lst))) |
|
1239 |
lst)) |
|
1240 |
(norm (lambda (arg) |
|
1241 |
(let ((v (if (and (listp (cdr arg)) (null (cddr arg))) |
|
1242 |
(copy-sequence (cdr arg)) |
|
1243 |
(cdr arg)))) |
|
1244 |
(when (and v (not (and (sequencep v) |
|
1245 |
(not (consp v)) |
|
1246 |
(= (length v) 0)))) |
|
1247 |
(cond |
|
1248 |
((and (listp v) ; lists are sorted |
|
1249 |
(member (car arg) '(:result-params))) |
|
1250 |
(sort (funcall rm v) #'string<)) |
|
1251 |
((and (stringp v) ; strings are sorted |
|
1252 |
(member (car arg) '(:results :exports))) |
|
1253 |
(mapconcat #'identity (sort (funcall rm (split-string v)) |
|
1254 |
#'string<) " ")) |
|
1255 |
(t v)))))) |
|
1256 |
;; expanded body |
|
1257 |
(lang (nth 0 info)) |
|
1258 |
(params (nth 2 info)) |
|
1259 |
(body (if (org-babel-noweb-p params :eval) |
|
1260 |
(org-babel-expand-noweb-references info) (nth 1 info))) |
|
1261 |
(expand-cmd (intern (concat "org-babel-expand-body:" lang))) |
|
1262 |
(assignments-cmd (intern (concat "org-babel-variable-assignments:" |
|
1263 |
lang))) |
|
1264 |
(expanded |
|
1265 |
(if (fboundp expand-cmd) (funcall expand-cmd body params) |
|
1266 |
(org-babel-expand-body:generic |
|
1267 |
body params (and (fboundp assignments-cmd) |
|
1268 |
(funcall assignments-cmd params)))))) |
|
1269 |
(let* ((it (format "%s-%s" |
|
1270 |
(mapconcat |
|
1271 |
#'identity |
|
1272 |
(delq nil (mapcar (lambda (arg) |
|
1273 |
(let ((normalized (funcall norm arg))) |
|
1274 |
(when normalized |
|
1275 |
(format "%S" normalized)))) |
|
1276 |
(nth 2 info))) ":") |
|
1277 |
expanded)) |
|
1278 |
(hash (sha1 it))) |
|
1279 |
(when (called-interactively-p 'interactive) (message hash)) |
|
1280 |
hash)))) |
|
1281 |
|
|
1282 |
(defun org-babel-current-result-hash (&optional info) |
|
1283 |
"Return the current in-buffer hash." |
|
1284 |
(let ((result (org-babel-where-is-src-block-result nil info))) |
|
1285 |
(when result |
|
1286 |
(org-with-wide-buffer |
|
1287 |
(goto-char result) |
|
1288 |
(looking-at org-babel-result-regexp) |
|
1289 |
(match-string-no-properties 1))))) |
|
1290 |
|
|
1291 |
(defun org-babel-set-current-result-hash (hash info) |
|
1292 |
"Set the current in-buffer hash to HASH." |
|
1293 |
(org-with-wide-buffer |
|
1294 |
(goto-char (org-babel-where-is-src-block-result nil info)) |
|
1295 |
(looking-at org-babel-result-regexp) |
|
1296 |
(goto-char (match-beginning 1)) |
|
1297 |
(mapc #'delete-overlay (overlays-at (point))) |
|
1298 |
(forward-char org-babel-hash-show) |
|
1299 |
(mapc #'delete-overlay (overlays-at (point))) |
|
1300 |
(replace-match hash nil nil nil 1) |
|
1301 |
(beginning-of-line) |
|
1302 |
(org-babel-hide-hash))) |
|
1303 |
|
|
1304 |
(defun org-babel-hide-hash () |
|
1305 |
"Hide the hash in the current results line. |
|
1306 |
Only the initial `org-babel-hash-show' characters of the hash |
|
1307 |
will remain visible." |
|
1308 |
(add-to-invisibility-spec '(org-babel-hide-hash . t)) |
|
1309 |
(save-excursion |
|
1310 |
(when (and (re-search-forward org-babel-result-regexp nil t) |
|
1311 |
(match-string 1)) |
|
1312 |
(let* ((start (match-beginning 1)) |
|
1313 |
(hide-start (+ org-babel-hash-show start)) |
|
1314 |
(end (match-end 1)) |
|
1315 |
(hash (match-string 1)) |
|
1316 |
ov1 ov2) |
|
1317 |
(setq ov1 (make-overlay start hide-start)) |
|
1318 |
(setq ov2 (make-overlay hide-start end)) |
|
1319 |
(overlay-put ov2 'invisible 'org-babel-hide-hash) |
|
1320 |
(overlay-put ov1 'babel-hash hash))))) |
|
1321 |
|
|
1322 |
(defun org-babel-hide-all-hashes () |
|
1323 |
"Hide the hash in the current buffer. |
|
1324 |
Only the initial `org-babel-hash-show' characters of each hash |
|
1325 |
will remain visible. This function should be called as part of |
|
1326 |
the `org-mode-hook'." |
|
1327 |
(save-excursion |
|
1328 |
(while (and (not org-babel-hash-show-time) |
|
1329 |
(re-search-forward org-babel-result-regexp nil t)) |
|
1330 |
(goto-char (match-beginning 0)) |
|
1331 |
(org-babel-hide-hash) |
|
1332 |
(goto-char (match-end 0))))) |
|
1333 |
(add-hook 'org-mode-hook 'org-babel-hide-all-hashes) |
|
1334 |
|
|
1335 |
(defun org-babel-hash-at-point (&optional point) |
|
1336 |
"Return the value of the hash at POINT. |
|
1337 |
\\<org-mode-map>\ |
|
1338 |
The hash is also added as the last element of the kill ring. |
|
1339 |
This can be called with `\\[org-ctrl-c-ctrl-c]'." |
|
1340 |
(interactive) |
|
1341 |
(let ((hash (car (delq nil (mapcar |
|
1342 |
(lambda (ol) (overlay-get ol 'babel-hash)) |
|
1343 |
(overlays-at (or point (point)))))))) |
|
1344 |
(when hash (kill-new hash) (message hash)))) |
|
1345 |
|
|
1346 |
(defun org-babel-result-hide-spec () |
|
1347 |
"Hide portions of results lines. |
|
1348 |
Add `org-babel-hide-result' as an invisibility spec for hiding |
|
1349 |
portions of results lines." |
|
1350 |
(add-to-invisibility-spec '(org-babel-hide-result . t))) |
|
1351 |
(add-hook 'org-mode-hook 'org-babel-result-hide-spec) |
|
1352 |
|
|
1353 |
(defvar org-babel-hide-result-overlays nil |
|
1354 |
"Overlays hiding results.") |
|
1355 |
|
|
1356 |
(defun org-babel-result-hide-all () |
|
1357 |
"Fold all results in the current buffer." |
|
1358 |
(interactive) |
|
1359 |
(org-babel-show-result-all) |
|
1360 |
(save-excursion |
|
1361 |
(while (re-search-forward org-babel-result-regexp nil t) |
|
1362 |
(save-excursion (goto-char (match-beginning 0)) |
|
1363 |
(org-babel-hide-result-toggle-maybe))))) |
|
1364 |
|
|
1365 |
(defun org-babel-show-result-all () |
|
1366 |
"Unfold all results in the current buffer." |
|
1367 |
(mapc 'delete-overlay org-babel-hide-result-overlays) |
|
1368 |
(setq org-babel-hide-result-overlays nil)) |
|
1369 |
|
|
1370 |
;;;###autoload |
|
1371 |
(defun org-babel-hide-result-toggle-maybe () |
|
1372 |
"Toggle visibility of result at point." |
|
1373 |
(interactive) |
|
1374 |
(let ((case-fold-search t)) |
|
1375 |
(if (save-excursion |
|
1376 |
(beginning-of-line 1) |
|
1377 |
(looking-at org-babel-result-regexp)) |
|
1378 |
(progn (org-babel-hide-result-toggle) |
|
1379 |
t) ;; to signal that we took action |
|
1380 |
nil))) ;; to signal that we did not |
|
1381 |
|
|
1382 |
(defun org-babel-hide-result-toggle (&optional force) |
|
1383 |
"Toggle the visibility of the current result." |
|
1384 |
(interactive) |
|
1385 |
(save-excursion |
|
1386 |
(beginning-of-line) |
|
1387 |
(if (re-search-forward org-babel-result-regexp nil t) |
|
1388 |
(let ((start (progn (beginning-of-line 2) (- (point) 1))) |
|
1389 |
(end (progn |
|
1390 |
(while (looking-at org-babel-multi-line-header-regexp) |
|
1391 |
(forward-line 1)) |
|
1392 |
(goto-char (- (org-babel-result-end) 1)) (point))) |
|
1393 |
ov) |
|
1394 |
(if (memq t (mapcar (lambda (overlay) |
|
1395 |
(eq (overlay-get overlay 'invisible) |
|
1396 |
'org-babel-hide-result)) |
|
1397 |
(overlays-at start))) |
|
1398 |
(when (or (not force) (eq force 'off)) |
|
1399 |
(mapc (lambda (ov) |
|
1400 |
(when (member ov org-babel-hide-result-overlays) |
|
1401 |
(setq org-babel-hide-result-overlays |
|
1402 |
(delq ov org-babel-hide-result-overlays))) |
|
1403 |
(when (eq (overlay-get ov 'invisible) |
|
1404 |
'org-babel-hide-result) |
|
1405 |
(delete-overlay ov))) |
|
1406 |
(overlays-at start))) |
|
1407 |
(setq ov (make-overlay start end)) |
|
1408 |
(overlay-put ov 'invisible 'org-babel-hide-result) |
|
1409 |
;; make the block accessible to isearch |
|
1410 |
(overlay-put |
|
1411 |
ov 'isearch-open-invisible |
|
1412 |
(lambda (ov) |
|
1413 |
(when (member ov org-babel-hide-result-overlays) |
|
1414 |
(setq org-babel-hide-result-overlays |
|
1415 |
(delq ov org-babel-hide-result-overlays))) |
|
1416 |
(when (eq (overlay-get ov 'invisible) |
|
1417 |
'org-babel-hide-result) |
|
1418 |
(delete-overlay ov)))) |
|
1419 |
(push ov org-babel-hide-result-overlays))) |
|
1420 |
(error "Not looking at a result line")))) |
|
1421 |
|
|
1422 |
;; org-tab-after-check-for-cycling-hook |
|
1423 |
(add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe) |
|
1424 |
;; Remove overlays when changing major mode |
|
1425 |
(add-hook 'org-mode-hook |
|
1426 |
(lambda () (add-hook 'change-major-mode-hook |
|
1427 |
'org-babel-show-result-all 'append 'local))) |
|
1428 |
|
|
1429 |
(defvar org-file-properties) |
|
1430 |
(defun org-babel-params-from-properties (&optional lang) |
|
1431 |
"Retrieve parameters specified as properties. |
|
1432 |
Return a list of association lists of source block params |
|
1433 |
specified in the properties of the current outline entry." |
|
1434 |
(save-match-data |
|
1435 |
(list |
|
1436 |
;; header arguments specified with the header-args property at |
|
1437 |
;; point of call. |
|
1438 |
(org-babel-parse-header-arguments |
|
1439 |
(org-entry-get org-babel-current-src-block-location |
|
1440 |
"header-args" |
|
1441 |
'inherit)) |
|
1442 |
(and lang ; language-specific header arguments at point of call |
|
1443 |
(org-babel-parse-header-arguments |
|
1444 |
(org-entry-get org-babel-current-src-block-location |
|
1445 |
(concat "header-args:" lang) |
|
1446 |
'inherit)))))) |
|
1447 |
|
|
1448 |
(defun org-babel-balanced-split (string alts) |
|
1449 |
"Split STRING on instances of ALTS. |
|
1450 |
ALTS is a character, or cons of two character options where each |
|
1451 |
option may be either the numeric code of a single character or |
|
1452 |
a list of character alternatives. For example, to split on |
|
1453 |
balanced instances of \"[ \t]:\", set ALTS to ((32 9) . 58)." |
|
1454 |
(with-temp-buffer |
|
1455 |
(insert string) |
|
1456 |
(goto-char (point-min)) |
|
1457 |
(let ((splitp (lambda (past next) |
|
1458 |
;; Non-nil when there should be a split after NEXT |
|
1459 |
;; character. PAST is the character before NEXT. |
|
1460 |
(pcase alts |
|
1461 |
(`(,(and first (pred consp)) . ,(and second (pred consp))) |
|
1462 |
(and (memq past first) (memq next second))) |
|
1463 |
(`(,first . ,(and second (pred consp))) |
|
1464 |
(and (eq past first) (memq next second))) |
|
1465 |
(`(,(and first (pred consp)) . ,second) |
|
1466 |
(and (memq past first) (eq next second))) |
|
1467 |
(`(,first . ,second) |
|
1468 |
(and (eq past first) (eq next second))) |
|
1469 |
((pred (eq next)) t) |
|
1470 |
(_ nil)))) |
|
1471 |
(partial nil) |
|
1472 |
(result nil)) |
|
1473 |
(while (not (eobp)) |
|
1474 |
(cond |
|
1475 |
((funcall splitp (char-before) (char-after)) |
|
1476 |
;; There is a split after point. If ALTS is two-folds, |
|
1477 |
;; remove last parsed character as it belongs to ALTS. |
|
1478 |
(when (consp alts) (pop partial)) |
|
1479 |
;; Include elements parsed so far in RESULTS and flush |
|
1480 |
;; partial parsing. |
|
1481 |
(when partial |
|
1482 |
(push (apply #'string (nreverse partial)) result) |
|
1483 |
(setq partial nil)) |
|
1484 |
(forward-char)) |
|
1485 |
((memq (char-after) '(?\( ?\[)) |
|
1486 |
;; Include everything between balanced brackets. |
|
1487 |
(let* ((origin (point)) |
|
1488 |
(after (char-after)) |
|
1489 |
(openings (list after))) |
|
1490 |
(forward-char) |
|
1491 |
(while (and openings (re-search-forward "[]()]" nil t)) |
|
1492 |
(pcase (char-before) |
|
1493 |
((and match (or ?\[ ?\()) (push match openings)) |
|
1494 |
(?\] (when (eq ?\[ (car openings)) (pop openings))) |
|
1495 |
(_ (when (eq ?\( (car openings)) (pop openings))))) |
|
1496 |
(if (null openings) |
|
1497 |
(setq partial |
|
1498 |
(nconc (nreverse (string-to-list |
|
1499 |
(buffer-substring origin (point)))) |
|
1500 |
partial)) |
|
1501 |
;; Un-balanced bracket. Backtrack. |
|
1502 |
(push after partial) |
|
1503 |
(goto-char (1+ origin))))) |
|
1504 |
((and (eq ?\" (char-after)) (not (eq ?\\ (char-before)))) |
|
1505 |
;; Include everything from current double quote to next |
|
1506 |
;; non-escaped double quote. |
|
1507 |
(let ((origin (point))) |
|
1508 |
(if (re-search-forward "[^\\]\"" nil t) |
|
1509 |
(setq partial |
|
1510 |
(nconc (nreverse (string-to-list |
|
1511 |
(buffer-substring origin (point)))) |
|
1512 |
partial)) |
|
1513 |
;; No closing double quote. Backtrack. |
|
1514 |
(push ?\" partial) |
|
1515 |
(forward-char)))) |
|
1516 |
(t (push (char-after) partial) |
|
1517 |
(forward-char)))) |
|
1518 |
;; Add pending parsing and return result. |
|
1519 |
(when partial (push (apply #'string (nreverse partial)) result)) |
|
1520 |
(nreverse result)))) |
|
1521 |
|
|
1522 |
(defun org-babel-join-splits-near-ch (ch list) |
|
1523 |
"Join splits where \"=\" is on either end of the split." |
|
1524 |
(let ((last= (lambda (str) (= ch (aref str (1- (length str)))))) |
|
1525 |
(first= (lambda (str) (= ch (aref str 0))))) |
|
1526 |
(reverse |
|
1527 |
(cl-reduce (lambda (acc el) |
|
1528 |
(let ((head (car acc))) |
|
1529 |
(if (and head (or (funcall last= head) (funcall first= el))) |
|
1530 |
(cons (concat head el) (cdr acc)) |
|
1531 |
(cons el acc)))) |
|
1532 |
list :initial-value nil)))) |
|
1533 |
|
|
1534 |
(defun org-babel-parse-header-arguments (arg-string) |
|
1535 |
"Parse a string of header arguments returning an alist." |
|
1536 |
(when (> (length arg-string) 0) |
|
1537 |
(org-babel-parse-multiple-vars |
|
1538 |
(delq nil |
|
1539 |
(mapcar |
|
1540 |
(lambda (arg) |
|
1541 |
(if (string-match |
|
1542 |
"\\([^ \f\t\n\r\v]+\\)[ \f\t\n\r\v]+\\([^ \f\t\n\r\v]+.*\\)" |
|
1543 |
arg) |
|
1544 |
(cons (intern (match-string 1 arg)) |
|
1545 |
(org-babel-read (org-babel-chomp (match-string 2 arg)))) |
|
1546 |
(cons (intern (org-babel-chomp arg)) nil))) |
|
1547 |
(let ((raw (org-babel-balanced-split arg-string '((32 9) . 58)))) |
|
1548 |
(cons (car raw) (mapcar (lambda (r) (concat ":" r)) (cdr raw))))))))) |
|
1549 |
|
|
1550 |
(defun org-babel-parse-multiple-vars (header-arguments) |
|
1551 |
"Expand multiple variable assignments behind a single :var keyword. |
|
1552 |
|
|
1553 |
This allows expression of multiple variables with one :var as |
|
1554 |
shown below. |
|
1555 |
|
|
1556 |
#+PROPERTY: var foo=1, bar=2" |
|
1557 |
(let (results) |
|
1558 |
(mapc (lambda (pair) |
|
1559 |
(if (eq (car pair) :var) |
|
1560 |
(mapcar (lambda (v) (push (cons :var (org-trim v)) results)) |
|
1561 |
(org-babel-join-splits-near-ch |
|
1562 |
61 (org-babel-balanced-split (cdr pair) 32))) |
|
1563 |
(push pair results))) |
|
1564 |
header-arguments) |
|
1565 |
(nreverse results))) |
|
1566 |
|
|
1567 |
(defun org-babel-process-params (params) |
|
1568 |
"Expand variables in PARAMS and add summary parameters." |
|
1569 |
(let* ((processed-vars (mapcar (lambda (el) |
|
1570 |
(if (consp el) |
|
1571 |
el |
|
1572 |
(org-babel-ref-parse el))) |
|
1573 |
(org-babel--get-vars params))) |
|
1574 |
(vars-and-names (if (and (assq :colname-names params) |
|
1575 |
(assq :rowname-names params)) |
|
1576 |
(list processed-vars) |
|
1577 |
(org-babel-disassemble-tables |
|
1578 |
processed-vars |
|
1579 |
(cdr (assq :hlines params)) |
|
1580 |
(cdr (assq :colnames params)) |
|
1581 |
(cdr (assq :rownames params))))) |
|
1582 |
(raw-result (or (cdr (assq :results params)) "")) |
|
1583 |
(result-params (delete-dups |
|
1584 |
(append |
|
1585 |
(split-string (if (stringp raw-result) |
|
1586 |
raw-result |
|
1587 |
(eval raw-result t))) |
|
1588 |
(cdr (assq :result-params params)))))) |
|
1589 |
(append |
|
1590 |
(mapcar (lambda (var) (cons :var var)) (car vars-and-names)) |
|
1591 |
(list |
|
1592 |
(cons :colname-names (or (cdr (assq :colname-names params)) |
|
1593 |
(cadr vars-and-names))) |
|
1594 |
(cons :rowname-names (or (cdr (assq :rowname-names params)) |
|
1595 |
(cl-caddr vars-and-names))) |
|
1596 |
(cons :result-params result-params) |
|
1597 |
(cons :result-type (cond ((member "output" result-params) 'output) |
|
1598 |
((member "value" result-params) 'value) |
|
1599 |
(t 'value)))) |
|
1600 |
(cl-remove-if |
|
1601 |
(lambda (x) (memq (car x) '(:colname-names :rowname-names :result-params |
|
1602 |
:result-type :var))) |
|
1603 |
params)))) |
|
1604 |
|
|
1605 |
;; row and column names |
|
1606 |
(defun org-babel-del-hlines (table) |
|
1607 |
"Remove all `hline's from TABLE." |
|
1608 |
(remq 'hline table)) |
|
1609 |
|
|
1610 |
(defun org-babel-get-colnames (table) |
|
1611 |
"Return the column names of TABLE. |
|
1612 |
Return a cons cell, the `car' of which contains the TABLE less |
|
1613 |
colnames, and the `cdr' of which contains a list of the column |
|
1614 |
names." |
|
1615 |
(if (eq 'hline (nth 1 table)) |
|
1616 |
(cons (cddr table) (car table)) |
|
1617 |
(cons (cdr table) (car table)))) |
|
1618 |
|
|
1619 |
(defun org-babel-get-rownames (table) |
|
1620 |
"Return the row names of TABLE. |
|
1621 |
Return a cons cell, the `car' of which contains the TABLE less |
|
1622 |
rownames, and the `cdr' of which contains a list of the rownames. |
|
1623 |
Note: this function removes any hlines in TABLE." |
|
1624 |
(let* ((table (org-babel-del-hlines table)) |
|
1625 |
(rownames (funcall (lambda () |
|
1626 |
(let ((tp table)) |
|
1627 |
(mapcar |
|
1628 |
(lambda (_row) |
|
1629 |
(prog1 |
|
1630 |
(pop (car tp)) |
|
1631 |
(setq tp (cdr tp)))) |
|
1632 |
table)))))) |
|
1633 |
(cons table rownames))) |
|
1634 |
|
|
1635 |
(defun org-babel-put-colnames (table colnames) |
|
1636 |
"Add COLNAMES to TABLE if they exist." |
|
1637 |
(if colnames (apply 'list colnames 'hline table) table)) |
|
1638 |
|
|
1639 |
(defun org-babel-put-rownames (table rownames) |
|
1640 |
"Add ROWNAMES to TABLE if they exist." |
|
1641 |
(if rownames |
|
1642 |
(mapcar (lambda (row) |
|
1643 |
(if (listp row) |
|
1644 |
(cons (or (pop rownames) "") row) |
|
1645 |
row)) table) |
|
1646 |
table)) |
|
1647 |
|
|
1648 |
(defun org-babel-pick-name (names selector) |
|
1649 |
"Select one out of an alist of row or column names. |
|
1650 |
SELECTOR can be either a list of names in which case those names |
|
1651 |
will be returned directly, or an index into the list NAMES in |
|
1652 |
which case the indexed names will be return." |
|
1653 |
(if (listp selector) |
|
1654 |
selector |
|
1655 |
(when names |
|
1656 |
(if (and selector (symbolp selector) (not (equal t selector))) |
|
1657 |
(cdr (assoc selector names)) |
|
1658 |
(if (integerp selector) |
|
1659 |
(nth (- selector 1) names) |
|
1660 |
(cdr (car (last names)))))))) |
|
1661 |
|
|
1662 |
(defun org-babel-disassemble-tables (vars hlines colnames rownames) |
|
1663 |
"Parse tables for further processing. |
|
1664 |
Process the variables in VARS according to the HLINES, |
|
1665 |
ROWNAMES and COLNAMES header arguments. Return a list consisting |
|
1666 |
of the vars, cnames and rnames." |
|
1667 |
(let (cnames rnames) |
|
1668 |
(list |
|
1669 |
(mapcar |
|
1670 |
(lambda (var) |
|
1671 |
(when (listp (cdr var)) |
|
1672 |
(when (and (not (equal colnames "no")) |
|
1673 |
(or colnames (and (eq (nth 1 (cdr var)) 'hline) |
|
1674 |
(not (member 'hline (cddr (cdr var))))))) |
|
1675 |
(let ((both (org-babel-get-colnames (cdr var)))) |
|
1676 |
(setq cnames (cons (cons (car var) (cdr both)) |
|
1677 |
cnames)) |
|
1678 |
(setq var (cons (car var) (car both))))) |
|
1679 |
(when (and rownames (not (equal rownames "no"))) |
|
1680 |
(let ((both (org-babel-get-rownames (cdr var)))) |
|
1681 |
(setq rnames (cons (cons (car var) (cdr both)) |
|
1682 |
rnames)) |
|
1683 |
(setq var (cons (car var) (car both))))) |
|
1684 |
(when (and hlines (not (equal hlines "yes"))) |
|
1685 |
(setq var (cons (car var) (org-babel-del-hlines (cdr var)))))) |
|
1686 |
var) |
|
1687 |
vars) |
|
1688 |
(reverse cnames) (reverse rnames)))) |
|
1689 |
|
|
1690 |
(defun org-babel-reassemble-table (table colnames rownames) |
|
1691 |
"Add column and row names to a table. |
|
1692 |
Given a TABLE and set of COLNAMES and ROWNAMES add the names |
|
1693 |
to the table for reinsertion to org-mode." |
|
1694 |
(if (listp table) |
|
1695 |
(let ((table (if (and rownames (= (length table) (length rownames))) |
|
1696 |
(org-babel-put-rownames table rownames) table))) |
|
1697 |
(if (and colnames (listp (car table)) (= (length (car table)) |
|
1698 |
(length colnames))) |
|
1699 |
(org-babel-put-colnames table colnames) table)) |
|
1700 |
table)) |
|
1701 |
|
|
1702 |
(defun org-babel-where-is-src-block-head (&optional src-block) |
|
1703 |
"Find where the current source block begins. |
|
1704 |
|
|
1705 |
If optional argument SRC-BLOCK is `src-block' type element, find |
|
1706 |
its current beginning instead. |
|
1707 |
|
|
1708 |
Return the point at the beginning of the current source block. |
|
1709 |
Specifically at the beginning of the #+BEGIN_SRC line. Also set |
|
1710 |
match-data relatively to `org-babel-src-block-regexp', which see. |
|
1711 |
If the point is not on a source block then return nil." |
|
1712 |
(let ((element (or src-block (org-element-at-point)))) |
|
1713 |
(when (eq (org-element-type element) 'src-block) |
|
1714 |
(let ((end (org-element-property :end element))) |
|
1715 |
(org-with-wide-buffer |
|
1716 |
;; Ensure point is not on a blank line after the block. |
|
1717 |
(beginning-of-line) |
|
1718 |
(skip-chars-forward " \r\t\n" end) |
|
1719 |
(when (< (point) end) |
|
1720 |
(prog1 (goto-char (org-element-property :post-affiliated element)) |
|
1721 |
(looking-at org-babel-src-block-regexp)))))))) |
|
1722 |
|
|
1723 |
;;;###autoload |
|
1724 |
(defun org-babel-goto-src-block-head () |
|
1725 |
"Go to the beginning of the current code block." |
|
1726 |
(interactive) |
|
1727 |
(let ((head (org-babel-where-is-src-block-head))) |
|
1728 |
(if head (goto-char head) (error "Not currently in a code block")))) |
|
1729 |
|
|
1730 |
;;;###autoload |
|
1731 |
(defun org-babel-goto-named-src-block (name) |
|
1732 |
"Go to a named source-code block." |
|
1733 |
(interactive |
|
1734 |
(let ((completion-ignore-case t) |
|
1735 |
(case-fold-search t) |
|
1736 |
(all-block-names (org-babel-src-block-names))) |
|
1737 |
(list (completing-read |
|
1738 |
"source-block name: " all-block-names nil t |
|
1739 |
(let* ((context (org-element-context)) |
|
1740 |
(type (org-element-type context)) |
|
1741 |
(noweb-ref |
|
1742 |
(and (memq type '(inline-src-block src-block)) |
|
1743 |
(org-in-regexp (org-babel-noweb-wrap))))) |
|
1744 |
(cond |
|
1745 |
(noweb-ref |
|
1746 |
(buffer-substring |
|
1747 |
(+ (car noweb-ref) (length org-babel-noweb-wrap-start)) |
|
1748 |
(- (cdr noweb-ref) (length org-babel-noweb-wrap-end)))) |
|
1749 |
((memq type '(babel-call inline-babel-call)) ;#+CALL: |
|
1750 |
(org-element-property :call context)) |
|
1751 |
((car (org-element-property :results context))) ;#+RESULTS: |
|
1752 |
((let ((symbol (thing-at-point 'symbol))) ;Symbol. |
|
1753 |
(and symbol |
|
1754 |
(member-ignore-case symbol all-block-names) |
|
1755 |
symbol))) |
|
1756 |
(t ""))))))) |
|
1757 |
(let ((point (org-babel-find-named-block name))) |
|
1758 |
(if point |
|
1759 |
;; Taken from `org-open-at-point'. |
|
1760 |
(progn (org-mark-ring-push) (goto-char point) (org-show-context)) |
|
1761 |
(message "source-code block `%s' not found in this buffer" name)))) |
|
1762 |
|
|
1763 |
(defun org-babel-find-named-block (name) |
|
1764 |
"Find a named source-code block. |
|
1765 |
Return the location of the source block identified by source |
|
1766 |
NAME, or nil if no such block exists. Set match data according |
|
1767 |
to `org-babel-named-src-block-regexp'." |
|
1768 |
(save-excursion |
|
1769 |
(goto-char (point-min)) |
|
1770 |
(let ((regexp (org-babel-named-src-block-regexp-for-name name))) |
|
1771 |
(or (and (looking-at regexp) |
|
1772 |
(progn (goto-char (match-beginning 1)) |
|
1773 |
(line-beginning-position))) |
|
1774 |
(ignore-errors (org-next-block 1 nil regexp)))))) |
|
1775 |
|
|
1776 |
(defun org-babel-src-block-names (&optional file) |
|
1777 |
"Returns the names of source blocks in FILE or the current buffer." |
|
1778 |
(with-current-buffer (if file (find-file-noselect file) (current-buffer)) |
|
1779 |
(org-with-point-at 1 |
|
1780 |
(let ((regexp "^[ \t]*#\\+begin_src ") |
|
1781 |
(case-fold-search t) |
|
1782 |
(names nil)) |
|
1783 |
(while (re-search-forward regexp nil t) |
|
1784 |
(let ((element (org-element-at-point))) |
|
1785 |
(when (eq 'src-block (org-element-type element)) |
|
1786 |
(let ((name (org-element-property :name element))) |
|
1787 |
(when name (push name names)))))) |
|
1788 |
names)))) |
|
1789 |
|
|
1790 |
;;;###autoload |
|
1791 |
(defun org-babel-goto-named-result (name) |
|
1792 |
"Go to a named result." |
|
1793 |
(interactive |
|
1794 |
(let ((completion-ignore-case t)) |
|
1795 |
(list (completing-read "Source-block name: " |
|
1796 |
(org-babel-result-names) nil t)))) |
|
1797 |
(let ((point (org-babel-find-named-result name))) |
|
1798 |
(if point |
|
1799 |
;; taken from `org-open-at-point' |
|
1800 |
(progn (goto-char point) (org-show-context)) |
|
1801 |
(message "result `%s' not found in this buffer" name)))) |
|
1802 |
|
|
1803 |
(defun org-babel-find-named-result (name) |
|
1804 |
"Find a named result. |
|
1805 |
Return the location of the result named NAME in the current |
|
1806 |
buffer or nil if no such result exists." |
|
1807 |
(save-excursion |
|
1808 |
(goto-char (point-min)) |
|
1809 |
(let ((case-fold-search t) |
|
1810 |
(re (format "^[ \t]*#\\+%s.*?:[ \t]*%s[ \t]*$" |
|
1811 |
org-babel-results-keyword |
|
1812 |
(regexp-quote name)))) |
|
1813 |
(catch :found |
|
1814 |
(while (re-search-forward re nil t) |
|
1815 |
(let ((element (org-element-at-point))) |
|
1816 |
(when (or (eq (org-element-type element) 'keyword) |
|
1817 |
(< (point) |
|
1818 |
(org-element-property :post-affiliated element))) |
|
1819 |
(throw :found (line-beginning-position))))))))) |
|
1820 |
|
|
1821 |
(defun org-babel-result-names (&optional file) |
|
1822 |
"Returns the names of results in FILE or the current buffer." |
|
1823 |
(save-excursion |
|
1824 |
(when file (find-file file)) (goto-char (point-min)) |
|
1825 |
(let ((case-fold-search t) names) |
|
1826 |
(while (re-search-forward org-babel-result-w-name-regexp nil t) |
|
1827 |
(setq names (cons (match-string-no-properties 9) names))) |
|
1828 |
names))) |
|
1829 |
|
|
1830 |
;;;###autoload |
|
1831 |
(defun org-babel-next-src-block (&optional arg) |
|
1832 |
"Jump to the next source block. |
|
1833 |
With optional prefix argument ARG, jump forward ARG many source blocks." |
|
1834 |
(interactive "p") |
|
1835 |
(org-next-block arg nil org-babel-src-block-regexp)) |
|
1836 |
|
|
1837 |
;;;###autoload |
|
1838 |
(defun org-babel-previous-src-block (&optional arg) |
|
1839 |
"Jump to the previous source block. |
|
1840 |
With optional prefix argument ARG, jump backward ARG many source blocks." |
|
1841 |
(interactive "p") |
|
1842 |
(org-previous-block arg org-babel-src-block-regexp)) |
|
1843 |
|
|
1844 |
(defvar org-babel-load-languages) |
|
1845 |
|
|
1846 |
;;;###autoload |
|
1847 |
(defun org-babel-mark-block () |
|
1848 |
"Mark current src block." |
|
1849 |
(interactive) |
|
1850 |
(let ((head (org-babel-where-is-src-block-head))) |
|
1851 |
(when head |
|
1852 |
(save-excursion |
|
1853 |
(goto-char head) |
|
1854 |
(looking-at org-babel-src-block-regexp)) |
|
1855 |
(push-mark (match-end 5) nil t) |
|
1856 |
(goto-char (match-beginning 5))))) |
|
1857 |
|
|
1858 |
(defun org-babel-demarcate-block (&optional arg) |
|
1859 |
"Wrap or split the code in the region or on the point. |
|
1860 |
When called from inside of a code block the current block is |
|
1861 |
split. When called from outside of a code block a new code block |
|
1862 |
is created. In both cases if the region is demarcated and if the |
|
1863 |
region is not active then the point is demarcated." |
|
1864 |
(interactive "P") |
|
1865 |
(let* ((info (org-babel-get-src-block-info 'light)) |
|
1866 |
(start (org-babel-where-is-src-block-head)) |
|
1867 |
(block (and start (match-string 0))) |
|
1868 |
(headers (and start (match-string 4))) |
|
1869 |
(stars (concat (make-string (or (org-current-level) 1) ?*) " ")) |
|
1870 |
(lower-case-p (and block |
|
1871 |
(let (case-fold-search) |
|
1872 |
(string-match-p "#\\+begin_src" block))))) |
|
1873 |
(if info |
|
1874 |
(mapc |
|
1875 |
(lambda (place) |
|
1876 |
(save-excursion |
|
1877 |
(goto-char place) |
|
1878 |
(let ((lang (nth 0 info)) |
|
1879 |
(indent (make-string (org-get-indentation) ?\s))) |
|
1880 |
(when (string-match "^[[:space:]]*$" |
|
1881 |
(buffer-substring (point-at-bol) |
|
1882 |
(point-at-eol))) |
|
1883 |
(delete-region (point-at-bol) (point-at-eol))) |
|
1884 |
(insert (concat |
|
1885 |
(if (looking-at "^") "" "\n") |
|
1886 |
indent (funcall (if lower-case-p 'downcase 'upcase) "#+end_src\n") |
|
1887 |
(if arg stars indent) "\n" |
|
1888 |
indent (funcall (if lower-case-p 'downcase 'upcase) "#+begin_src ") |
|
1889 |
lang |
|
1890 |
(if (> (length headers) 1) |
|
1891 |
(concat " " headers) headers) |
|
1892 |
(if (looking-at "[\n\r]") |
|
1893 |
"" |
|
1894 |
(concat "\n" (make-string (current-column) ? ))))))) |
|
1895 |
(move-end-of-line 2)) |
|
1896 |
(sort (if (org-region-active-p) (list (mark) (point)) (list (point))) #'>)) |
|
1897 |
(let ((start (point)) |
|
1898 |
(lang (completing-read |
|
1899 |
"Lang: " |
|
1900 |
(mapcar #'symbol-name |
|
1901 |
(delete-dups |
|
1902 |
(append (mapcar #'car org-babel-load-languages) |
|
1903 |
(mapcar (lambda (el) (intern (car el))) |
|
1904 |
org-src-lang-modes)))))) |
|
1905 |
(body (delete-and-extract-region |
|
1906 |
(if (org-region-active-p) (mark) (point)) (point)))) |
|
1907 |
(insert (concat (if (looking-at "^") "" "\n") |
|
1908 |
(if arg (concat stars "\n") "") |
|
1909 |
(funcall (if lower-case-p 'downcase 'upcase) "#+begin_src ") |
|
1910 |
lang "\n" |
|
1911 |
body |
|
1912 |
(if (or (= (length body) 0) |
|
1913 |
(string-suffix-p "\r" body) |
|
1914 |
(string-suffix-p "\n" body)) "" "\n") |
|
1915 |
(funcall (if lower-case-p 'downcase 'upcase) "#+end_src\n"))) |
|
1916 |
(goto-char start) (move-end-of-line 1))))) |
|
1917 |
|
|
1918 |
(defun org-babel--insert-results-keyword (name hash) |
|
1919 |
"Insert RESULTS keyword with NAME value at point. |
|
1920 |
If NAME is nil, results are anonymous. HASH is a string used as |
|
1921 |
the results hash, or nil. Leave point before the keyword." |
|
1922 |
(save-excursion (insert "\n")) ;open line to indent. |
|
1923 |
(org-indent-line) |
|
1924 |
(delete-char 1) |
|
1925 |
(insert (concat "#+" org-babel-results-keyword |
|
1926 |
(cond ((not hash) nil) |
|
1927 |
(org-babel-hash-show-time |
|
1928 |
(format "[%s %s]" |
|
1929 |
(format-time-string "<%F %T>") |
|
1930 |
hash)) |
|
1931 |
(t (format "[%s]" hash))) |
|
1932 |
":" |
|
1933 |
(when name (concat " " name)) |
|
1934 |
"\n")) |
|
1935 |
;; Make sure results are going to be followed by at least one blank |
|
1936 |
;; line so they do not get merged with the next element, e.g., |
|
1937 |
;; |
|
1938 |
;; #+results: |
|
1939 |
;; : 1 |
|
1940 |
;; |
|
1941 |
;; : fixed-width area, unrelated to the above. |
|
1942 |
(unless (looking-at "^[ \t]*$") (save-excursion (insert "\n"))) |
|
1943 |
(beginning-of-line 0) |
|
1944 |
(when hash (org-babel-hide-hash))) |
|
1945 |
|
|
1946 |
(defun org-babel--clear-results-maybe (hash) |
|
1947 |
"Clear results when hash doesn't match HASH. |
|
1948 |
|
|
1949 |
When results hash does not match HASH, remove RESULTS keyword at |
|
1950 |
point, along with related contents. Do nothing if HASH is nil. |
|
1951 |
|
|
1952 |
Return a non-nil value if results were cleared. In this case, |
|
1953 |
leave point where new results should be inserted." |
|
1954 |
(when hash |
|
1955 |
(looking-at org-babel-result-regexp) |
|
1956 |
(unless (string= (match-string 1) hash) |
|
1957 |
(let* ((e (org-element-at-point)) |
|
1958 |
(post (copy-marker (org-element-property :post-affiliated e)))) |
|
1959 |
;; Delete contents. |
|
1960 |
(delete-region post |
|
1961 |
(save-excursion |
|
1962 |
(goto-char (org-element-property :end e)) |
|
1963 |
(skip-chars-backward " \t\n") |
|
1964 |
(line-beginning-position 2))) |
|
1965 |
;; Delete RESULT keyword. However, if RESULTS keyword is |
|
1966 |
;; orphaned, ignore this part. The deletion above already |
|
1967 |
;; took care of it. |
|
1968 |
(unless (= (point) post) |
|
1969 |
(delete-region (line-beginning-position) |
|
1970 |
(line-beginning-position 2))) |
|
1971 |
(goto-char post) |
|
1972 |
(set-marker post nil) |
|
1973 |
t)))) |
|
1974 |
|
|
1975 |
(defun org-babel-where-is-src-block-result (&optional insert _info hash) |
|
1976 |
"Find where the current source block results begin. |
|
1977 |
|
|
1978 |
Return the point at the beginning of the result of the current |
|
1979 |
source block, specifically at the beginning of the results line. |
|
1980 |
|
|
1981 |
If no result exists for this block return nil, unless optional |
|
1982 |
argument INSERT is non-nil. In this case, create a results line |
|
1983 |
following the source block and return the position at its |
|
1984 |
beginning. In the case of inline code, remove the results part |
|
1985 |
instead. |
|
1986 |
|
|
1987 |
If optional argument HASH is a string, remove contents related to |
|
1988 |
RESULTS keyword if its hash is different. Then update the latter |
|
1989 |
to HASH." |
|
1990 |
(let ((context (org-element-context))) |
|
1991 |
(catch :found |
|
1992 |
(org-with-wide-buffer |
|
1993 |
(pcase (org-element-type context) |
|
1994 |
((or `inline-babel-call `inline-src-block) |
|
1995 |
;; Results for inline objects are located right after them. |
|
1996 |
;; There is no RESULTS line to insert either. |
|
1997 |
(let ((limit (org-element-property |
|
1998 |
:contents-end (org-element-property :parent context)))) |
|
1999 |
(goto-char (org-element-property :end context)) |
|
2000 |
(skip-chars-forward " \t\n" limit) |
|
2001 |
(throw :found |
|
2002 |
(and |
|
2003 |
(< (point) limit) |
|
2004 |
(let ((result (org-element-context))) |
|
2005 |
(and (eq (org-element-type result) 'macro) |
|
2006 |
(string= (org-element-property :key result) |
|
2007 |
"results") |
|
2008 |
(if (not insert) (point) |
|
2009 |
(delete-region |
|
2010 |
(point) |
|
2011 |
(progn |
|
2012 |
(goto-char (org-element-property :end result)) |
|
2013 |
(skip-chars-backward " \t") |
|
2014 |
(point))) |
|
2015 |
(point)))))))) |
|
2016 |
((or `babel-call `src-block) |
|
2017 |
(let* ((name (org-element-property :name context)) |
|
2018 |
(named-results (and name (org-babel-find-named-result name)))) |
|
2019 |
(goto-char (or named-results (org-element-property :end context))) |
|
2020 |
(cond |
|
2021 |
;; Existing results named after the current source. |
|
2022 |
(named-results |
|
2023 |
(when (org-babel--clear-results-maybe hash) |
|
2024 |
(org-babel--insert-results-keyword name hash)) |
|
2025 |
(throw :found (point))) |
|
2026 |
;; Named results expect but none to be found. |
|
2027 |
(name) |
|
2028 |
;; No possible anonymous results at the very end of |
|
2029 |
;; buffer or outside CONTEXT parent. |
|
2030 |
((eq (point) |
|
2031 |
(or (org-element-property |
|
2032 |
:contents-end (org-element-property :parent context)) |
|
2033 |
(point-max)))) |
|
2034 |
;; Check if next element is an anonymous result below |
|
2035 |
;; the current block. |
|
2036 |
((let* ((next (org-element-at-point)) |
|
2037 |
(end (save-excursion |
|
2038 |
(goto-char |
|
2039 |
(org-element-property :post-affiliated next)) |
|
2040 |
(line-end-position))) |
|
2041 |
(empty-result-re (concat org-babel-result-regexp "$")) |
|
2042 |
(case-fold-search t)) |
|
2043 |
(re-search-forward empty-result-re end t)) |
|
2044 |
(beginning-of-line) |
|
2045 |
(when (org-babel--clear-results-maybe hash) |
|
2046 |
(org-babel--insert-results-keyword nil hash)) |
|
2047 |
(throw :found (point)))))) |
|
2048 |
;; Ignore other elements. |
|
2049 |
(_ (throw :found nil)))) |
|
2050 |
;; No result found. Insert a RESULTS keyword below element, if |
|
2051 |
;; appropriate. In this case, ensure there is an empty line |
|
2052 |
;; after the previous element. |
|
2053 |
(when insert |
|
2054 |
(save-excursion |
|
2055 |
(goto-char (min (org-element-property :end context) (point-max))) |
|
2056 |
(skip-chars-backward " \t\n") |
|
2057 |
(forward-line) |
|
2058 |
(unless (bolp) (insert "\n")) |
|
2059 |
(insert "\n") |
|
2060 |
(org-babel--insert-results-keyword |
|
2061 |
(org-element-property :name context) hash) |
|
2062 |
(point)))))) |
|
2063 |
|
|
2064 |
(defun org-babel-read-element (element) |
|
2065 |
"Read ELEMENT into emacs-lisp. |
|
2066 |
Return nil if ELEMENT cannot be read." |
|
2067 |
(org-with-wide-buffer |
|
2068 |
(goto-char (org-element-property :post-affiliated element)) |
|
2069 |
(pcase (org-element-type element) |
|
2070 |
(`fixed-width |
|
2071 |
(let ((v (org-trim (org-element-property :value element)))) |
|
2072 |
(or (org-babel--string-to-number v) v))) |
|
2073 |
(`table (org-babel-read-table)) |
|
2074 |
(`plain-list (org-babel-read-list)) |
|
2075 |
(`example-block |
|
2076 |
(let ((v (org-element-property :value element))) |
|
2077 |
(if (or org-src-preserve-indentation |
|
2078 |
(org-element-property :preserve-indent element)) |
|
2079 |
v |
|
2080 |
(org-remove-indentation v)))) |
|
2081 |
(`export-block |
|
2082 |
(org-remove-indentation (org-element-property :value element))) |
|
2083 |
(`paragraph |
|
2084 |
;; Treat paragraphs containing a single link specially. |
|
2085 |
(skip-chars-forward " \t") |
|
2086 |
(if (and (looking-at org-bracket-link-regexp) |
|
2087 |
(save-excursion |
|
2088 |
(goto-char (match-end 0)) |
|
2089 |
(skip-chars-forward " \r\t\n") |
|
2090 |
(<= (org-element-property :end element) |
|
2091 |
(point)))) |
|
2092 |
(org-babel-read-link) |
|
2093 |
(buffer-substring-no-properties |
|
2094 |
(org-element-property :contents-begin element) |
|
2095 |
(org-element-property :contents-end element)))) |
|
2096 |
((or `center-block `quote-block `verse-block `special-block) |
|
2097 |
(org-remove-indentation |
|
2098 |
(buffer-substring-no-properties |
|
2099 |
(org-element-property :contents-begin element) |
|
2100 |
(org-element-property :contents-end element)))) |
|
2101 |
(_ nil)))) |
|
2102 |
|
|
2103 |
(defun org-babel-read-result () |
|
2104 |
"Read the result at point into emacs-lisp." |
|
2105 |
(and (not (save-excursion |
|
2106 |
(beginning-of-line) |
|
2107 |
(looking-at-p "[ \t]*$"))) |
|
2108 |
(org-babel-read-element (org-element-at-point)))) |
|
2109 |
|
|
2110 |
(defun org-babel-read-table () |
|
2111 |
"Read the table at point into emacs-lisp." |
|
2112 |
(mapcar (lambda (row) |
|
2113 |
(if (and (symbolp row) (equal row 'hline)) row |
|
2114 |
(mapcar (lambda (el) (org-babel-read el 'inhibit-lisp-eval)) row))) |
|
2115 |
(org-table-to-lisp))) |
|
2116 |
|
|
2117 |
(defun org-babel-read-list () |
|
2118 |
"Read the list at point into emacs-lisp." |
|
2119 |
(mapcar (lambda (el) (org-babel-read el 'inhibit-lisp-eval)) |
|
2120 |
(cdr (org-list-to-lisp)))) |
|
2121 |
|
|
2122 |
(defvar org-link-types-re) |
|
2123 |
(defun org-babel-read-link () |
|
2124 |
"Read the link at point into emacs-lisp. |
|
2125 |
If the path of the link is a file path it is expanded using |
|
2126 |
`expand-file-name'." |
|
2127 |
(let* ((case-fold-search t) |
|
2128 |
(raw (and (looking-at org-bracket-link-regexp) |
|
2129 |
(org-no-properties (match-string 1)))) |
|
2130 |
(type (and (string-match org-link-types-re raw) |
|
2131 |
(match-string 1 raw)))) |
|
2132 |
(cond |
|
2133 |
((not type) (expand-file-name raw)) |
|
2134 |
((string= type "file") |
|
2135 |
(and (string-match "file\\(.*\\):\\(.+\\)" raw) |
|
2136 |
(expand-file-name (match-string 2 raw)))) |
|
2137 |
(t raw)))) |
|
2138 |
|
|
2139 |
(defun org-babel-format-result (result &optional sep) |
|
2140 |
"Format RESULT for writing to file." |
|
2141 |
(let ((echo-res (lambda (r) (if (stringp r) r (format "%S" r))))) |
|
2142 |
(if (listp result) |
|
2143 |
;; table result |
|
2144 |
(orgtbl-to-generic |
|
2145 |
result (list :sep (or sep "\t") :fmt echo-res)) |
|
2146 |
;; scalar result |
|
2147 |
(funcall echo-res result)))) |
|
2148 |
|
|
2149 |
(defun org-babel-insert-result (result &optional result-params info hash lang) |
|
2150 |
"Insert RESULT into the current buffer. |
|
2151 |
|
|
2152 |
By default RESULT is inserted after the end of the current source |
|
2153 |
block. The RESULT of an inline source block usually will be |
|
2154 |
wrapped inside a `results' macro and placed on the same line as |
|
2155 |
the inline source block. The macro is stripped upon export. |
|
2156 |
Multiline and non-scalar RESULTS from inline source blocks are |
|
2157 |
not allowed. With optional argument RESULT-PARAMS controls |
|
2158 |
insertion of results in the Org mode file. RESULT-PARAMS can |
|
2159 |
take the following values: |
|
2160 |
|
|
2161 |
replace - (default option) insert results after the source block |
|
2162 |
or inline source block replacing any previously |
|
2163 |
inserted results. |
|
2164 |
|
|
2165 |
silent -- no results are inserted into the Org buffer but |
|
2166 |
the results are echoed to the minibuffer and are |
|
2167 |
ingested by Emacs (a potentially time consuming |
|
2168 |
process). |
|
2169 |
|
|
2170 |
file ---- the results are interpreted as a file path, and are |
|
2171 |
inserted into the buffer using the Org file syntax. |
|
2172 |
|
|
2173 |
list ---- the results are interpreted as an Org list. |
|
2174 |
|
|
2175 |
raw ----- results are added directly to the Org file. This is |
|
2176 |
a good option if you code block will output Org |
|
2177 |
formatted text. |
|
2178 |
|
|
2179 |
drawer -- results are added directly to the Org file as with |
|
2180 |
\"raw\", but are wrapped in a RESULTS drawer or results |
|
2181 |
macro, allowing them to later be replaced or removed |
|
2182 |
automatically. |
|
2183 |
|
|
2184 |
org ----- results are added inside of a \"src_org{}\" or \"#+BEGIN_SRC |
|
2185 |
org\" block depending on whether the current source block is |
|
2186 |
inline or not. They are not comma-escaped when inserted, |
|
2187 |
but Org syntax here will be discarded when exporting the |
|
2188 |
file. |
|
2189 |
|
|
2190 |
html ---- results are added inside of a #+BEGIN_EXPORT HTML block |
|
2191 |
or html export snippet depending on whether the current |
|
2192 |
source block is inline or not. This is a good option |
|
2193 |
if your code block will output html formatted text. |
|
2194 |
|
|
2195 |
latex --- results are added inside of a #+BEGIN_EXPORT LATEX |
|
2196 |
block or latex export snippet depending on whether the |
|
2197 |
current source block is inline or not. This is a good |
|
2198 |
option if your code block will output latex formatted |
|
2199 |
text. |
|
2200 |
|
|
2201 |
code ---- the results are extracted in the syntax of the source |
|
2202 |
code of the language being evaluated and are added |
|
2203 |
inside of a source block with the source-code language |
|
2204 |
set appropriately. Also, source block inlining is |
|
2205 |
preserved in this case. Note this relies on the |
|
2206 |
optional LANG argument. |
|
2207 |
|
|
2208 |
list ---- the results are rendered as a list. This option not |
|
2209 |
allowed for inline src blocks. |
|
2210 |
|
|
2211 |
table --- the results are rendered as a table. This option not |
|
2212 |
allowed for inline src blocks. |
|
2213 |
|
|
2214 |
INFO may provide the values of these header arguments (in the |
|
2215 |
`header-arguments-alist' see the docstring for |
|
2216 |
`org-babel-get-src-block-info'): |
|
2217 |
|
|
2218 |
:file --- the name of the file to which output should be written. |
|
2219 |
|
|
2220 |
:wrap --- the effect is similar to `latex' in RESULT-PARAMS but |
|
2221 |
using the argument supplied to specify the export block |
|
2222 |
or snippet type." |
|
2223 |
(cond ((stringp result) |
|
2224 |
(setq result (org-no-properties result)) |
|
2225 |
(when (member "file" result-params) |
|
2226 |
(setq result (org-babel-result-to-file |
|
2227 |
result (when (assq :file-desc (nth 2 info)) |
|
2228 |
(or (cdr (assq :file-desc (nth 2 info))) |
|
2229 |
result)))))) |
|
2230 |
((listp result)) |
|
2231 |
(t (setq result (format "%S" result)))) |
|
2232 |
(if (and result-params (member "silent" result-params)) |
|
2233 |
(progn (message (replace-regexp-in-string "%" "%%" (format "%S" result))) |
|
2234 |
result) |
|
2235 |
(let ((inline (let ((context (org-element-context))) |
|
2236 |
(and (memq (org-element-type context) |
|
2237 |
'(inline-babel-call inline-src-block)) |
|
2238 |
context)))) |
|
2239 |
(when inline |
|
2240 |
(let ((warning |
|
2241 |
(or (and (member "table" result-params) "`:results table'") |
|
2242 |
(and (listp result) "list result") |
|
2243 |
(and (string-match-p "\n." result) "multiline result") |
|
2244 |
(and (member "list" result-params) "`:results list'")))) |
|
2245 |
(when warning |
|
2246 |
(user-error "Inline error: %s cannot be used" warning)))) |
|
2247 |
(save-excursion |
|
2248 |
(let* ((visible-beg (point-min-marker)) |
|
2249 |
(visible-end (copy-marker (point-max) t)) |
|
2250 |
(inline (let ((context (org-element-context))) |
|
2251 |
(and (memq (org-element-type context) |
|
2252 |
'(inline-babel-call inline-src-block)) |
|
2253 |
context))) |
|
2254 |
(existing-result (org-babel-where-is-src-block-result t nil hash)) |
|
2255 |
(results-switches (cdr (assq :results_switches (nth 2 info)))) |
|
2256 |
;; When results exist outside of the current visible |
|
2257 |
;; region of the buffer, be sure to widen buffer to |
|
2258 |
;; update them. |
|
2259 |
(outside-scope (and existing-result |
|
2260 |
(buffer-narrowed-p) |
|
2261 |
(or (> visible-beg existing-result) |
|
2262 |
(<= visible-end existing-result)))) |
|
2263 |
beg end indent) |
|
2264 |
;; Ensure non-inline results end in a newline. |
|
2265 |
(when (and (org-string-nw-p result) |
|
2266 |
(not inline) |
|
2267 |
(not (string-equal (substring result -1) "\n"))) |
|
2268 |
(setq result (concat result "\n"))) |
|
2269 |
(unwind-protect |
|
2270 |
(progn |
|
2271 |
(when outside-scope (widen)) |
|
2272 |
(if existing-result (goto-char existing-result) |
|
2273 |
(goto-char (org-element-property :end inline)) |
|
2274 |
(skip-chars-backward " \t")) |
|
2275 |
(unless inline |
|
2276 |
(setq indent (org-get-indentation)) |
|
2277 |
(forward-line 1)) |
|
2278 |
(setq beg (point)) |
|
2279 |
(cond |
|
2280 |
(inline |
|
2281 |
;; Make sure new results are separated from the |
|
2282 |
;; source code by one space. |
|
2283 |
(unless existing-result |
|
2284 |
(insert " ") |
|
2285 |
(setq beg (point)))) |
|
2286 |
((member "replace" result-params) |
|
2287 |
(delete-region (point) (org-babel-result-end))) |
|
2288 |
((member "append" result-params) |
|
2289 |
(goto-char (org-babel-result-end)) (setq beg (point-marker))) |
|
2290 |
((member "prepend" result-params))) ; already there |
|
2291 |
(setq results-switches |
|
2292 |
(if results-switches (concat " " results-switches) "")) |
|
2293 |
(let ((wrap |
|
2294 |
(lambda (start finish &optional no-escape no-newlines |
|
2295 |
inline-start inline-finish) |
|
2296 |
(when inline |
|
2297 |
(setq start inline-start) |
|
2298 |
(setq finish inline-finish) |
|
2299 |
(setq no-newlines t)) |
|
2300 |
(let ((before-finish (marker-position end))) |
|
2301 |
(goto-char end) |
|
2302 |
(insert (concat finish (unless no-newlines "\n"))) |
|
2303 |
(goto-char beg) |
|
2304 |
(insert (concat start (unless no-newlines "\n"))) |
|
2305 |
(unless no-escape |
|
2306 |
(org-escape-code-in-region |
|
2307 |
(min (point) before-finish) before-finish)) |
|
2308 |
(goto-char end)))) |
|
2309 |
(tabulablep |
|
2310 |
(lambda (r) |
|
2311 |
;; Non-nil when result R can be turned into |
|
2312 |
;; a table. |
|
2313 |
(and (listp r) |
|
2314 |
(null (cdr (last r))) |
|
2315 |
(cl-every |
|
2316 |
(lambda (e) (or (atom e) (null (cdr (last e))))) |
|
2317 |
result))))) |
|
2318 |
;; insert results based on type |
|
2319 |
(cond |
|
2320 |
;; Do nothing for an empty result. |
|
2321 |
((null result)) |
|
2322 |
;; Insert a list if preferred. |
|
2323 |
((member "list" result-params) |
|
2324 |
(insert |
|
2325 |
(org-trim |
|
2326 |
(org-list-to-generic |
|
2327 |
(cons 'unordered |
|
2328 |
(mapcar |
|
2329 |
(lambda (e) |
|
2330 |
(list (if (stringp e) e (format "%S" e)))) |
|
2331 |
(if (listp result) result |
|
2332 |
(split-string result "\n" t)))) |
|
2333 |
'(:splicep nil :istart "- " :iend "\n"))) |
|
2334 |
"\n")) |
|
2335 |
;; Try hard to print RESULT as a table. Give up if |
|
2336 |
;; it contains an improper list. |
|
2337 |
((funcall tabulablep result) |
|
2338 |
(goto-char beg) |
|
2339 |
(insert (concat (orgtbl-to-orgtbl |
|
2340 |
(if (cl-every |
|
2341 |
(lambda (e) |
|
2342 |
(or (eq e 'hline) (listp e))) |
|
2343 |
result) |
|
2344 |
result |
|
2345 |
(list result)) |
|
2346 |
nil) |
|
2347 |
"\n")) |
|
2348 |
(goto-char beg) |
|
2349 |
(when (org-at-table-p) (org-table-align)) |
|
2350 |
(goto-char (org-table-end))) |
|
2351 |
;; Print verbatim a list that cannot be turned into |
|
2352 |
;; a table. |
|
2353 |
((listp result) (insert (format "%s\n" result))) |
|
2354 |
((member "file" result-params) |
|
2355 |
(when inline |
|
2356 |
(setq result (org-macro-escape-arguments result))) |
|
2357 |
(insert result)) |
|
2358 |
((and inline (not (member "raw" result-params))) |
|
2359 |
(insert (org-macro-escape-arguments |
|
2360 |
(org-babel-chomp result "\n")))) |
|
2361 |
(t (goto-char beg) (insert result))) |
|
2362 |
(setq end (copy-marker (point) t)) |
|
2363 |
;; possibly wrap result |
|
2364 |
(cond |
|
2365 |
((assq :wrap (nth 2 info)) |
|
2366 |
(let ((name (or (cdr (assq :wrap (nth 2 info))) "RESULTS"))) |
|
2367 |
(funcall wrap (concat "#+BEGIN_" name) |
|
2368 |
(concat "#+END_" (car (split-string name))) |
|
2369 |
nil nil (concat "{{{results(@@" name ":") "@@)}}}"))) |
|
2370 |
((member "html" result-params) |
|
2371 |
(funcall wrap "#+BEGIN_EXPORT html" "#+END_EXPORT" nil nil |
|
2372 |
"{{{results(@@html:" "@@)}}}")) |
|
2373 |
((member "latex" result-params) |
|
2374 |
(funcall wrap "#+BEGIN_EXPORT latex" "#+END_EXPORT" nil nil |
|
2375 |
"{{{results(@@latex:" "@@)}}}")) |
|
2376 |
((member "org" result-params) |
|
2377 |
(goto-char beg) (when (org-at-table-p) (org-cycle)) |
|
2378 |
(funcall wrap "#+BEGIN_SRC org" "#+END_SRC" nil nil |
|
2379 |
"{{{results(src_org{" "})}}}")) |
|
2380 |
((member "code" result-params) |
|
2381 |
(let ((lang (or lang "none"))) |
|
2382 |
(funcall wrap (format "#+BEGIN_SRC %s%s" lang results-switches) |
|
2383 |
"#+END_SRC" nil nil |
|
2384 |
(format "{{{results(src_%s[%s]{" lang results-switches) |
|
2385 |
"})}}}"))) |
|
2386 |
((member "raw" result-params) |
|
2387 |
(goto-char beg) (when (org-at-table-p) (org-cycle))) |
|
2388 |
((or (member "drawer" result-params) |
|
2389 |
;; Stay backward compatible with <7.9.2 |
|
2390 |
(member "wrap" result-params)) |
|
2391 |
(goto-char beg) (when (org-at-table-p) (org-cycle)) |
|
2392 |
(funcall wrap ":RESULTS:" ":END:" 'no-escape nil |
|
2393 |
"{{{results(" ")}}}")) |
|
2394 |
((and inline (member "file" result-params)) |
|
2395 |
(funcall wrap nil nil nil nil "{{{results(" ")}}}")) |
|
2396 |
((and (not (funcall tabulablep result)) |
|
2397 |
(not (member "file" result-params))) |
|
2398 |
(let ((org-babel-inline-result-wrap |
|
2399 |
;; Hard code {{{results(...)}}} on top of |
|
2400 |
;; customization. |
|
2401 |
(format "{{{results(%s)}}}" |
|
2402 |
org-babel-inline-result-wrap))) |
|
2403 |
(org-babel-examplify-region |
|
2404 |
beg end results-switches inline))))) |
|
2405 |
;; Possibly indent results in par with #+results line. |
|
2406 |
(when (and (not inline) (numberp indent) (> indent 0) |
|
2407 |
;; In this case `table-align' does the work |
|
2408 |
;; for us. |
|
2409 |
(not (and (listp result) |
|
2410 |
(member "append" result-params)))) |
|
2411 |
(indent-rigidly beg end indent)) |
|
2412 |
(if (null result) |
|
2413 |
(if (member "value" result-params) |
|
2414 |
(message "Code block returned no value.") |
|
2415 |
(message "Code block produced no output.")) |
|
2416 |
(message "Code block evaluation complete."))) |
|
2417 |
(set-marker end nil) |
|
2418 |
(when outside-scope (narrow-to-region visible-beg visible-end)) |
|
2419 |
(set-marker visible-beg nil) |
|
2420 |
(set-marker visible-end nil))))))) |
|
2421 |
|
|
2422 |
(defun org-babel-remove-result (&optional info keep-keyword) |
|
2423 |
"Remove the result of the current source block." |
|
2424 |
(interactive) |
|
2425 |
(let ((location (org-babel-where-is-src-block-result nil info))) |
|
2426 |
(when location |
|
2427 |
(save-excursion |
|
2428 |
(goto-char location) |
|
2429 |
(when (looking-at (concat org-babel-result-regexp ".*$")) |
|
2430 |
(delete-region |
|
2431 |
(if keep-keyword (line-beginning-position 2) |
|
2432 |
(save-excursion |
|
2433 |
(skip-chars-backward " \r\t\n") |
|
2434 |
(line-beginning-position 2))) |
|
2435 |
(progn (forward-line) (org-babel-result-end)))))))) |
|
2436 |
|
|
2437 |
(defun org-babel-remove-inline-result (&optional datum) |
|
2438 |
"Remove the result of the current inline-src-block or babel call. |
|
2439 |
The result must be wrapped in a `results' macro to be removed. |
|
2440 |
Leading white space is trimmed." |
|
2441 |
(interactive) |
|
2442 |
(let* ((el (or datum (org-element-context)))) |
|
2443 |
(when (memq (org-element-type el) '(inline-src-block inline-babel-call)) |
|
2444 |
(org-with-wide-buffer |
|
2445 |
(goto-char (org-element-property :end el)) |
|
2446 |
(skip-chars-backward " \t") |
|
2447 |
(let ((result (save-excursion |
|
2448 |
(skip-chars-forward |
|
2449 |
" \t\n" |
|
2450 |
(org-element-property |
|
2451 |
:contents-end (org-element-property :parent el))) |
|
2452 |
(org-element-context)))) |
|
2453 |
(when (and (eq (org-element-type result) 'macro) |
|
2454 |
(string= (org-element-property :key result) "results")) |
|
2455 |
(delete-region ; And leading whitespace. |
|
2456 |
(point) |
|
2457 |
(progn (goto-char (org-element-property :end result)) |
|
2458 |
(skip-chars-backward " \t\n") |
|
2459 |
(point))))))))) |
|
2460 |
|
|
2461 |
(defun org-babel-remove-result-one-or-many (x) |
|
2462 |
"Remove the result of the current source block. |
|
2463 |
If called with a prefix argument, remove all result blocks |
|
2464 |
in the buffer." |
|
2465 |
(interactive "P") |
|
2466 |
(if x |
|
2467 |
(org-babel-map-src-blocks nil (org-babel-remove-result)) |
|
2468 |
(org-babel-remove-result))) |
|
2469 |
|
|
2470 |
(defun org-babel-result-end () |
|
2471 |
"Return the point at the end of the current set of results." |
|
2472 |
(cond ((looking-at-p "^[ \t]*$") (point)) ;no result |
|
2473 |
((looking-at-p (format "^[ \t]*%s[ \t]*$" org-bracket-link-regexp)) |
|
2474 |
(line-beginning-position 2)) |
|
2475 |
(t |
|
2476 |
(let ((element (org-element-at-point))) |
|
2477 |
(if (memq (org-element-type element) |
|
2478 |
;; Possible results types. |
|
2479 |
'(drawer example-block export-block fixed-width item |
|
2480 |
plain-list src-block table)) |
|
2481 |
(save-excursion |
|
2482 |
(goto-char (min (point-max) ;for narrowed buffers |
|
2483 |
(org-element-property :end element))) |
|
2484 |
(skip-chars-backward " \r\t\n") |
|
2485 |
(line-beginning-position 2)) |
|
2486 |
(point)))))) |
|
2487 |
|
|
2488 |
(defun org-babel-result-to-file (result &optional description) |
|
2489 |
"Convert RESULT into an Org link with optional DESCRIPTION. |
|
2490 |
If the `default-directory' is different from the containing |
|
2491 |
file's directory then expand relative links." |
|
2492 |
(when (stringp result) |
|
2493 |
(format "[[file:%s]%s]" |
|
2494 |
(if (and default-directory |
|
2495 |
buffer-file-name |
|
2496 |
(not (string= (expand-file-name default-directory) |
|
2497 |
(expand-file-name |
|
2498 |
(file-name-directory buffer-file-name))))) |
|
2499 |
(expand-file-name result default-directory) |
|
2500 |
result) |
|
2501 |
(if description (concat "[" description "]") "")))) |
|
2502 |
|
|
2503 |
(defun org-babel-examplify-region (beg end &optional results-switches inline) |
|
2504 |
"Comment out region using the inline `==' or `: ' org example quote." |
|
2505 |
(interactive "*r") |
|
2506 |
(let ((maybe-cap |
|
2507 |
(lambda (str) |
|
2508 |
(if org-babel-uppercase-example-markers (upcase str) str)))) |
|
2509 |
(if inline |
|
2510 |
(save-excursion |
|
2511 |
(goto-char beg) |
|
2512 |
(insert (format org-babel-inline-result-wrap |
|
2513 |
(delete-and-extract-region beg end)))) |
|
2514 |
(let ((size (count-lines beg end))) |
|
2515 |
(save-excursion |
|
2516 |
(cond ((= size 0)) ; do nothing for an empty result |
|
2517 |
((< size org-babel-min-lines-for-block-output) |
|
2518 |
(goto-char beg) |
|
2519 |
(dotimes (_ size) |
|
2520 |
(beginning-of-line 1) (insert ": ") (forward-line 1))) |
|
2521 |
(t |
|
2522 |
(goto-char beg) |
|
2523 |
(insert (if results-switches |
|
2524 |
(format "%s%s\n" |
|
2525 |
(funcall maybe-cap "#+begin_example") |
|
2526 |
results-switches) |
|
2527 |
(funcall maybe-cap "#+begin_example\n"))) |
|
2528 |
(let ((p (point))) |
|
2529 |
(if (markerp end) (goto-char end) (forward-char (- end beg))) |
|
2530 |
(org-escape-code-in-region p (point))) |
|
2531 |
(insert (funcall maybe-cap "#+end_example\n"))))))))) |
|
2532 |
|
|
2533 |
(defun org-babel-update-block-body (new-body) |
|
2534 |
"Update the body of the current code block to NEW-BODY." |
|
2535 |
(let ((element (org-element-at-point))) |
|
2536 |
(unless (eq (org-element-type element) 'src-block) |
|
2537 |
(error "Not in a source block")) |
|
2538 |
(goto-char (org-babel-where-is-src-block-head element)) |
|
2539 |
(let* ((ind (org-get-indentation)) |
|
2540 |
(body-start (line-beginning-position 2)) |
|
2541 |
(body (org-element-normalize-string |
|
2542 |
(if (or org-src-preserve-indentation |
|
2543 |
(org-element-property :preserve-indent element)) |
|
2544 |
new-body |
|
2545 |
(with-temp-buffer |
|
2546 |
(insert (org-remove-indentation new-body)) |
|
2547 |
(indent-rigidly |
|
2548 |
(point-min) |
|
2549 |
(point-max) |
|
2550 |
(+ ind org-edit-src-content-indentation)) |
|
2551 |
(buffer-string)))))) |
|
2552 |
(delete-region body-start |
|
2553 |
(org-with-wide-buffer |
|
2554 |
(goto-char (org-element-property :end element)) |
|
2555 |
(skip-chars-backward " \t\n") |
|
2556 |
(line-beginning-position))) |
|
2557 |
(goto-char body-start) |
|
2558 |
(insert body)))) |
|
2559 |
|
|
2560 |
(defun org-babel-merge-params (&rest plists) |
|
2561 |
"Combine all parameter association lists in PLISTS. |
|
2562 |
Later elements of PLISTS override the values of previous elements. |
|
2563 |
This takes into account some special considerations for certain |
|
2564 |
parameters when merging lists." |
|
2565 |
(let* ((results-exclusive-groups |
|
2566 |
(mapcar (lambda (group) (mapcar #'symbol-name group)) |
|
2567 |
(cdr (assq 'results org-babel-common-header-args-w-values)))) |
|
2568 |
(exports-exclusive-groups |
|
2569 |
(mapcar (lambda (group) (mapcar #'symbol-name group)) |
|
2570 |
(cdr (assq 'exports org-babel-common-header-args-w-values)))) |
|
2571 |
(merge |
|
2572 |
(lambda (exclusive-groups &rest result-params) |
|
2573 |
;; Maintain exclusivity of mutually exclusive parameters, |
|
2574 |
;; as defined in EXCLUSIVE-GROUPS while merging lists in |
|
2575 |
;; RESULT-PARAMS. |
|
2576 |
(let (output) |
|
2577 |
(dolist (new-params result-params (delete-dups output)) |
|
2578 |
(dolist (new-param new-params) |
|
2579 |
(dolist (exclusive-group exclusive-groups) |
|
2580 |
(when (member new-param exclusive-group) |
|
2581 |
(setq output (cl-remove-if |
|
2582 |
(lambda (o) (member o exclusive-group)) |
|
2583 |
output)))) |
|
2584 |
(push new-param output)))))) |
|
2585 |
(variable-index 0) ;Handle positional arguments. |
|
2586 |
clearnames |
|
2587 |
params ;Final parameters list. |
|
2588 |
;; Some keywords accept multiple values. We need to treat |
|
2589 |
;; them specially. |
|
2590 |
vars results exports) |
|
2591 |
(dolist (plist plists) |
|
2592 |
(dolist (pair plist) |
|
2593 |
(pcase pair |
|
2594 |
(`(:var . ,value) |
|
2595 |
(let ((name (cond |
|
2596 |
((listp value) (car value)) |
|
2597 |
((string-match "^\\([^= \f\t\n\r\v]+\\)[ \t]*=" value) |
|
2598 |
(intern (match-string 1 value))) |
|
2599 |
(t nil)))) |
|
2600 |
(cond |
|
2601 |
(name |
|
2602 |
(setq vars |
|
2603 |
(append (if (not (assoc name vars)) vars |
|
2604 |
(push name clearnames) |
|
2605 |
(cl-remove-if (lambda (p) (equal name (car p))) |
|
2606 |
vars)) |
|
2607 |
(list (cons name pair))))) |
|
2608 |
((and vars (nth variable-index vars)) |
|
2609 |
;; If no name is given and we already have named |
|
2610 |
;; variables then assign to named variables in order. |
|
2611 |
(let ((name (car (nth variable-index vars)))) |
|
2612 |
;; Clear out colnames and rownames for replace vars. |
|
2613 |
(push name clearnames) |
|
2614 |
(setf (cddr (nth variable-index vars)) |
|
2615 |
(concat (symbol-name name) "=" value)) |
|
2616 |
(cl-incf variable-index))) |
|
2617 |
(t (error "Variable \"%s\" must be assigned a default value" |
|
2618 |
(cdr pair)))))) |
|
2619 |
(`(:results . ,value) |
|
2620 |
(setq results (funcall merge |
|
2621 |
results-exclusive-groups |
|
2622 |
results |
|
2623 |
(split-string |
|
2624 |
(if (stringp value) value (eval value t)))))) |
|
2625 |
(`(,(or :file :file-ext) . ,value) |
|
2626 |
;; `:file' and `:file-ext' are regular keywords but they |
|
2627 |
;; imply a "file" `:results' and a "results" `:exports'. |
|
2628 |
(when value |
|
2629 |
(setq results |
|
2630 |
(funcall merge results-exclusive-groups results '("file"))) |
|
2631 |
(unless (or (member "both" exports) |
|
2632 |
(member "none" exports) |
|
2633 |
(member "code" exports)) |
|
2634 |
(setq exports |
|
2635 |
(funcall merge |
|
2636 |
exports-exclusive-groups exports '("results")))) |
|
2637 |
(push pair params))) |
|
2638 |
(`(:exports . ,value) |
|
2639 |
(setq exports (funcall merge |
|
2640 |
exports-exclusive-groups |
|
2641 |
exports |
|
2642 |
(split-string (or value ""))))) |
|
2643 |
;; Regular keywords: any value overwrites the previous one. |
|
2644 |
(_ (setq params (cons pair (assq-delete-all (car pair) params))))))) |
|
2645 |
;; Handle `:var' and clear out colnames and rownames for replaced |
|
2646 |
;; variables. |
|
2647 |
(setq params (nconc (mapcar (lambda (v) (cons :var (cddr v))) vars) |
|
2648 |
params)) |
|
2649 |
(dolist (name clearnames) |
|
2650 |
(dolist (param '(:colname-names :rowname-names)) |
|
2651 |
(when (assq param params) |
|
2652 |
(setf (cdr (assq param params)) |
|
2653 |
(cl-remove-if (lambda (pair) (equal name (car pair))) |
|
2654 |
(cdr (assq param params)))) |
|
2655 |
(setq params |
|
2656 |
(cl-remove-if (lambda (pair) (and (equal (car pair) param) |
|
2657 |
(null (cdr pair)))) |
|
2658 |
params))))) |
|
2659 |
;; Handle other special keywords, which accept multiple values. |
|
2660 |
(setq params (nconc (list (cons :results (mapconcat #'identity results " ")) |
|
2661 |
(cons :exports (mapconcat #'identity exports " "))) |
|
2662 |
params)) |
|
2663 |
;; Return merged params. |
|
2664 |
params)) |
|
2665 |
|
|
2666 |
(defvar org-babel-use-quick-and-dirty-noweb-expansion nil |
|
2667 |
"Set to true to use regular expressions to expand noweb references. |
|
2668 |
This results in much faster noweb reference expansion but does |
|
2669 |
not properly allow code blocks to inherit the \":noweb-ref\" |
|
2670 |
header argument from buffer or subtree wide properties.") |
|
2671 |
|
|
2672 |
(defun org-babel-noweb-p (params context) |
|
2673 |
"Check if PARAMS require expansion in CONTEXT. |
|
2674 |
CONTEXT may be one of :tangle, :export or :eval." |
|
2675 |
(let ((allowed-values (cl-case context |
|
2676 |
(:tangle '("yes" "tangle" "no-export" "strip-export")) |
|
2677 |
(:eval '("yes" "no-export" "strip-export" "eval")) |
|
2678 |
(:export '("yes"))))) |
|
2679 |
(cl-some (lambda (v) (member v allowed-values)) |
|
2680 |
(split-string (or (cdr (assq :noweb params)) ""))))) |
|
2681 |
|
|
2682 |
(defun org-babel-expand-noweb-references (&optional info parent-buffer) |
|
2683 |
"Expand Noweb references in the body of the current source code block. |
|
2684 |
|
|
2685 |
For example the following reference would be replaced with the |
|
2686 |
body of the source-code block named `example-block'. |
|
2687 |
|
|
2688 |
<<example-block>> |
|
2689 |
|
|
2690 |
Note that any text preceding the <<foo>> construct on a line will |
|
2691 |
be interposed between the lines of the replacement text. So for |
|
2692 |
example if <<foo>> is placed behind a comment, then the entire |
|
2693 |
replacement text will also be commented. |
|
2694 |
|
|
2695 |
This function must be called from inside of the buffer containing |
|
2696 |
the source-code block which holds BODY. |
|
2697 |
|
|
2698 |
In addition the following syntax can be used to insert the |
|
2699 |
results of evaluating the source-code block named `example-block'. |
|
2700 |
|
|
2701 |
<<example-block()>> |
|
2702 |
|
|
2703 |
Any optional arguments can be passed to example-block by placing |
|
2704 |
the arguments inside the parenthesis following the convention |
|
2705 |
defined by `org-babel-lob'. For example |
|
2706 |
|
|
2707 |
<<example-block(a=9)>> |
|
2708 |
|
|
2709 |
would set the value of argument \"a\" equal to \"9\". Note that |
|
2710 |
these arguments are not evaluated in the current source-code |
|
2711 |
block but are passed literally to the \"example-block\"." |
|
2712 |
(let* ((parent-buffer (or parent-buffer (current-buffer))) |
|
2713 |
(info (or info (org-babel-get-src-block-info 'light))) |
|
2714 |
(lang (nth 0 info)) |
|
2715 |
(body (nth 1 info)) |
|
2716 |
(ob-nww-start org-babel-noweb-wrap-start) |
|
2717 |
(ob-nww-end org-babel-noweb-wrap-end) |
|
2718 |
(comment (string= "noweb" (cdr (assq :comments (nth 2 info))))) |
|
2719 |
(rx-prefix (concat "\\(" org-babel-src-name-regexp "\\|" |
|
2720 |
":noweb-ref[ \t]+" "\\)")) |
|
2721 |
(new-body "") |
|
2722 |
(nb-add (lambda (text) (setq new-body (concat new-body text)))) |
|
2723 |
(c-wrap (lambda (text) |
|
2724 |
(with-temp-buffer |
|
2725 |
(funcall (intern (concat lang "-mode"))) |
|
2726 |
(comment-region (point) (progn (insert text) (point))) |
|
2727 |
(org-trim (buffer-string))))) |
|
2728 |
index source-name evaluate prefix) |
|
2729 |
(with-temp-buffer |
|
2730 |
(setq-local org-babel-noweb-wrap-start ob-nww-start) |
|
2731 |
(setq-local org-babel-noweb-wrap-end ob-nww-end) |
|
2732 |
(insert body) (goto-char (point-min)) |
|
2733 |
(setq index (point)) |
|
2734 |
(while (and (re-search-forward (org-babel-noweb-wrap) nil t)) |
|
2735 |
(save-match-data (setf source-name (match-string 1))) |
|
2736 |
(save-match-data (setq evaluate (string-match "(.*)" source-name))) |
|
2737 |
(save-match-data |
|
2738 |
(setq prefix |
|
2739 |
(buffer-substring (match-beginning 0) |
|
2740 |
(save-excursion |
|
2741 |
(beginning-of-line 1) (point))))) |
|
2742 |
;; add interval to new-body (removing noweb reference) |
|
2743 |
(goto-char (match-beginning 0)) |
|
2744 |
(funcall nb-add (buffer-substring index (point))) |
|
2745 |
(goto-char (match-end 0)) |
|
2746 |
(setq index (point)) |
|
2747 |
(funcall |
|
2748 |
nb-add |
|
2749 |
(with-current-buffer parent-buffer |
|
2750 |
(save-restriction |
|
2751 |
(widen) |
|
2752 |
(mapconcat ;; Interpose PREFIX between every line. |
|
2753 |
#'identity |
|
2754 |
(split-string |
|
2755 |
(if evaluate |
|
2756 |
(let ((raw (org-babel-ref-resolve source-name))) |
|
2757 |
(if (stringp raw) raw (format "%S" raw))) |
|
2758 |
(or |
|
2759 |
;; Retrieve from the library of babel. |
|
2760 |
(nth 2 (assoc (intern source-name) |
|
2761 |
org-babel-library-of-babel)) |
|
2762 |
;; Return the contents of headlines literally. |
|
2763 |
(save-excursion |
|
2764 |
(when (org-babel-ref-goto-headline-id source-name) |
|
2765 |
(org-babel-ref-headline-body))) |
|
2766 |
;; Find the expansion of reference in this buffer. |
|
2767 |
(let ((rx (concat rx-prefix source-name "[ \t\n]")) |
|
2768 |
expansion) |
|
2769 |
(save-excursion |
|
2770 |
(goto-char (point-min)) |
|
2771 |
(if org-babel-use-quick-and-dirty-noweb-expansion |
|
2772 |
(while (re-search-forward rx nil t) |
|
2773 |
(let* ((i (org-babel-get-src-block-info 'light)) |
|
2774 |
(body (if (org-babel-noweb-p (nth 2 i) :eval) |
|
2775 |
(org-babel-expand-noweb-references i) |
|
2776 |
(nth 1 i))) |
|
2777 |
(sep (or (cdr (assq :noweb-sep (nth 2 i))) |
|
2778 |
"\n")) |
|
2779 |
(full (if comment |
|
2780 |
(let ((cs (org-babel-tangle-comment-links i))) |
|
2781 |
(concat (funcall c-wrap (car cs)) "\n" |
|
2782 |
body "\n" |
|
2783 |
(funcall c-wrap (cadr cs)))) |
|
2784 |
body))) |
|
2785 |
(setq expansion (cons sep (cons full expansion))))) |
|
2786 |
(org-babel-map-src-blocks nil |
|
2787 |
(let ((i (let ((org-babel-current-src-block-location (point))) |
|
2788 |
(org-babel-get-src-block-info 'light)))) |
|
2789 |
(when (equal (or (cdr (assq :noweb-ref (nth 2 i))) |
|
2790 |
(nth 4 i)) |
|
2791 |
source-name) |
|
2792 |
(let* ((body (if (org-babel-noweb-p (nth 2 i) :eval) |
|
2793 |
(org-babel-expand-noweb-references i) |
|
2794 |
(nth 1 i))) |
|
2795 |
(sep (or (cdr (assq :noweb-sep (nth 2 i))) |
|
2796 |
"\n")) |
|
2797 |
(full (if comment |
|
2798 |
(let ((cs (org-babel-tangle-comment-links i))) |
|
2799 |
(concat (funcall c-wrap (car cs)) "\n" |
|
2800 |
body "\n" |
|
2801 |
(funcall c-wrap (cadr cs)))) |
|
2802 |
body))) |
|
2803 |
(setq expansion |
|
2804 |
(cons sep (cons full expansion))))))))) |
|
2805 |
(and expansion |
|
2806 |
(mapconcat #'identity (nreverse (cdr expansion)) ""))) |
|
2807 |
;; Possibly raise an error if named block doesn't exist. |
|
2808 |
(if (or org-babel-noweb-error-all-langs |
|
2809 |
(member lang org-babel-noweb-error-langs)) |
|
2810 |
(error "%s" (concat |
|
2811 |
(org-babel-noweb-wrap source-name) |
|
2812 |
"could not be resolved (see " |
|
2813 |
"`org-babel-noweb-error-langs')")) |
|
2814 |
""))) |
|
2815 |
"[\n\r]") (concat "\n" prefix)))))) |
|
2816 |
(funcall nb-add (buffer-substring index (point-max)))) |
|
2817 |
new-body)) |
|
2818 |
|
|
2819 |
(defun org-babel--script-escape-inner (str) |
|
2820 |
(let (in-single in-double backslash out) |
|
2821 |
(mapc |
|
2822 |
(lambda (ch) |
|
2823 |
(setq |
|
2824 |
out |
|
2825 |
(if backslash |
|
2826 |
(progn |
|
2827 |
(setq backslash nil) |
|
2828 |
(cond |
|
2829 |
((and in-single (eq ch ?')) |
|
2830 |
;; Escaped single quote inside single quoted string: |
|
2831 |
;; emit just a single quote, since we've changed the |
|
2832 |
;; outer quotes to double. |
|
2833 |
(cons ch out)) |
|
2834 |
((eq ch ?\") |
|
2835 |
;; Escaped double quote |
|
2836 |
(if in-single |
|
2837 |
;; This should be interpreted as backslash+quote, |
|
2838 |
;; not an escape. Emit a three backslashes |
|
2839 |
;; followed by a quote (because one layer of |
|
2840 |
;; quoting will be stripped by `org-babel-read'). |
|
2841 |
(append (list ch ?\\ ?\\ ?\\) out) |
|
2842 |
;; Otherwise we are in a double-quoted string. Emit |
|
2843 |
;; a single escaped quote |
|
2844 |
(append (list ch ?\\) out))) |
|
2845 |
((eq ch ?\\) |
|
2846 |
;; Escaped backslash: emit a single escaped backslash |
|
2847 |
(append (list ?\\ ?\\) out)) |
|
2848 |
;; Other: emit a quoted backslash followed by whatever |
|
2849 |
;; the character was (because one layer of quoting will |
|
2850 |
;; be stripped by `org-babel-read'). |
|
2851 |
(t (append (list ch ?\\ ?\\) out)))) |
|
2852 |
(cl-case ch |
|
2853 |
(?\[ (if (or in-double in-single) |
|
2854 |
(cons ?\[ out) |
|
2855 |
(cons ?\( out))) |
|
2856 |
(?\] (if (or in-double in-single) |
|
2857 |
(cons ?\] out) |
|
2858 |
(cons ?\) out))) |
|
2859 |
(?\{ (if (or in-double in-single) |
|
2860 |
(cons ?\{ out) |
|
2861 |
(cons ?\( out))) |
|
2862 |
(?\} (if (or in-double in-single) |
|
2863 |
(cons ?\} out) |
|
2864 |
(cons ?\) out))) |
|
2865 |
(?, (if (or in-double in-single) |
|
2866 |
(cons ?, out) (cons ?\s out))) |
|
2867 |
(?\' (if in-double |
|
2868 |
(cons ?\' out) |
|
2869 |
(setq in-single (not in-single)) (cons ?\" out))) |
|
2870 |
(?\" (if in-single |
|
2871 |
(append (list ?\" ?\\) out) |
|
2872 |
(setq in-double (not in-double)) (cons ?\" out))) |
|
2873 |
(?\\ (unless (or in-single in-double) |
|
2874 |
(error "Can't handle backslash outside string in `org-babel-script-escape'")) |
|
2875 |
(setq backslash t) |
|
2876 |
out) |
|
2877 |
(t (cons ch out)))))) |
|
2878 |
(string-to-list str)) |
|
2879 |
(when (or in-single in-double) |
|
2880 |
(error "Unterminated string in `org-babel-script-escape'")) |
|
2881 |
(apply #'string (reverse out)))) |
|
2882 |
|
|
2883 |
(defun org-babel-script-escape (str &optional force) |
|
2884 |
"Safely convert tables into elisp lists." |
|
2885 |
(unless (stringp str) |
|
2886 |
(error "`org-babel-script-escape' expects a string")) |
|
2887 |
(let ((escaped |
|
2888 |
(cond |
|
2889 |
((and (> (length str) 2) |
|
2890 |
(or (and (string-equal "[" (substring str 0 1)) |
|
2891 |
(string-equal "]" (substring str -1))) |
|
2892 |
(and (string-equal "{" (substring str 0 1)) |
|
2893 |
(string-equal "}" (substring str -1))) |
|
2894 |
(and (string-equal "(" (substring str 0 1)) |
|
2895 |
(string-equal ")" (substring str -1))))) |
|
2896 |
|
|
2897 |
(concat "'" (org-babel--script-escape-inner str))) |
|
2898 |
((or force |
|
2899 |
(and (> (length str) 2) |
|
2900 |
(or (and (string-equal "'" (substring str 0 1)) |
|
2901 |
(string-equal "'" (substring str -1))) |
|
2902 |
;; We need to pass double-quoted strings |
|
2903 |
;; through the backslash-twiddling bits, even |
|
2904 |
;; though we don't need to change their |
|
2905 |
;; delimiters. |
|
2906 |
(and (string-equal "\"" (substring str 0 1)) |
|
2907 |
(string-equal "\"" (substring str -1)))))) |
|
2908 |
(org-babel--script-escape-inner str)) |
|
2909 |
(t str)))) |
|
2910 |
(condition-case nil (org-babel-read escaped) (error escaped)))) |
|
2911 |
|
|
2912 |
(defun org-babel-read (cell &optional inhibit-lisp-eval) |
|
2913 |
"Convert the string value of CELL to a number if appropriate. |
|
2914 |
Otherwise if CELL looks like lisp (meaning it starts with a |
|
2915 |
\"(\", \"\\='\", \"\\=`\" or a \"[\") then read and evaluate it as |
|
2916 |
lisp, otherwise return it unmodified as a string. Optional |
|
2917 |
argument INHIBIT-LISP-EVAL inhibits lisp evaluation for |
|
2918 |
situations in which is it not appropriate." |
|
2919 |
(cond ((not (org-string-nw-p cell)) cell) |
|
2920 |
((org-babel--string-to-number cell)) |
|
2921 |
((and (not inhibit-lisp-eval) |
|
2922 |
(or (memq (string-to-char cell) '(?\( ?' ?` ?\[)) |
|
2923 |
(string= cell "*this*"))) |
|
2924 |
(eval (read cell) t)) |
|
2925 |
((eq (string-to-char cell) ?\") (read cell)) |
|
2926 |
(t (org-no-properties cell)))) |
|
2927 |
|
|
2928 |
(defun org-babel--string-to-number (string) |
|
2929 |
"If STRING represents a number return its value. |
|
2930 |
Otherwise return nil." |
|
2931 |
(and (string-match-p "\\`-?[0-9]*\\.?[0-9]*\\'" string) |
|
2932 |
(string-to-number string))) |
|
2933 |
|
|
2934 |
(defun org-babel-import-elisp-from-file (file-name &optional separator) |
|
2935 |
"Read the results located at FILE-NAME into an elisp table. |
|
2936 |
If the table is trivial, then return it as a scalar." |
|
2937 |
(let (result) |
|
2938 |
(save-window-excursion |
|
2939 |
(with-temp-buffer |
|
2940 |
(condition-case err |
|
2941 |
(progn |
|
2942 |
(org-table-import file-name separator) |
|
2943 |
(delete-file file-name) |
|
2944 |
(setq result (mapcar (lambda (row) |
|
2945 |
(mapcar #'org-babel-string-read row)) |
|
2946 |
(org-table-to-lisp)))) |
|
2947 |
(error (message "Error reading results: %s" err) nil))) |
|
2948 |
(if (null (cdr result)) ;; if result is trivial vector, then scalarize it |
|
2949 |
(if (consp (car result)) |
|
2950 |
(if (null (cdr (car result))) |
|
2951 |
(caar result) |
|
2952 |
result) |
|
2953 |
(car result)) |
|
2954 |
result)))) |
|
2955 |
|
|
2956 |
(defun org-babel-string-read (cell) |
|
2957 |
"Strip nested \"s from around strings." |
|
2958 |
(org-babel-read (or (and (stringp cell) |
|
2959 |
(string-match "\\\"\\(.+\\)\\\"" cell) |
|
2960 |
(match-string 1 cell)) |
|
2961 |
cell) t)) |
|
2962 |
|
|
2963 |
(defun org-babel-chomp (string &optional regexp) |
|
2964 |
"Strip a trailing space or carriage return from STRING. |
|
2965 |
The default regexp used is \"[ \\f\\t\\n\\r\\v]\" but another one |
|
2966 |
can be specified as the REGEXP argument." |
|
2967 |
(let ((regexp (or regexp "[ \f\t\n\r\v]"))) |
|
2968 |
(while (and (> (length string) 0) |
|
2969 |
(string-match regexp (substring string -1))) |
|
2970 |
(setq string (substring string 0 -1))) |
|
2971 |
string)) |
|
2972 |
|
|
2973 |
(defun org-babel-process-file-name (name &optional no-quote-p) |
|
2974 |
"Prepare NAME to be used in an external process. |
|
2975 |
If NAME specifies a remote location, the remote portion of the |
|
2976 |
name is removed, since in that case the process will be executing |
|
2977 |
remotely. The file name is then processed by `expand-file-name'. |
|
2978 |
Unless second argument NO-QUOTE-P is non-nil, the file name is |
|
2979 |
additionally processed by `shell-quote-argument'" |
|
2980 |
(let ((f (org-babel-local-file-name (expand-file-name name)))) |
|
2981 |
(if no-quote-p f (shell-quote-argument f)))) |
|
2982 |
|
|
2983 |
(defvar org-babel-temporary-directory) |
|
2984 |
(unless (or noninteractive (boundp 'org-babel-temporary-directory)) |
|
2985 |
(defvar org-babel-temporary-directory |
|
2986 |
(or (and (boundp 'org-babel-temporary-directory) |
|
2987 |
(file-exists-p org-babel-temporary-directory) |
|
2988 |
org-babel-temporary-directory) |
|
2989 |
(make-temp-file "babel-" t)) |
|
2990 |
"Directory to hold temporary files created to execute code blocks. |
|
2991 |
Used by `org-babel-temp-file'. This directory will be removed on |
|
2992 |
Emacs shutdown.")) |
|
2993 |
|
|
2994 |
(defcustom org-babel-remote-temporary-directory "/tmp/" |
|
2995 |
"Directory to hold temporary files on remote hosts." |
|
2996 |
:group 'org-babel |
|
2997 |
:type 'string) |
|
2998 |
|
|
2999 |
(defmacro org-babel-result-cond (result-params scalar-form &rest table-forms) |
|
3000 |
"Call the code to parse raw string results according to RESULT-PARAMS." |
|
3001 |
(declare (indent 1) |
|
3002 |
(debug (form form &rest form))) |
|
3003 |
(org-with-gensyms (params) |
|
3004 |
`(let ((,params ,result-params)) |
|
3005 |
(unless (member "none" ,params) |
|
3006 |
(if (or (member "scalar" ,params) |
|
3007 |
(member "verbatim" ,params) |
|
3008 |
(member "html" ,params) |
|
3009 |
(member "code" ,params) |
|
3010 |
(member "pp" ,params) |
|
3011 |
(member "file" ,params) |
|
3012 |
(and (or (member "output" ,params) |
|
3013 |
(member "raw" ,params) |
|
3014 |
(member "org" ,params) |
|
3015 |
(member "drawer" ,params)) |
|
3016 |
(not (member "table" ,params)))) |
|
3017 |
,scalar-form |
|
3018 |
,@table-forms))))) |
|
3019 |
(def-edebug-spec org-babel-result-cond (form form body)) |
|
3020 |
|
|
3021 |
(defun org-babel-temp-file (prefix &optional suffix) |
|
3022 |
"Create a temporary file in the `org-babel-temporary-directory'. |
|
3023 |
Passes PREFIX and SUFFIX directly to `make-temp-file' with the |
|
3024 |
value of `temporary-file-directory' temporarily set to the value |
|
3025 |
of `org-babel-temporary-directory'." |
|
3026 |
(if (file-remote-p default-directory) |
|
3027 |
(let ((prefix |
|
3028 |
(concat (file-remote-p default-directory) |
|
3029 |
(expand-file-name |
|
3030 |
prefix org-babel-remote-temporary-directory)))) |
|
3031 |
(make-temp-file prefix nil suffix)) |
|
3032 |
(let ((temporary-file-directory |
|
3033 |
(or (and (boundp 'org-babel-temporary-directory) |
|
3034 |
(file-exists-p org-babel-temporary-directory) |
|
3035 |
org-babel-temporary-directory) |
|
3036 |
temporary-file-directory))) |
|
3037 |
(make-temp-file prefix nil suffix)))) |
|
3038 |
|
|
3039 |
(defun org-babel-remove-temporary-directory () |
|
3040 |
"Remove `org-babel-temporary-directory' on Emacs shutdown." |
|
3041 |
(when (and (boundp 'org-babel-temporary-directory) |
|
3042 |
(file-exists-p org-babel-temporary-directory)) |
|
3043 |
;; taken from `delete-directory' in files.el |
|
3044 |
(condition-case nil |
|
3045 |
(progn |
|
3046 |
(mapc (lambda (file) |
|
3047 |
;; This test is equivalent to |
|
3048 |
;; (and (file-directory-p fn) (not (file-symlink-p fn))) |
|
3049 |
;; but more efficient |
|
3050 |
(if (eq t (car (file-attributes file))) |
|
3051 |
(delete-directory file) |
|
3052 |
(delete-file file))) |
|
3053 |
;; We do not want to delete "." and "..". |
|
3054 |
(directory-files org-babel-temporary-directory 'full |
|
3055 |
"^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) |
|
3056 |
(delete-directory org-babel-temporary-directory)) |
|
3057 |
(error |
|
3058 |
(message "Failed to remove temporary Org-babel directory %s" |
|
3059 |
(if (boundp 'org-babel-temporary-directory) |
|
3060 |
org-babel-temporary-directory |
|
3061 |
"[directory not defined]")))))) |
|
3062 |
|
|
3063 |
(add-hook 'kill-emacs-hook 'org-babel-remove-temporary-directory) |
|
3064 |
|
|
3065 |
(defun org-babel-one-header-arg-safe-p (pair safe-list) |
|
3066 |
"Determine if the PAIR is a safe babel header arg according to SAFE-LIST. |
|
3067 |
|
|
3068 |
For the format of SAFE-LIST, see `org-babel-safe-header-args'." |
|
3069 |
(and (consp pair) |
|
3070 |
(keywordp (car pair)) |
|
3071 |
(stringp (cdr pair)) |
|
3072 |
(or |
|
3073 |
(memq (car pair) safe-list) |
|
3074 |
(let ((entry (assq (car pair) safe-list))) |
|
3075 |
(and entry |
|
3076 |
(consp entry) |
|
3077 |
(cond ((functionp (cdr entry)) |
|
3078 |
(funcall (cdr entry) (cdr pair))) |
|
3079 |
((listp (cdr entry)) |
|
3080 |
(member (cdr pair) (cdr entry))) |
|
3081 |
(t nil))))))) |
|
3082 |
|
|
3083 |
(defun org-babel-generate-file-param (src-name params) |
|
3084 |
"Calculate the filename for source block results. |
|
3085 |
|
|
3086 |
The directory is calculated from the :output-dir property of the |
|
3087 |
source block; if not specified, use the current directory. |
|
3088 |
|
|
3089 |
If the source block has a #+NAME and the :file parameter does not |
|
3090 |
contain any period characters, then the :file parameter is |
|
3091 |
treated as an extension, and the output file name is the |
|
3092 |
concatenation of the directory (as calculated above), the block |
|
3093 |
name, a period, and the parameter value as a file extension. |
|
3094 |
Otherwise, the :file parameter is treated as a full file name, |
|
3095 |
and the output file name is the directory (as calculated above) |
|
3096 |
plus the parameter value." |
|
3097 |
(let* ((file-cons (assq :file params)) |
|
3098 |
(file-ext-cons (assq :file-ext params)) |
|
3099 |
(file-ext (cdr-safe file-ext-cons)) |
|
3100 |
(dir (cdr-safe (assq :output-dir params))) |
|
3101 |
fname) |
|
3102 |
;; create the output-dir if it does not exist |
|
3103 |
(when dir |
|
3104 |
(make-directory dir t)) |
|
3105 |
(if file-cons |
|
3106 |
;; :file given; add :output-dir if given |
|
3107 |
(when dir |
|
3108 |
(setcdr file-cons (concat (file-name-as-directory dir) (cdr file-cons)))) |
|
3109 |
;; :file not given; compute from name and :file-ext if possible |
|
3110 |
(when (and src-name file-ext) |
|
3111 |
(if dir |
|
3112 |
(setq fname (concat (file-name-as-directory (or dir "")) |
|
3113 |
src-name "." file-ext)) |
|
3114 |
(setq fname (concat src-name "." file-ext))) |
|
3115 |
(setq params (cons (cons :file fname) params)))) |
|
3116 |
params)) |
|
3117 |
|
|
3118 |
(defun org-babel-graphical-output-file (params) |
|
3119 |
"File where a babel block should send graphical output, per PARAMS. |
|
3120 |
Return nil if no graphical output is expected. Raise an error if |
|
3121 |
the output file is ill-defined." |
|
3122 |
(let ((file (cdr (assq :file params)))) |
|
3123 |
(cond (file (and (member "graphics" (cdr (assq :result-params params))) |
|
3124 |
file)) |
|
3125 |
((assq :file-ext params) |
|
3126 |
(user-error ":file-ext given but no :file generated; did you forget \ |
|
3127 |
to name a block?")) |
|
3128 |
(t (user-error "No :file header argument given; cannot create \ |
|
3129 |
graphical result"))))) |
|
3130 |
|
|
3131 |
(defun org-babel-make-language-alias (new old) |
|
3132 |
"Make source blocks of type NEW aliases for those of type OLD. |
|
3133 |
|
|
3134 |
NEW and OLD should be strings. This function should be called |
|
3135 |
after the babel API for OLD-type source blocks is fully defined. |
|
3136 |
|
|
3137 |
Callers of this function will probably want to add an entry to |
|
3138 |
`org-src-lang-modes' as well." |
|
3139 |
(dolist (fn '("execute" "expand-body" "prep-session" |
|
3140 |
"variable-assignments" "load-session")) |
|
3141 |
(let ((sym (intern-soft (concat "org-babel-" fn ":" old)))) |
|
3142 |
(when (and sym (fboundp sym)) |
|
3143 |
(defalias (intern (concat "org-babel-" fn ":" new)) sym)))) |
|
3144 |
;; Technically we don't need a `dolist' for just one variable, but |
|
3145 |
;; we keep it for symmetry/ease of future expansion. |
|
3146 |
(dolist (var '("default-header-args")) |
|
3147 |
(let ((sym (intern-soft (concat "org-babel-" var ":" old)))) |
|
3148 |
(when (and sym (boundp sym)) |
|
3149 |
(defvaralias (intern (concat "org-babel-" var ":" new)) sym))))) |
|
3150 |
|
|
3151 |
(defun org-babel-strip-quotes (string) |
|
3152 |
"Strip \\\"s from around a string, if applicable." |
|
3153 |
(org-unbracket-string "\"" "\"" string)) |
|
3154 |
|
|
3155 |
(provide 'ob-core) |
|
3156 |
|
|
3157 |
;; Local variables: |
|
3158 |
;; generated-autoload-file: "org-loaddefs.el" |
|
3159 |
;; End: |
|
3160 |
|
|
3161 |
;;; ob-core.el ends here |