2

I heard that Vim has an ex mode which is line-oriented.
That means users can use the editor by echoing commands to it, e.g.,

bash$ echo "123" > 123.txt  # 123.txt: 123
bash$ echo "s/2/0
> w" | vim -e 123.txt       # replace "2" with "0", then save the edit
bash$ cat 123.txt           # 123.txt: 103
103

Is it possible for Emacs to do this?
If yes, how?

Or, more generally,
has Emacs implemented the line-oriented feature?
If not, why?

0

2 Answers 2

3

emacs -batch can do that:

echo '(progn (find-file "123.txt") (replace-string "2" "0") (save-buffer))' | emacs -batch --eval "(call-interactively #'eval-expression)"

This starts emacs in batch mode where it evaluates its command-line arguments and exits. In this case, the only command line argument is --eval which is asked to call eval-expression interactively. Normally eval-expression reads from the minibuffer, but in batch mode there is no minibuffer and eval-expression reads from stdin. The pipe has arranged for Emacs's stdin to be connected with the stdout of echo, so eval-expression ends up being called with the echo output as its argument. It proceeds to open the file, replace the string and save the buffer. Emacs then exits.

Equivalently but a bit closer in spirit to your example:

echo '(progn (replace-string "2" "0") (save-buffer))' | emacs -batch --file 123.txt --eval "(call-interactively #'eval-expression)"

Here Emacs gets two arguments, a --file argument that visits the file and an --eval argument as before.

2
  • 2
    Strictly speaking, emacs -batch -eval "(call-interactively #'eval-expression)" is still a little different from Vim's ex mode which is a read and execute loop. I also posted an answer based on yours :-)
    – shynur
    Commented Feb 26, 2023 at 7:49
  • 1
    You are right, although I suspect nobody will want to do it this way: vim's command "language" is simple enough to be able to type it in, but even in that case, a purpose-made filter can be much more convenient (e.g. sed or awk). OTOH, Emacs is heavily weighted towards interactive use, so the command language is elisp: very flexible and powerful for writing extensions and scripting it but a bit too verbose to use interactively on the command line, IMO.
    – NickD
    Commented Feb 26, 2023 at 21:07
3

According to @NickD’s answer,
to make Emacs line-oriented just like Vim’s ex mode, use:

$ emacs -batch \
>       -eval "(while t \
>                (write-char ?\\n) \
>                (call-interactively #'eval-expression))"

This will provide you with a read and execute loop.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.