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:
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?
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 thishelm
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.