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/null
Here 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/null
Let's break it down.
--batchRuns Emacs in
batchmode, 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-in
serverpackage. 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 a
progn, but this felt cleaner.
mapc FUNCTION SEQUENCEApply
FUNCTIONto every object in the list
princOutputs the printed form of an object to
standard-out. It's used here because it doesn't surround the string in quotes like
STREAM, in this case a string, and turn it into a lisp object
server-eval-at \"server\" FORMEvaluates
FORMon 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 of
OBJECT. I use this instead of
princbecause 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 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