2

I have several interactive functions that pretty straightforwardly do re-search-forward and 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-beginning-position) and (line-end-position), then hand those to goto-char and re-search-forward in the same way as with a region.

The code is like this:

(defun oh-woe (beg end)
  (interactive "r")
  (unless (region-active-p)
    (setq beg (line-beginning-position))
    (setq end (line-end-position)))
  (goto-char beg)
  (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.

4
  • 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. I guess I didn't watch the values that well.
    – aaa
    Jun 28, 2023 at 15:06
  • Add the info from your comment to your question, if you think it might help others. Comments can be deleted at any time. Thx.
    – Drew
    Jun 28, 2023 at 16:19
  • @Drew Could you please say a couple words on what is meant by “Comments can be deleted at any time”? This is not even my first account on SE, but the first time I hear about this.
    – aaa
    Jun 28, 2023 at 16:26
  • Dunno more than that. Moderators can delete any comment, and the person who wrote a comment can delete that comment. The point is that Q&A need to stand on their own. Comments are not searchable, for instance - either on SE or by Google etc. search. SE is Q&A for everyone, and the typical access/discovery is by internet search.
    – Drew
    Jun 28, 2023 at 16:45

1 Answer 1

1

Should I use a marker manually

Yes, if you are repeatedly searching and replacing within the same initial beg end region, you need to use a marker to ensure that the bounds remain sane from one iteration to the next.

retrieving the position each time in the loop?

It's likely sufficient to simply set a marker for the original end position -- it will be adjusted at each replacement.

(Remember to set-marker to nil when you're done with it.)

judging by the help and the manual, it doesn't support markers

It does. That might be considered a documentation bug so you might M-x report-emacs-bug for that if it hasn't been raised already.

(For the code in question, see the fix_position function in buffer.c which is used by search_command in search.c. I'm looking at the code for 28.2.)

2
  • Seems to work, at least for now. Apparently I was wrong about the point staying in the bounds. Regarding “remember to set-marker to nil”—the manual says that markers get garbage-collected, though I guess I could relieve Emacs of some labor before the GC cycle comes.
    – aaa
    Jun 28, 2023 at 15:56
  • There have also been some Emacs bugs that resulted in this error. When reported they've been fixed. If you (OP) don't find a solution then you might want to report the problem, with a reproducible recipe starting from emacs -Q: M-x report-emacs-bug.
    – Drew
    Jun 28, 2023 at 16:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.