Pipe to Emacs
While there are many ways to pipe to emacs, they all involve either shuttling text by repeatedly calling emacsclient or writing to a temporary file. However, neither are necessary.
Basically, while emacs can't (yet) read from a named pipe (FIFO), it can read
standard output from a process so, one gratuitous use of cat
later...
(defun pager-read-pipe (fname)
(let ((buf (generate-new-buffer "*pager*"))
(pname (concat "pager-" fname)))
(with-current-buffer buf (read-only-mode))
(switch-to-buffer buf)
(let ((proc (start-process pname buf "/usr/bin/cat" fname)))
(set-process-sentinel proc (lambda (proc e) ()))
(set-process-filter proc (lambda (proc string)
(when (buffer-live-p (process-buffer proc))
(with-current-buffer (process-buffer proc)
(save-excursion
;; Insert the text, advancing the process marker.
(let ((inhibit-read-only t))
(goto-char (process-mark proc))
(insert string)
(set-auto-mode)
(set-marker (process-mark proc) (point))))))))
proc)))
...and you can read a from named pipe. As an added bonus, this function will try to autodetect the correct mode.
To actually use this, I recommend the following shell script:
#!/bin/bash
set -e
cleanup() {
trap - TERM INT EXIT
if [[ -O "$FIFO" ]]; then
rm -f "$FIFO" || :
fi
if [[ -O "$DIR" ]]; then
rmdir "$DIR" || :
fi
}
trap "cleanup" TERM INT EXIT
SOCKET="${XDG_RUNTIME_DIR:-/run/user/$UID}/emacs/server"
# Create a named pipe in /dev/shm
DIR=$(mktemp -d "/dev/shm/epipe-$$.XXXXXXXXXX")
FIFO="$DIR/fifo"
mkfifo -m 0600 "$DIR/fifo"
# Ask emacs to read from the names socket.
emacsclient -s "$SOCKET" -n --eval "(pager-read-pipe \"$FIFO\")" >/dev/null <&-
exec 1>"$FIFO"
cleanup # Cleanup early. Nobody needs the paths now...
cat
You will probably need to set the SOCKET
variable to your emacs socket filename.
Usage:
$ dmesg --follow | epipe