I'd like to replace my selection with the output of a program, an annoyance is - when there is an error, the error replaces my text.
Is there a way to check the exit code and only replace the text if it's zero.
I'd like to replace my selection with the output of a program, an annoyance is - when there is an error, the error replaces my text.
Is there a way to check the exit code and only replace the text if it's zero.
I would suggest considering to report a bug. Personally I'm fine with it, since it's easy to fix via C-/ (undo
).
To do what you want right now, my first thought is to advice shell-command-on-region
, something like:
(define-advice shell-command-on-region (:filter-return (exit-status) failture)
(prog1 exit-status
(unless (zerop exit-status)
(let ((msg (buffer-substring (region-beginning) (region-end))))
(undo)
(message "%s" msg)))))
but it's not a clean way, and defining a new command is straightforward:
(defun my-shell-command-on-region (beg end command)
"Alternative to C-u M-| (`shell-command-on-region')."
(interactive
(let ((s (read-shell-command "Shell command on region: ")))
(list (region-beginning)
(region-end)
s)))
(let* ((temp-buffer (generate-new-buffer " *temp*"))
(exit-status (call-shell-region beg end command nil temp-buffer))
(output (with-current-buffer temp-buffer
(buffer-string))))
(if (zerop exit-status)
(progn (delete-region beg end)
(insert output))
(message "%s" output))))