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 (of the region you are interested).
Use “save-restriction” and “narrow-to-region”, like this:
(save-restriction
(narrow-to-region pos1 pos2)
(something1-region (point-min) (point-max))
(something2-region (point-min) (point-max))
…
)
I got stung by this. Last week, i re-implemented some of my personal commands, and today found that it behaved incorrectly: it deleted text outside of a region!
Few days ago, i updated the article Emacs Lisp: Syntax Color Source Code in HTML. There's a function “dehtmlize-span-region” effected by this. It's corrected now. Here's a example:
(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. I have p1 and p2 as region, and i work on them. Here's the correct code:
(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 checking and testing and rewriting to finally realize this. 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.