mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-12-23 10:34:17 +00:00
ob-core.el: allow the auto-generation of output file names for src blocks.
* lisp/ob-core.el (org-babel-generate-file-param): New function. (org-babel-get-src-block-info): Use it. (org-babel-merge-params): Handle :file-ext. (org-babel-graphical-output-file): error if no :file or :file-ext. * testing/lisp/test-ob.el (test-org-babel/file-ext-and-output-dir): New test. * doc/org.texi (Specific header arguments): Add doc for :file-ext and :output-dir header args. * lisp/ob-R.el (org-babel-expand-body:R): Don’t calculate graphics-file. (org-babel-execute:R): Only look for a graphics-file if needed.
This commit is contained in:
parent
7c8559e339
commit
08e2596718
25
doc/org.texi
25
doc/org.texi
@ -14406,6 +14406,8 @@ argument in lowercase letters. The following header arguments are defined:
|
||||
be collected and handled
|
||||
* file:: Specify a path for file output
|
||||
* file-desc:: Specify a description for file results
|
||||
* file-ext:: Specify an extension for file output
|
||||
* output-dir:: Specify a directory to write file output to
|
||||
* dir:: Specify the default (possibly remote)
|
||||
directory for code block execution
|
||||
* exports:: Export code and/or results
|
||||
@ -14840,6 +14842,29 @@ description for file code block results which are inserted as Org mode links
|
||||
with no value the link path will be placed in both the ``link'' and the
|
||||
``description'' portion of the Org mode link.
|
||||
|
||||
@node file-ext
|
||||
@subsubsection @code{:file-ext}
|
||||
@cindex @code{:file-ext}, src header argument
|
||||
|
||||
The value of the @code{:file-ext} header argument is used to provide an
|
||||
extension to write the file output to. It is combined with the
|
||||
@code{#+NAME:} of the source block and the value of the @ref{output-dir}
|
||||
header argument to generate a complete file name.
|
||||
|
||||
This header arg will be overridden by @code{:file}, and thus has no effect
|
||||
when the latter is specified.
|
||||
|
||||
@node output-dir
|
||||
@subsubsection @code{:output-dir}
|
||||
@cindex @code{:output-dir}, src header argument
|
||||
|
||||
The value of the @code{:output-dir} header argument is used to provide a
|
||||
directory to write the file output to. It may specify an absolute directory
|
||||
(beginning with @code{/}) or a relative directory (without @code{/}). It can
|
||||
be combined with the @code{#+NAME:} of the source block and the value of the
|
||||
@ref{file-ext} header argument to generate a complete file name, or used
|
||||
along with a @ref{file} header arg.
|
||||
|
||||
@node dir
|
||||
@subsubsection @code{:dir} and remote execution
|
||||
@cindex @code{:dir}, src header argument
|
||||
|
23
lisp/ob-R.el
23
lisp/ob-R.el
@ -95,17 +95,15 @@ this variable.")
|
||||
|
||||
(defun org-babel-expand-body:R (body params &optional graphics-file)
|
||||
"Expand BODY according to PARAMS, return the expanded body."
|
||||
(let ((graphics-file
|
||||
(or graphics-file (org-babel-graphical-output-file params))))
|
||||
(mapconcat #'identity
|
||||
(append
|
||||
(when (cdr (assoc :prologue params))
|
||||
(list (cdr (assoc :prologue params))))
|
||||
(org-babel-variable-assignments:R params)
|
||||
(list body)
|
||||
(when (cdr (assoc :epilogue params))
|
||||
(list (cdr (assoc :epilogue params)))))
|
||||
"\n")))
|
||||
(mapconcat #'identity
|
||||
(append
|
||||
(when (cdr (assoc :prologue params))
|
||||
(list (cdr (assoc :prologue params))))
|
||||
(org-babel-variable-assignments:R params)
|
||||
(list body)
|
||||
(when (cdr (assoc :epilogue params))
|
||||
(list (cdr (assoc :epilogue params)))))
|
||||
"\n"))
|
||||
|
||||
(defun org-babel-execute:R (body params)
|
||||
"Execute a block of R code.
|
||||
@ -117,7 +115,8 @@ This function is called by `org-babel-execute-src-block'."
|
||||
(cdr (assoc :session params)) params))
|
||||
(colnames-p (cdr (assoc :colnames params)))
|
||||
(rownames-p (cdr (assoc :rownames params)))
|
||||
(graphics-file (org-babel-graphical-output-file params))
|
||||
(graphics-file (and (member "graphics" (assq :result-params params))
|
||||
(org-babel-graphical-output-file params)))
|
||||
(full-body
|
||||
(let ((inside
|
||||
(list (org-babel-expand-body:R body params graphics-file))))
|
||||
|
@ -283,6 +283,8 @@ Returns a list
|
||||
;; resolve variable references and add summary parameters
|
||||
(when (and info (not light))
|
||||
(setf (nth 2 info) (org-babel-process-params (nth 2 info))))
|
||||
(when info
|
||||
(setf (nth 2 info) (org-babel-generate-file-param name (nth 2 info))))
|
||||
(when info (append info (list name indent head)))))
|
||||
|
||||
(defvar org-babel-exp-reference-buffer nil
|
||||
@ -2435,6 +2437,16 @@ parameters when merging lists."
|
||||
(setq exports (funcall e-merge exports-exclusive-groups
|
||||
exports '("results"))))
|
||||
(setq params (cons pair (assq-delete-all (car pair) params)))))
|
||||
(:file-ext
|
||||
(when (cdr pair)
|
||||
(setq results (funcall e-merge results-exclusive-groups
|
||||
results '("file")))
|
||||
(unless (or (member "both" exports)
|
||||
(member "none" exports)
|
||||
(member "code" exports))
|
||||
(setq exports (funcall e-merge exports-exclusive-groups
|
||||
exports '("results"))))
|
||||
(setq params (cons pair (assq-delete-all (car pair) params)))))
|
||||
(:exports
|
||||
(setq exports (funcall e-merge exports-exclusive-groups
|
||||
exports (split-string (cdr pair)))))
|
||||
@ -2890,10 +2902,48 @@ For the format of SAFE-LIST, see `org-babel-safe-header-args'."
|
||||
(member (cdr pair) (cdr entry)))
|
||||
(t nil)))))))
|
||||
|
||||
(defun org-babel-generate-file-param (src-name params)
|
||||
"Calculate the filename for source block results.
|
||||
|
||||
The directory is calculated from the :output-dir property of the
|
||||
source block; if not specified, use the current directory.
|
||||
|
||||
If the source block has a #+NAME and the :file parameter does not
|
||||
contain any period characters, then the :file parameter is
|
||||
treated as an extension, and the output file name is the
|
||||
concatenation of the directory (as calculated above), the block
|
||||
name, a period, and the parameter value as a file extension.
|
||||
Otherwise, the :file parameter is treated as a full file name,
|
||||
and the output file name is the directory (as calculated above)
|
||||
plus the parameter value."
|
||||
(let* ((file-cons (assq :file params))
|
||||
(file-ext-cons (assq :file-ext params))
|
||||
(file-ext (cdr-safe file-ext-cons))
|
||||
(dir (cdr-safe (assq :output-dir params)))
|
||||
fname)
|
||||
;; create the output-dir if it does not exist
|
||||
(when dir
|
||||
(make-directory dir t))
|
||||
(if file-cons
|
||||
;; :file given; add :output-dir if given
|
||||
(when dir
|
||||
(setcdr file-cons (concat (file-name-as-directory dir) (cdr file-cons))))
|
||||
;; :file not given; compute from name and :file-ext if possible
|
||||
(when (and src-name file-ext)
|
||||
(if dir
|
||||
(setq fname (concat (file-name-as-directory (or dir ""))
|
||||
src-name "." file-ext))
|
||||
(setq fname (concat src-name "." file-ext)))
|
||||
(setq params (cons (cons :file fname) params))))
|
||||
params))
|
||||
|
||||
;;; Used by backends: R, Maxima, Octave.
|
||||
(defun org-babel-graphical-output-file (params)
|
||||
"File where a babel block should send graphical output, per PARAMS."
|
||||
(unless (assq :file params)
|
||||
(if (assq :file-ext params)
|
||||
(error ":file-ext given but no :file generated; did you forget to give a block a #+NAME?")
|
||||
(error "No :file header argument given; cannot create graphical result.")))
|
||||
(and (member "graphics" (cdr (assq :result-params params)))
|
||||
(cdr (assq :file params))))
|
||||
|
||||
|
@ -458,3 +458,37 @@ comments for ":var":
|
||||
"0"))))
|
||||
(format "elisp a:%d, b:%d, c:%d, d:%d, e:%d" a b c d e)
|
||||
#+END_SRC
|
||||
|
||||
* =:file-ext= and =:output-dir= header args
|
||||
:PROPERTIES:
|
||||
:ID: 93573e1d-6486-442e-b6d0-3fedbdc37c9b
|
||||
:END:
|
||||
#+name: file-ext-basic
|
||||
#+BEGIN_SRC emacs-lisp :file-ext txt
|
||||
nil
|
||||
#+END_SRC
|
||||
|
||||
#+name: file-ext-dir-relative
|
||||
#+BEGIN_SRC emacs-lisp :file-ext txt :output-dir foo
|
||||
nil
|
||||
#+END_SRC
|
||||
|
||||
#+name: file-ext-dir-relative-slash
|
||||
#+BEGIN_SRC emacs-lisp :file-ext txt :output-dir foo/
|
||||
nil
|
||||
#+END_SRC
|
||||
|
||||
#+name: file-ext-dir-absolute
|
||||
#+BEGIN_SRC emacs-lisp :file-ext txt :output-dir /tmp
|
||||
nil
|
||||
#+END_SRC
|
||||
|
||||
#+name: file-ext-file-wins
|
||||
#+BEGIN_SRC emacs-lisp :file-ext txt :file foo.bar
|
||||
nil
|
||||
#+END_SRC
|
||||
|
||||
#+name: output-dir-and-file
|
||||
#+BEGIN_SRC emacs-lisp :output-dir xxx :file foo.bar
|
||||
nil
|
||||
#+END_SRC
|
||||
|
@ -1237,6 +1237,28 @@ echo \"$data\"
|
||||
(org-babel-execute-src-block)))
|
||||
(should (= noweb-expansions-in-cache-var 2)))))
|
||||
|
||||
(ert-deftest test-org-babel/file-ext-and-output-dir ()
|
||||
(org-test-at-id "93573e1d-6486-442e-b6d0-3fedbdc37c9b"
|
||||
(org-babel-next-src-block)
|
||||
(should (equal "file-ext-basic.txt"
|
||||
(cdr (assq :file (nth 2 (org-babel-get-src-block-info t))))))
|
||||
(org-babel-next-src-block)
|
||||
(should (equal "foo/file-ext-dir-relative.txt"
|
||||
(cdr (assq :file (nth 2 (org-babel-get-src-block-info t))))))
|
||||
(org-babel-next-src-block)
|
||||
(should (equal "foo/file-ext-dir-relative-slash.txt"
|
||||
(cdr (assq :file (nth 2 (org-babel-get-src-block-info t))))))
|
||||
(org-babel-next-src-block)
|
||||
(should (equal "/tmp/file-ext-dir-absolute.txt"
|
||||
(cdr (assq :file (nth 2 (org-babel-get-src-block-info t))))))
|
||||
(org-babel-next-src-block)
|
||||
(should (equal "foo.bar"
|
||||
(cdr (assq :file (nth 2 (org-babel-get-src-block-info t))))))
|
||||
(org-babel-next-src-block)
|
||||
(should (equal "xxx/foo.bar"
|
||||
(cdr (assq :file (nth 2 (org-babel-get-src-block-info t))))))
|
||||
))
|
||||
|
||||
(provide 'test-ob)
|
||||
|
||||
;;; test-ob ends here
|
||||
|
Loading…
Reference in New Issue
Block a user