5

I'm trying to capture stderr separately from stdout for a (synchronous) process run from emacs. I've found one way of doing it based on some code copied from emacs' shell-command function (I don't want to use shell-command directly because there is no need for a shell and shell-command puts stdout into a buffer):

(defun helm-dash-sql (db-path sql)
  "Run the sql command, parse the results and display errors"
  (helm-dash-parse-sql-results
   (with-output-to-string
     (let ((error-file (make-temp-file "helm-dash-errors-file")))
       (call-process "sqlite3" nil (list standard-output error-file) nil
                     ;; args for sqlite3:
                     db-path sql)

       ;; display errors, stolen from emacs' `shell-command` function
       (when (and error-file (file-exists-p error-file))
         (if (< 0 (nth 7 (file-attributes error-file)))
             (with-current-buffer (get-buffer-create "*helm-dash-errors*")
               (let ((pos-from-end (- (point-max) (point))))
                 (or (bobp)
                     (insert "\f\n"))
                 ;; Do no formatting while reading error file,
                 ;; because that can run a shell command, and we
                 ;; don't want that to cause an infinite recursion.
                 (format-insert-file error-file nil)
                 ;; Put point after the inserted errors.
                 (goto-char (- (point-max) pos-from-end)))
               (display-buffer (current-buffer))))
     (delete-file error-file))))))

However I suspect it could be done better in two ways:

  1. It seems like this should be a solved problem and emacs should have a function that just "does the right thing" with stderr, but I can't find one. Is there such a function?

  2. Every time a process is run shell-command creates (and later deletes) a temp file in which to store stderr. We are slightly concerned that this could have a performance impact because multiple processes are run for every keypress while inside this helm command. Is this likely to be an issue, and if so what is the best way around it?


For anyone curious: this is for helm-dash. The exact code I'm currently using is in this pull-request.

7

This is fixed in Emacs 25, where you can use the make-process function with the :stderr argument. I don't think there's anything suitable in Emacs 24.

  • Is there a synchronous version of make-process? Or am stuck with choosing between the horrifying hack in the OP versus some kind of horrifying busy-loop/polling hack to block until the process exits? – Radon Rosborough Jul 27 '17 at 5:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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