I have several interactive functions that pretty straightforwardly do
replace-match in a loop. Once in a while, if I have a region selected and do the replacement in it,
re-search-forward throws an error with the message
Invalid search bound (wrong side of point), and the last
replace-match only replaces a part of the match, leaving some of its tail untouched. This error message is mightily uninformative, and I have no idea what it's trying to tell me and what I am supposed to do. I tried watching the values of the point and the search boundaries, and at least I can tell that the point doesn't seem to get outside of the boundaries. I also use
save-match-data if I'm doing fancy string manipulation in the function.
This seems to never happen if I don't use the region, and instead invoke the command on the current line. The only difference in this case is that I don't get the values for the search boundaries from
(interactive "r"), but take
(line-end-position), then hand those to
re-search-forward in the same way as with a region.
The code is like this:
(defun oh-woe (beg end)
(setq beg (line-beginning-position))
(setq end (line-end-position)))
(while (re-search-forward "foo" end t)
(replace-match "barbaz" t t)))
I might hypothesize that matches at the end of the search boundary pose a difficulty for
re-search-forward, particularly if
replace-match already did something before that position. However, lots of the time replacement in a region works fine, and only in some cases it errors out (100% reproducibly, though). Plus, presumably the last call to
re-search-forward would just return nil if the match doesn't fit, since that's what the boundary argument is for.
One would also think that
re-search-forward should use a marker for the boundary parameter, when it's called in a loop—to account for the text shifting after
replace-match. But, judging by the help and the manual, it doesn't support markers—and several examples of the use of this function that I've seen, just specify a static position. Should I use a marker manually, retrieving the position each time in the loop?
Update: some further investigation:
Invalid search bound (wrong side of point) is in fact thrown by
re-search-forward when the search boundary is before the current point. Guess I didn't watch the values that well.