Silent update 2019-09-25: added to blog series "Using Org Mode Features"
Update 2019-11-15: Screencast demo
Please do read my "Using Org Mode Features" (UOMF) series page for explanations on articles of this series.
If you are using Org-mode you might find yourself in a position, where you want to set or update a property value for an existing property.
In my case, I frequently do this for my contacts. Whenever a phone number changes, I add a note to the heading of the corresponding contact. Additionally, I maintain phone numbers in properties as well. To do this in a sane way, I only mark the new phone number (region) and press a keyboard shortcut which calls an Elisp function. This function asks me for the name of a property (with tab completion). Then, the value of this property is set to the string of the region.
Very handy.
Here is the Elisp code of my-org-region-to-property() which was made possible with the help of Antoine R. Dumont:
(defun org-read-entry-property-name ()
"Read a property name from the current entry."
(let ((completion-ignore-case t)
(default-prop (or (and (org-at-property-p)
(org-match-string-no-properties 2))
org-last-set-property)))
(org-completing-read
(format "Property [%s]: " (if default-prop default-prop ""))
(org-entry-properties nil nil)
nil nil nil nil default-prop)))
(defun my-org-region-to-property (&optional property)
"Copies the region as value to an Org-mode property"
(interactive)
;; if no region is defined, do nothing
(if (use-region-p)
;; if a region string is found, ask for a property and set property to
;; the string in the region
(let ((val (replace-regexp-in-string
"\\`[ \t\n]*" ""
(replace-regexp-in-string "[ \t\n]*\\'" ""
(substring (buffer-string)
(- (region-beginning) 1)
(region-end))))
)
;; if none was stated by user, read property from user
(prop (or property
(org-read-entry-property-name))))
;; set property
(org-set-property prop val))))
In the following screencast, you can see how I am adding a new contact to my Org mode contacts.org and how I make use of my-org-region-to-property():