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
(setq deactivate-mark 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.
(defun 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 (string= evil-state "visual")
(when (eq (evil-visual-type) evil-visual-line)
(evil-visual-select start end 'line)))))
Example call:
(shell-command-on-region-keep-region-and-select
(region-beginning) (region-end)
"tr A-Za-z a-zA-Z && echo ' extra text'")