reddit / emacs

Replace org links content, or replace strings in buffer

inwit_ · 2022-04-22 21:34
I'm slowly learning elisp, and, as part of some org file processing that I want to do, I need to replace the content part of org-mode links (which are of the form: `[[path][content]]`) in a buffer. After looking around for a function that does that I couldn't find it, so I thought a good training might be to try to write it from sratch. I came up with: (defun inwit/replace-org-link-description (link new-description) (setq content-start-point (org-element-property :contents-begin link)) (setq content-end-point (org-element-property :contents-end link)) (setq len-thing-to-remove (- content-end-point content-start-point)) (setq len-thing-to-add (length new-description)) (setq offset-delta (- len-thing-to-add len-thing-to-remove)) (delete-region content-start-point content-end-point) (goto-char (+ content-start-point offset-delta)) (insert new-description) ) However, this doesn't quite work, especially if it is run sequentially over several links in a buffer, because the substitutions (both the deletions and the insertions) start missing the correct spots after the first replacement, which works fine. What is happening here? I know that `delete-region` leaves the point where it should, and I thought that also `insert` does place the point after the insertion. However, I don't see how sequential calls to this function in a map loop can miss the right spots after the first one. It's like the numbering of the positions in the buffer does not update with my substitutions. In other words, is there a way to update the buffer so the following calls to my function can refer to the actual positions of the already modified buffer? Or, am I missing the point and there is a much better way to approach this task?
Illiamen · 2022-04-23 04:24
1. Use `let` (or `let*`) to contain your variables to the function. If you only use `setq`, the variables will exist outside of the function. That can cause unexpected behavior in itself. 2. I'm not familiar with the Org parser. If you know the form of what you want to find and replace, have you tried just using `replace-regexp`? 3. Interactively, `C-c C-l` can update the link and description at point. Maybe you could copy how it works.
inwit_ · 2022-05-04 14:54
Thanks, Illiamen. I followed your suggestion, and came up with a regexp-based substitution including a loop over `re-search-forward` using `replace-match` to replace just the description with a string computed on the fly. [Here](https://github.com/rougier/mu4e-dashboard/issues/42#issuecomment-1117408127) it is, in context.