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.

ideasman42
  • 8,375
  • 1
  • 28
  • 105
  • 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 '17 at 06:27
  • Good to know, I cobbled together this function which needs to be modified to check exit code I expect. https://emacs.stackexchange.com/a/37030 – ideasman42 Nov 23 '17 at 07:55

1 Answers1

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))))
xuchunyang
  • 14,302
  • 1
  • 18
  • 39