7

Is there a way to use file local variables set in an org-mode file in the following contexts:

  1. Simply expanding the variable when text is exported (eg: to LaTeX)
  2. Passing the value to :var in a babel source block (SQL or Python)
  3. Expanding the variable in a org-mode table for use in #+TBLFM

For example here is the local variable definition at the end of the document:

# Local Variables:                                             
# mode: org
# foo: bar
# aNumber: 32                                                     
# End:  

Context 1:

* First Section
is about <foo>

Context 2:

#+BEGIN_SRC python :var baz=<foo>
print(baz)
#+END_SRC

Context 3:

|Numbers | NumbersMultipliedBy2 |
|<aNumber>   | =@2$1 * 2            |
PeterT
  • 73
  • 1
  • 4

1 Answers1

4

Orgmode's export function copies the buffer content to a new buffer and evaluates the source blocks in the new buffer. Thereby only buffer local variables with prefixes org- and orgtbl- are copied from the original buffer to the new one.

That means you need to prefix your buffer local variables with org- or orgtbl-.

In order to avoid clashes between org variables and your own buffer local variables I suggest to use some unique id at the second position of the name, e.g., org-my-....

I did not find a simple inline substitution of local variables by their evaluation result.
The closest one gets is inline source code src_emacs-lisp[:var baz=org-my-foo]{baz}. The problem is that the :exports header argument does not work for inline source code. So you cannot suppress the source code.

For that reason I defined a new eval: link type with the following elisp code.

(require 'org)

(defun my-org-link-eval (path &rest _rest)
  "Evaluate PATH and return result as string."
  (condition-case err
      (prin1-to-string (eval (read path)))
    (error (format "Error in eval of %S: %S." path err))))

(defun my-org-link-eval-activate (start end path bracketp)
  "Display text from START to END as result of the eval of PATH.
BRACKETP is ignored."
  (save-excursion
    (if org-descriptive-links
      (add-text-properties
       start end
       (list 'display (propertize (my-org-link-eval path) 'face 'org-link)))
      (remove-text-properties start end '(display nil)))))

(org-link-set-parameters "val"
             :export #'my-org-link-eval
             :activate-func #'my-org-link-eval-activate)

If you install that code in your init file and restart emacs you can use the following org file as a demo for all your contexts.

Context 1:
* First Section
is about [[val:org-my-foo]]

Context 2:

#+BEGIN_SRC python :var baz=(prin1-to-string org-my-foo) :exports results
return(baz)
#+END_SRC

#+RESULTS:
: bar

Context 3:

| Numbers | NumbersMultipliedBy2 |
|---------+----------------------|
|      32 |                   64 |
#+TBLFM: $1='(prin1-to-string org-my-aNumber)::$2=@2$1 * 2

# Local Variables:                                             
# mode: org
# org-my-foo: bar
# org-my-aNumber: 32                                                     
# End:

With descriptive links activated [[eval:org-my-foo]] is displayed as bar. Independently of the display the link always exports to bar.

The header argument :var baz=(prin1-to-string org-my-foo) of the python source block evaluates org-my-foo in the course of function argument evaluation and formats the resulting value as string. The resulting string is assigned to the python variable baz.

The '(prin1-to-string org-my-aNumber) in the table formula evaluates the lisp form (prin1-to-string org-my-aNumber) in the same way as in the previous paragraph.

Tobias
  • 32,569
  • 1
  • 34
  • 75