So, this is something that has irritated me from time to time about
emacs. I have long thought that it was not possible to read data from stdin
from emacs when in batch mode (I had discovered that
would write foo to stdout, so that wasn’t an issue). I have tried to
search google for it in the past, but I never found what I was looking
I have again been dealing with this problem, and finally found the solution, which is documented at (info “(elisp) Batch Mode”).
The relvant selection is:
Any Lisp program output that would normally go to the echo area, either using `message', or using `prin1', etc., with `t' as the stream, goes instead to Emacs's standard error descriptor when in batch mode. Similarly, input that would normally come from the minibuffer is read from the standard input descriptor. Thus, Emacs behaves much like a noninteractive application program. (The echo area output that Emacs itself normally generates, such as command echoing, is suppressed entirely.)
So, we can use
read-from-minibuffer to get data from stdin, and
princ to write data.
A Real-World Example
My goal was to write a plugin for Jekyll that will convert org mode files into blog posts (which is working, but I still need to tweak things, so that will be saved for a later post).
Basically, Jekyll reads the files that represents your posts, removes yaml metadata from the head of the document, and hands the content of the file to the converter plugin. Thus, I have the text contents of an org file, and need to convert that to an html version. In an ideal world, I would be able to pipe this text into emacs and have it output the html I want.
The portion of elisp that implements this:
(defun compile-org-file () (interactive) (let ((org-document-content "") this-read) (while (setq this-read (ignore-errors (read-from-minibuffer ""))) (setq org-document-content (concat org-document-content "\n" this-read))) (with-temp-buffer (org-mode) (insert org-document-content) (org-html-export-as-html) (princ (buffer-string)))))
There are a number of things to point out, here.
read-from-minibuffer was tricky, and needed some special consideration:
- No prompt should be displayed to the user, since data is coming in unprompted. Thus, an empty string argument.
- This function reads in a single line at a time. As data is read in, it must be appended to what has already been read.
- When EOF is read, an error is thrown, which is useless to
us. Instead of worrying about the error, we can wrap the function
call in an
ignore-errorsmacro, which will return
nilwhen an EOF occurs.
Once the entire data is read in, we can convert it org mode.
- A temporary buffer is created, which is converted to
- The contents of the org document are inserted into the buffer.
org-html-export-as-htmlcreates a new buffer, makes it current, and inserts the exported html into that buffer.
princwrites the converted html to stdout.
Overall, I am pretty happy with the solution. This is one of the lesser known areas of Emacs, and I’m really glad that I finally know how to do it, because it is a problem I have had to deal with on several occasions.