4

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.

2
  • I don't use shell-command-on-region, but a quick glance at the code reveals that it uses exit-status throughout the function to decide what to do. One idea would be to take the function and modify it (creating a new custom function) to suit your needs -- if exit-status is successful, then do x/y/z, else, do something else. I realize 99.9 percent of Emacs users want things like defadvice and other tweaks that don't directly modify the code of existing function, but I am that 0.1 percent who modifies anything and everything.
    – lawlist
    Nov 23, 2017 at 6:27
  • Good to know, I cobbled together this function which needs to be modified to check exit code I expect. emacs.stackexchange.com/a/37030
    – ideasman42
    Nov 23, 2017 at 7:55

1 Answer 1

5

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))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.