Search code examples
emacshyperlinkorg-mode

Org mode internal link dynamic naming


Is there a way to rename links automatically based on the original headline?

Example:

* Headline 1
:PROPERTIES:
:ID: some_id
:END:

* Headline 2

 - Headline 1 // this is a link using an id

* Headline 3

 - Headline 1 // this is a link using an id

When creating a new internal link, org allows you to specify the text for that link. Is there a way to dynamically change that linking text based on the headline? If I change Headline 1 to Headline 4, I want the text of the links to also change to Headline 4 automatically.

Is that possible?


Solution

  • Its a little slow, but this worked:

    (defun us/description-of-target-link (target-id)
      (car (org-map-entries '(org-entry-get nil "ITEM") (concat "ID=\"" target-id "\"")))
      )
    
    (defun us/update-internal-link-descriptions ()
      (interactive)
      (setq offset 0)
      ;;; map over all elements in the buffer
      (org-element-map (org-element-parse-buffer) 'link
        (lambda (link)
          ;;; filter to internal links with id
          (when (string= (org-element-property :type link) "id")
            (setq content-start-point-raw (org-element-property :contents-begin link))
            (setq content-end-point-raw (org-element-property :contents-end link))
            (setq len-thing-to-remove (- content-end-point-raw content-start-point-raw))
            (setq new-description (us/description-of-target-link (org-element-property :path link)))
            (setq len-thing-to-add (length new-description))
            (setq offset-delta (- len-thing-to-add len-thing-to-remove))
            (setq content-remove-point-start-with-offset (+ content-start-point-raw offset))
            (setq content-remove-point-end-with-offset (+ content-end-point-raw offset))
            (goto-char content-remove-point-start-with-offset)
            (delete-region content-remove-point-start-with-offset content-remove-point-end-with-offset)
            (insert new-description)
            (setq offset (+ offset offset-delta ))
            )
          )
        )
      )