A while back I posted a response to someone's question on reddit about how to get a list of all Emacs daemon buffers from a shell script. It was a pretty interesting problem so I thought I'd explain my answer here.
The question was "Is it there a way to export the list of opened buffers to STDOUT?".
In the comments I left a rather byzantine looking snippet of code that I'd managed to produce.
emacs --batch --eval "(require 'server)" --eval "(mapc #'print (read (server-eval-at \"server\" '(format \"%s\" (mapcar (lambda (buffer) (format \"\\\"%s\\\"\n\" buffer)) (buffer-list))))))" | sed '/^$/d; s/^"//g; s/"$//g'I've simplified the lisp slightly since I answered that question. Here's the updated version.
emacs --batch --eval "(require 'server)" --eval "(mapc #'princ (read (server-eval-at \"server\" '(prin1-to-string (mapcar (lambda (buffer) (format \"%s\\n\" buffer)) (buffer-list))))))" 2>/dev/nullHere it is written in a way that's easier to read.
emacs --batch \
--eval "(require 'server)" \
--eval "(mapc #'princ
(read (server-eval-at \"server\"
'(prin1-to-string (mapcar (lambda (buffer)
(format \"%s\\n\" buffer))
(buffer-list))))))" \
2>/dev/nullLet's break it down.
-
emacsEmacs itself!--batchRuns Emacs inbatchmode, which executes commands non-interactively and stops it from opening a window. This is usually used for running Emacs lisp as a script.-
--evalEvaluates the following piece of elisp in the batch Emacs(require 'server)Loads the built-inserverpackage. This is used to connect to the running Emacs daemon
-
--evalSince the previous elisp snippet was a complete s-expression I evaluate the next expression as a new argument. I could have also wrapped them both in aprogn, but this felt cleaner.-
mapc FUNCTION SEQUENCEApplyFUNCTIONto every object in the listSEQUENCE.princOutputs the printed form of an object tostandard-out. It's used here because it doesn't surround the string in quotes likeprintdoes.-
read STREAMReadSTREAM, in this case a string, and turn it into a lisp object-
server-eval-at \"server\" FORMEvaluatesFORMon the Emacs daemon and returns the result. The quotes are escaped because it's already inside a quote because it's a command line argument.-
prin1-to-string OBJECTReturn a string containing the printed representation ofOBJECT. I use this instead ofprincbecause that outputs the result to the minibuffer of the Emacs daemon instead of returning it.-
mapcar FUNCTION SEQUENCEApplies FUNCTION to each element of SEQUENCE and returns a list of the result.(lambda (buffer) (format \"%s\\n\" buffer)An anonymous function that takes a buffer and returns the string version of its name followed by a newline. The quotes and newline are escaped because it's already inside a quote because it's a command line argument.buffer-listReturns a list of all buffers in Emacs
-
-
-
-
2>/dev/nullSend the Emacs startup text, which is outputted tostderr, to/dev/null. We don't want to see it.
The result is a single line command that outputs the name of every
buffer in the Emacs daemon, one per line, to stdout.