How to make Emacs read buffer from stdin on start?
Solution 1
Correct, it is impossible to read a buffer from stdin.
The only mention of stdin in the Emacs info pages is this, which says:
In batch mode, Emacs does not display the text being edited, and the standard terminal interrupt characters such as
C-z
andC-c
continue to have their normal effect. The functionsprin1
,princ
andstdout
instead of the echo area, whilemessage
and error messages output tostderr
. Functions that would normally read from the minibuffer take their input fromstdin
instead.
And the read
function can read from stdin
, but only in batch mode.
So, you can't even work around this by writing custom elisp.
Solution 2
You could use process substitution:
$ emacs --insert <(echo 123)
Solution 3
You can redirect to a file, then open the file. e.g.
echo 123 > temp; emacs temp
jweede notes that if you want the temp file to automatically be removed, you can:
echo 123 > temp; emacs temp; rm temp
The Emacsy way to do this is to run the shell command in Emacs.
M-! echo 123 RET
That gives you a buffer named *Shell Command Output* with the results of the command.
Solution 4
It is possible, see https://stackoverflow.com/questions/2879746/idomatic-batch-processing-of-text-in-emacs
Here is echo in an emacs script (copied from the above link):
#!/usr/bin/emacs --script
(condition-case nil
(let (line)
(while (setq line (read-from-minibuffer ""))
(princ line)
(princ "\n")))
(error nil))
or to read it into a buffer and then print it out all in one go
#!/usr/bin/emacs --script
(with-temp-buffer
(progn
(condition-case nil
(let (line)
(while (setq line (read-from-minibuffer ""))
(insert line)
(insert "\n")))
(error nil))
(princ (buffer-string))
))
Solution 5
Another possibility not mentioned in any of the previous answers is to use /dev/stdin
if your chosen Unix variant has it.
Simply trying to open /dev/stdin
directly doesn't work, because Emacs does a few checks and then reports Symbolic link that points to nonexistent file
. (And if Emacs would have allowed you to load the file, then trying to save it again as /dev/stdin
would rarely do what the user expected.)
However combining /dev/stdin
with the --insert
argument does work:
echo 123 | emacs --insert /dev/stdin
It should be noted that this version only works when using X. If you need a solution which works in a terminal I suggest you look at another answer.
Related videos on Youtube
sastanin
Updated on September 17, 2022Comments
-
sastanin over 1 year
With Vim I can easily do
$ echo 123 | vim -
Is it possible to do with Emacs?
$ echo 123 | emacs23 ... Emacs starts with a Welcome message $ echo 123 | emacs23 - ... Emacs starts with an empty *scratch* buffer and “Unknown option” $ echo 123 | emacs23 --insert - ... “No such file or directory”, empty *scratch* buffer
Is it really impossible to read a buffer from a unix pipe?
Edit: As a solution, I wrote a shell wrapper named
emacspipe
:#!/bin/sh TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP
-
sastanin over 14 yearsYes, I know there is emacsy way, but I hoped it may be used unixy way. Creating a temporary file is not a very nice option (I have to remember to delete it later).
-
jweede over 14 yearstacking on ';rm temp' should delete the file once emacs closes
-
Richard Hoskins over 14 yearsIn general, there is a high impedance between Emacs and Unix. Or at least between Emacs and the traditional Unix work flow.
-
Richard Hoskins over 14 years@jweede If you want to add M-! part of my answer to yours, then I could delete my answer. There is a large overlap in our answers, but I think meta-bang is important to future readers.
-
sastanin over 14 yearstemp may already exist in the current directory, it's not safe; as a solution, I wrote a wrapper:
TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP
. Thanks everybody! -
dbmikus over 9 yearsThis is definitely the answer that gets closest to the Vim functionality. Pretty much just moving the piped part into a subprocess substitution.
-
Andrew Wood over 9 years@dbmikus I can't decide which I prefer between mine and Tomasz Obrębski's..
-
dbmikus over 9 yearsTomasz's results in me getting the following error for some reason:
emacs: standard input is not a tty
-
Andrew Wood over 9 yearsOh indeed! I assumed he'd tested before posting.
-
user787832 over 9 yearsI mean no disrespect to anyone, but this is abhorrent. This is a very basic editor feature and GNU EMACS has been around for decades. It should be built in.
-
Andrew Wood over 9 yearsHmm.. I just tried Tomasz Obrębski's again, and it works for me this time :/
-
dbmikus about 9 yearsMaybe it depends on the month.
-
pyrocrasty almost 9 years
echo 123 | exec emacs -nw --insert <(cat) </dev/tty
should work. -
RoyM over 8 yearsThat works; why the exec? This also works: emacs -nw --insert <(echo 123) </dev/tty
-
Charles Roberto Canato over 8 yearsGo figure: works beautifully on Emacs (w32) on Cygwin, where lots of other settings of mine do not
-
Alejandro about 8 yearsThis works well for me, but _emacsfun should be
emacsclient -c -t $@
, or at the very least drop the -n option. man pages withemacsclient -t --eval "(man \"$1\")" --eval "(delete-window)"
(and now you canhelm-swoop
your way to Man Glory!) -
Bao Haojun about 7 yearsThank you very much! Now I have a “wrap” function written with Emacs: cat file-with-long-lines | emacs -nw --batch -Q --insert <(cat) --eval '(progn (fill-paragraph)(message (buffer-string)))' 2>&1
-
rien333 over 6 yearsAn even more emacs way to do this is to C-u M-! (prefix argument + shell command), which inserts the output at the current point. (the shell to command to execute would be for example
cat the/file/you/want
) -
Admin about 6 yearswhat about
(t)csh
shell which is the default in thebsd
family who lack such a feature? -
Admin about 6 yearsi got
emacs: standard input is not a tty
message testing it on linux and bsd -
kasperd about 6 years@Chinggis6 Looks like my suggestion only works when using X11. If I first type
unset DISPLAY
, I get the same error message as you. -
kasperd about 6 years@Chinggis6 I updated my answer to point out that it needs X to work and pointed to an answer which works without X.
-
Alien Life Form almost 6 yearsToo bad it does no work with emacsclient
-
dylnmc over 5 yearsexcept when you're in a shell and want to do something like
curl foo.bar | vim -
.. I'm sorry. I meantcurl foo.bar | emacs
except you can't do that -
Admin over 5 yearsThis is a very cool trick! I used it to make an executable Bash script that's also an Emacs lisp file that is effectively a single-file Emacs app installer and runner. github.com/jgkamat/matrix-client-el/blob/master/misc/…
-
user2751003 about 5 yearsThis is the only answer that I could get to work with emacsclient. I made a shell script out of the basic idea so I can call it from i3 config. +1
-
Flux about 3 yearsWhy not do
(let (line) (while (setq line (ignore-errors (read-from-minibuffer ""))) (insert line) (insert "\n")))
instead of usingcondition-case
?