(require 'org-element) (defun eth/linkAttachments (examName examDir) ;; When called interactively (M-x), ask for arguments (interactive "MExam name: \nMAttachments directory: ") (unless (derived-mode-p 'org-mode) (error "This function can only be run in an org-mode buffer")) ;; We wrap the entire operation in `save-excursion` so that the ;; user's cursor position is restored after the function completes, ;; even though we are moving around and modifying the buffer. (save-excursion (org-map-entries (lambda () (let* ( (baseFilename (org-entry-get (point) "baseFilename")) (attachment (concat examDir "/" baseFilename ".pdf")) (exams-heading-pos nil) ) (when (file-exists-p attachment) (catch 'found (org-map-entries (lambda () (when (string= (org-get-heading t) "Exams") (setq exams-heading-pos (point)) (throw 'found t) ) ) t 'tree ) ) (when exams-heading-pos (goto-char exams-heading-pos) (let* ( (current-level (org-outline-level)) (new-level (1+ current-level)) (stars (make-string new-level ?*)) (link (format "[[file:%s][%s]]" attachment examName)) (new-heading (format "\n%s %s" stars link)) ) (org-end-of-subtree) (insert new-heading)) ) ) )) "baseFilename={.+}" 'file) ) (message "Done linking files") )