How one can programmatically read and set a buffer-wide org-mode property?

I am aware of this, which points to

(org-entry-put POM "PWE-1" "47")

but it does not seem useful in case of buffer global properties.


If a file has buffer global properties, like,

#+PROPERTY: Cite "Silmarillon 1984"
#+PROPERTY: my/common-list (1 "two" (1 2 3 5 7))

How could one fetch, for example, the buffer-wide property PWE-1, or any other?

How would one set it, ie, write a different value, say

#+PROPERTY: PWE-1 2197

so that the buffer will keep the updated value as stored in the file, available at next load?

Where could I look up similar information in detail? Is there a detailed list of org-mode's API?

Thank you in advance.

  • There is org-element-parse-buffer. Maybe, that helps. As far as I remember, you get also the buffer positions of the parsed stuff. So you can replace the text for PWE-1. (Don't have time to check right now.) – Tobias Apr 6 '16 at 11:34
  • Thank you for the pointer. That page pointed to orgmode.org/worg/exporters/org-element-docstrings.html, but it does not seem to list a global #+PROPERTY as a parseable element? – gsl Apr 6 '16 at 11:47
  • 1
    Just do (setq p (org-element-parse-buffer)) and you will get (org-data nil (section (:begin 1 :end 108 :contents-begin 1 :contents-end 107 :post-blank 1 :parent #0) (keyword (:key "PROPERTY" :value "PWE-1 42" :begin 1 :end 22 :post-blank 0 :post-affiliated 1 :parent #1)) at the beginning of p if your example text is at the beginning of the current org-buffer. – Tobias Apr 6 '16 at 12:52
  • Wouldn't it be :PROPERTIES:, then :PWE-1: 42, then :END:? – mankoff Apr 6 '16 at 13:03
  • @mankoff That would be a drawer for the current tree. #+PROPERTY: PWE-1 42 is also fine. That's global. (See info files.) – Tobias Apr 6 '16 at 13:44

You could just do a text search for #+PROPERTY: ....

Alternatively, you can use the following functions. These functions take into account that values can be accumulated via + and it is an error if the first PROPERTY key has a +. (Is that true?)

(require 'cl-lib)

(defun org-global-props-key-re (key)
  "Construct a regular expression matching key and an optional plus and eating the spaces behind.
Test for existence of the plus: (match-beginning 1)"
  (concat "^" (regexp-quote key) "\\(\\+\\)?[[:space:]]+"))

(defun org-global-props (&optional buffer)
  "Get the plists of global org properties of current buffer."
  (with-current-buffer (or buffer (current-buffer))
    (org-element-map (org-element-parse-buffer) 'keyword (lambda (el) (when (string-equal (org-element-property :key el) "PROPERTY") (nth 1 el))))))

(defun org-global-prop-value (key)
  "Get global org property KEY of current buffer.
Adding up values for one key is supported."
  (let ((key-re (org-global-props-key-re key))
    (props (org-global-props))
    (cl-loop with val for prop in props
         when (string-match key-re (setq val (plist-get prop :value))) do
          val (substring val (match-end 0))
          ret (if (match-beginning 1)
              (concat ret " " val)

(defun org-global-prop-set (key value)
  "Set the value of the first occurence of
add it at the beginning of file if there is none."
    (let* ((key-re (org-global-props-key-re key))
       (prop (cl-find-if (lambda (prop)
                   (string-match key-re (plist-get prop :value)))
      (if prop
        (assert (null (match-beginning 1)) "First occurence of key %s is followed by +." key)
        (goto-char (plist-get prop :begin))
        (kill-region (point) (plist-get prop :end)))
    (goto-char 1))
      (insert "#+PROPERTY: " key " " value "\n"))))
  • 1
    This is exactly what I was looking for. I am able to fetch and set a buffer-wide property just by specifying its name, ie (org-global-prop-value "pwe-1"), (org-global-prop-set "pwe-1" "77"). Your code is quite instructive, I am learning a lot. It should be included in org-mode API, I am sure I am not the only one to find it very useful! Thank you. – gsl Apr 7 '16 at 7:07
  • org-global-prop-value is quite slow – Toothrot Jan 28 '20 at 22:20
  • This is insanely difficult for such a common need. – RichieHH Dec 21 '20 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.