This can be done, I managed to get it working (with help from @wasamasa), notes:
- The selection needs to be stored and restored.
- It's important to run
deactivate-mark
is nil
so Emacs can restore the selection.
- Special handling is needed for evil-visual-line mode,
(evil-visual-select ...)
needs to be called.
Below is a wrapper for shell-command-on-region
that handles re-selection.
;; Wrapper for 'shell-command-on-region', keeps the selection.
(defun my-shell-command-on-region-and-select
(start
end
command
&optional
output-buffer
replace
error-buffer
display-error-buffer
region-noncontiguous-p)
"Wrapper for 'shell-command-on-region', re-selecting the output.
Useful when called with a selection, so it can be modified in-place."
(interactive)
(let ((buffer-size-init (buffer-size)))
(shell-command-on-region
start
end
command
output-buffer
replace
error-buffer
display-error-buffer
region-noncontiguous-p)
(setq deactivate-mark nil)
(setq end (+ end (- (buffer-size) buffer-size-init)))
(set-mark start)
(goto-char end)
(activate-mark)
;; needed for evil line mode
(when (and (boundp evil-state) (string= evil-state "visual"))
(when (eq (evil-visual-type) evil-visual-line)
(evil-visual-select start end 'line)))))
Example call:
(my-shell-command-on-region-keep-region-and-select
(region-beginning) (region-end)
"tr A-Za-z a-zA-Z && echo ' extra text'")