help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: replace-regexp


From: Stefan Monnier
Subject: Re: replace-regexp
Date: Sat, 08 May 2021 09:53:06 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

>> > Maybe it has something to do with the replacement being
>> > longer than the original string?
>>
>> That's it, I think, as this doesn't give me the error:
>>
>> (defun md-latex-reduce (beg end)
>>   (interactive "r")
>>   (save-excursion
>>     (goto-char beg)
>>     (while (re-search-forward "_\\(.*\\)_" end t)
>>       (replace-match "\\1") )))
>
> And this is probably one of the reasons why most[citation needed]
> tutorials, when implementing a function operating on a region, do a
> ‘narrow-to-region’ first thing.
>
>     (defun md-latex-reduce (beg end)
>       (interactive "r")
>       (save-excursion
>         (save-restriction
>           (narrow-to-region beg end)
>
>           (goto-char (point-min))
>           (while (re-search-forward "_\\(.*\\)_" nil t)
>             (replace-match "\\\\textit{\\1}"))))
>
> You might probably solve the same issue by carefully tracking the
> lengthening of text — e.g. by incrementing ‘end’ by (- (length
> "\\\\textit{}") (length "__")) on each iteration — or by putting a
> marker at end and then passing that marker in re-search-forward. But
> narrowing is easier.

I recommend avoiding the use of narrowing as much as possible since it
can have other undesirable effects (e.g. it changes the result of
things like `syntax-ppss`).

There are indeed 2 "standard" solutions:
1- start your loop at the end, moving towards the beginning.
2- use a marker to keep track of the end.

You say "narrowing is easier", but using a marker is as simple as:

    (setq end (copy-marker end t))

so it's arguably simpler.


        Stefan




reply via email to

[Prev in Thread] Current Thread [Next in Thread]