Open wavexx opened 10 years ago
I try to be consistent with how the builtin replace-regexp
and query-replace-regexp
behave. Both of them work on the active region or from the current point onwards.
It should be possible to create a wrapper function, or a keyboard macro, that does what you want though.
Maybe something like this, though I haven't checked if it works in all circumstances:
(defun vr-replace-whole-buffer ()
(interactive)
(save-excursion
(beginning-of-buffer)
(call-interactively 'vr/replace)))
If you insist on using the prefix argument to choose between the two behaviors:
(defun vr-replace-whole-buffer (arg)
(interactive "P")
(save-excursion
(when arg
(beginning-of-buffer))
(call-interactively 'vr/replace)))
Though I would not recommend it, as this might conflict with a potential future use of the prefix argument in those functions.
On 07/23/2014 12:14 PM, benma wrote:
I try to be consistent with how the builtin
replace-regexp
andquery-replace-regexp
behave. Both of them work on the active region or from the current point onwards.
I'd like replace-regexp/query-regexp to be consistent with the isearch-* functions to be totally honest. They should start from the current point, show the preview matches also above the point. The query functions should also start from the point, but then wrap around.
It should be possible to create a wrapper function, or a keyboard macro, that does what you want though.
Not "exactly", as calling (beginning-of-buffer) will move the point away from the current position. So if I was trying to match something just above/under the cursor, it's would be suddenly out of sight.
For the normal replace-string/query-replace/query-regexp-replace it doesn't matter, as they are not interactive.
But for vr/query|vr/replace it does, as ideally the preview should not move the point, but still highlight matches above.
I was able to define a new interactive function by using directly (vr--interactive-get-args) and then setting the point/calling vr/replace... But of course you won't have a preview/count for matches above the point :(
Having proper wrappers around the replace functions is also tricky to get right. I've currently refined this this:
(defmacro global-replace-function (fun) `(defun ,(intern (concat "global-" (symbol-name fun))) () (interactive) (setq this-original-command ',fun) ; fix mc/maybe-m-c-m loop (let ((region (use-region-p)) (mark (point-marker))) (unless region (goto-char (point-min))) (unwind-protect (call-interactively ',fun) (if (and (not region) ; region initially active (not (use-region-p))) ; region re-activated (goto-char (marker-position mark)))))))
(global-replace-function vr/mc-mark) (global-replace-function vr/replace) ....
in order to define global-* variants that operate correctly when the mark is active, when using mc-mark, etc. And still it sucks!
For a wrap-around query-replace, how about using vr--interactive-get-args
to get the arguments, and then call vr/query-replace
twice in succession, once with current point to point-max, and then once again from point-min to original point?
Disregarding some details, something like this (where the arguments are obtained beforehand with vr--interactive-get-args
):
(let ((current-point (point)))
(vr/query-replace "regexp" "replace" current-point (point-max))
(vr/query-replace "regexp" "replace" (point-min) current-point)
))
I could patch vr--interactive-get-args
to accept arguments to control start and end. Preview feedback while entering the arguments would then be decoupled from where the replacement would actually be performed. This way, you could use it to display preview from (window-start)
or (point-min)
, i.e. the region before point.
In the same way, you could get feedback from before point, and afterwards run vr/replace with whatever range you want, to get a full buffer replace.
Sounds good?
On 07/27/2014 08:54 AM, benma wrote:
For a wrap-around query-replace, how about using
vr--interactive-get-args
to get the arguments, and then callvr/query-replace
twice in succession, once with current point to point-max, and then once again from point-min to original point?Disregarding some details, something like this (where the arguments are obtained beforehand with
vr--interactive-get-args
):(let ((current-point (point))) (vr/query-replace "regexp" "replace" current-point (point-max)) (vr/query-replace "regexp" "replace" (point-min) current-point) ))
Sounds good. As for query-replace, please return some different value if the replace is aborted, so we can skip the second call if the user wants to stop.
I could patch
vr--interactive-get-args
to accept arguments to control start and end. Preview feedback while entering the arguments would then be decoupled from where the replacement would actually be performed. This way, you could use it to display preview from(window-start)
or(point-min)
, i.e. the region before point.
Yes, if the preview region is decoupled, it would work nicely.
Sounds good?
I like the proposal :)
Any updates on the status of this issue? Do the new helper functions make this any easier to implement?
Not sure if there are any updates on this, but as a workaround, I've added the following to my .emacs
:
(defun vr--use-whole-buffer ()
(unless (region-active-p) (setq vr--target-buffer-start (point-min))))
(advice-add 'vr--set-target-buffer-start-end :after 'vr--use-whole-buffer)
This will search the whole buffer in vr/replace
and vr/query-replace
when there's no region selected.
Is it possible to have a setting (and a prefix argument to override it) for vr/replace and vr/query-replace to operate on the entire buffer when there's no mark?
Ideally, the when matching the entire buffer, the point should not be moved until the replace is executed (so that I can match on the text I'm looking at, not at the beginning of the buffer which might contain nothing).
For query-replace, it would be nice if the query would wrap around like isearch, but I would be absolutely happy if it would just start from (point-min).
I'm tired of going to the beginning of the buffer just to perform a global replace...
Thanks