Context: I want to create a command that can increment a number or character contained within an arbitrary area of a buffer. I've reduced the problem to calling some function to set the text of a narrowed buffer, a la replace-region-contents
, with the following additional properties:
- markers that start on either end of the region (including mark and point themselves) stay on either end of the replaced text
- markers that start within the region are bounded by the region (they stay within the region or at either end)
- the positions taken as parameters to the command are not treated specially, and the command does not explicitly set point or mark
- the command does not print any messages
No method I know of so far has all the above properties.
- The best by far is
replace-region-contents
itself, and when the original and resulting strings are similar, it is perfect. But otherwise, the first property is not upheld replace-regexp
seems to be appropriate except that it prints messages on every operation- manually deleting and inserting does not respect markers at all
- I thought maybe manually inserting then deleting would be better, but it is not
Is there any function that does what I want? If not, how would I do this myself?
Edit: Prompted by @phils, I tried to reproduce the trouble I was having earlier with replace-region-contents
As requested, here is a recipe / test showing that markers are not preserved by replace-region-contents
in the way I'd like for this case:
(progn
'original ; < this symbol will be replaced
(setq mark1 (copy-marker 10))
(setq mark2 (copy-marker 19))
(setq replacement "'replacement") ; < with this
(replace-region-contents mark1 mark2 (lambda () replacement))
(set-mark mark1)
(goto-char mark2)
(setq deactivate-mark nil)
;; and I want for markers that surrounded the text before replacement
;; to surround the new text after replacement
(cl-assert (eq (marker-position mark1) 10) :show)
(cl-assert (eq (marker-position mark2) (+ mark1 (length replacement))) :show)
)
second edit: my test was flawed, and my description of the constraints were inaccurate. I have now updated both the conditions and the test.
Having typed all this out, though, I suspect that a "solution" could end up being a bit of a hack, and my approach may be over-engineered. I might just reduce the problem to working with only mark and point, not caring about where other markers end up.
replace-region-contents
? Markers outside the region (and I'm assuming that "just outside the region" is what you mean) ought to retain their relative positions. If they don't, pleaseM-x report-emacs-bug
. Markers inside the region are subject to the text changes.