ELisp: Beware of Region Boundary Change
Got stung by region in emacs, wasted about 4 hours. Here's what i learned.
Whenever you work in a region, remember that the boundaries of the text that you are interested is changed when you add or remove text in that region. For example, suppose p1 and p2 is the boundary of some text you are interested. After doing some change there, suppose you want to do some more change. Don't just call
(something-region p1 p2) again, because p2 is no longer the correct boundary.
narrow-to-region, like this:
(save-restriction (narrow-to-region pos1 pos2) (something1-region (point-min) (point-max)) (something2-region (point-min) (point-max)) … )
Last week, i updated the article Emacs Lisp: Syntax Color Source Code in HTML and re-implemented several of my personal commands, and today found that it behaved incorrectly: it deleted text outside of a region!
Here's a function
dehtmlize-span-region effected by this:
;; WRONG! INCORRECT! DO NOT USE (defun dehtmlize-span-region (p1 p2) (interactive "r") (replace-regexp-pairs-region p1 p2 '(["<span class=\"[^\"]+\">" ""])) (replace-pairs-region p1 p2 '( ["</span>" ""] ["&" "&"] ["<" "<"] [">" ">"] ) ) )
Note how innocuous it looks.
p2 are my region boundaries, and i work on them. Here's the correct code:
;; correct (defun dehtmlize-span-region (p1 p2) (interactive "r") (save-excursion (save-restriction (narrow-to-region p1 p2) (replace-regexp-pairs-region (point-min) (point-max) '(["<span class=\"[^\"]+\">" ""])) (replace-pairs-region (point-min) (point-max) '( ["</span>" ""] ["&" "&"] ["<" "<"] [">" ">"] ) ) ) ) )
Looks so trivial a thing, but i spent 4 hours debugging to realize the fact that when i modified the text in region by my first function, the region boundary has changed. I remember, few years ago, i also spent half a day on region problems and wrongly concluded that
narrow-to-region should be avoided in elisp program.