Thorsten Jolitz <tjol...@gmail.com> writes: Hi List,
> now that I understand the 'org-element API' a bit better, I think that > the following two functions can be very useful for creating and > modifying Org elements without the usual point movements, regexp > searches and string operations in a buffer: > > #+begin_src emacs-lisp > ;; might become `org-element-create' > (defun* tj/create-element (&optional insert-p &rest args &key (type > 'headline) &allow-other-keys) > "Create Org element, maybe insert at point." > (let ((strg (org-element-interpret-data > (list type args)))) > (if insert-p (insert strg) strg))) > #+end_src I made the second 'rewire element' function smarter so that it can now reuse the old value when setting a new value for a property of the 'rewired' element: #+begin_src emacs-lisp ;; might become `org-element-rewire' (defun* tj/rewire-element (&optional replace &rest args &key type &allow-other-keys) "Rewire element at point, maybe replace it. The former value of an element property can be reused in the creation of a new value by giving a `lambda' expession with one function argument instead of a value to a key. That argument will then be replaced by the property's former value when applying the function." (let* ((elem (org-element-at-point)) (plist (cadr elem)) (beg (org-element-property :begin elem)) (end (org-element-property :end elem)) strg) (while args (let* ((key (pop args)) (val-or-fun (pop args)) (old-val (org-element-property key elem)) (new-val (if (functionp val-or-fun) (apply val-or-fun (list old-val)) val-or-fun))) (setq plist (plist-put plist key new-val)))) (setq strg (org-element-interpret-data (list (or type (org-element-type elem)) plist))) (case replace (append (save-excursion (goto-char end) (insert strg))) (prepend (goto-char beg) (insert strg)) (t (if replace (let ((marker (save-excursion (goto-char end) (point-marker)))) (delete-region beg end) (goto-char marker) (set-marker marker nil) (save-excursion (insert strg))) strg))))) #+end_src #+results: : tj/rewire-element Here a few examples, all of them assuming point is at beginning of this src-block if not stated otherwise: #+begin_src emacs-lisp (+ 2 2) #+end_src 1. do M-: [content-of-next-src-block] #+begin_src emacs-lisp (tj/rewire-element 'append :name (format "rewired-%d" (1+ (random 10)))) #+end_src #+NAME: rewired-7 #+BEGIN_SRC emacs-lisp (+ 2 2) #+END_SRC 2. do M-: [content-of-next-src-block] #+begin_src emacs-lisp (tj/rewire-element 'append :name (lambda (_old_) (if _old_ (format "rewired-%d" (* (string-to-number (car (last (split-string _old_ "-" t)))) (1+ (random 10)))) (format "rewired-%d" (1+ (random 10))))) :language "picolisp") #+end_src gives #+NAME: rewired-2 #+BEGIN_SRC picolisp (+ 2 2) #+END_SRC when called on the original src-block, but #+NAME: rewired-63 #+BEGIN_SRC picolisp (+ 2 2) #+END_SRC when called on the result of usage example 1 (with name rewired-7). 3. do M-: [content-of-next-src-block] #+begin_src emacs-lisp (tj/rewire-element 'append :value (lambda (_old_) (concat "(message \"%d\" " (car (split-string _old_ "\n" t)) ")\n")) :parameters ":results raw") #+end_src gives #+BEGIN_SRC emacs-lisp :results raw (message "%d" (+ 2 2)) #+END_SRC -- cheers, Thorsten