Last edit
Summary: setting exitcode
Added:
> ==Error codes==
> One use of batch scripting is to run a predicate over a collection of files. For example, to use 'check-parens' and exit with an error code 1 if 'check-parens' throws an exception:
> {{{
> emacs file --batch --eval="(condition-case nil (check-parens) (error (kill-emacs 1)))"
> }}}
> Easily turned into a shell script to print out the names of files with detected imbalances:
> {{{
> for file in *.txt; do emacs "$file" --batch --eval="(condition-case nil (check-parens) (error (kill-emacs 1)))" &> /dev/null || echo $file; done
> }}}
[For the Emacs mode for editing DOS batch files, see DosScripts.]
According to the EmacsManual:
‘-batch’ causes Emacs to run noninteractively. In this mode, Emacs does not read commands from the terminal, it does not alter the terminal modes, and it does not expect to be outputting to an erasable screen. The idea is that you specify Lisp programs to run; when they are finished, Emacs should exit. […]‘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 EmacsManual does not give any examples so here are a few.
You can call simulate an EmacsLisp-based script by putting this in a batch script:
emacs -batch -l ~/.emacs.editor --eval="(require 'foo)" \ --eval="(require 'bar)" \ --eval="(some-function $*)"
Starting with the Emacs 22, you can write Emacs scripts just as if you were writing Bash or Perl scripts, when you include this at the top of your script file:
#!/usr/bin/emacs --script
One use of batch scripting is to run a predicate over a collection of files. For example, to use ‘check-parens’ and exit with an error code 1 if ‘check-parens’ throws an exception:
emacs file --batch --eval="(condition-case nil (check-parens) (error (kill-emacs 1)))"
Easily turned into a shell script to print out the names of files with detected imbalances:
for file in *.txt; do emacs "$file" --batch --eval="(condition-case nil (check-parens) (error (kill-emacs 1)))" &> /dev/null || echo $file; done
emacs -batch sample.c --eval '(indent-region (point-min) (point-max) nil)' -f save-buffer
The above opens the file sample.c and runs ‘indent-region’ from the beginning (‘point-min’) to the end (‘point-max’) of the file, then saves the file. Because Emacs is thoughtful, it automatically saves a copy of the original file to sample.c~.
Emacs is provided with an intelligent paragraph filling command, which can be helpful for use on numerous files. To have Emacs fix the long lines of one or more files from the command-line, use the following command:
emacs -batch long-file.txt --eval '(fill-region (point-min) (point-max))' -f save-buffer
Emacs will use the filling rules for the mode the file is opened in, and fill all lines in the file. This could have unexpected results in certain modes.
Here is a link to a script that wraps up the command so it can be conveniently used on the command line with command line arguments:
Emacs can, from the command-line, update or insert Texinfo menus and nodes in a Texinfo document using the ‘texinfo-every-node-update’ and ‘texinfo-all-menus-update’ commands. This is especially helpful when a Texinfo file is being generated or converted from another source document. Consider the following MakeFILE? rule which can convert some OTHER format into Texinfo (where OTHER is some other document format like XML or HTML):
%.texi: %.other $(OTHER2TEXI)
$(OTHER2TEXI) $< > $@
emacs -batch $@ \
-f texinfo-every-node-update -f texinfo-all-menus-update \
-f save-bufferThe example script shs-example demonstrates all the things you’d want to do with emacs scripts, and is meant to serve as a tutorial (I am teaching myself and improvements are very welcome) as well as demonstrate some useful functions from shs.el. Save these files somewhere in your bash path, change the path to that path in example-emacs-script and change the “#/usr/local/bin/emacs” address call to that of your actual Emacs path. Then, on bash prompt, type example-emacs-script.
If active Emacs developers are reading this, we’d like to point out that (princ) in batch-mode prints to stdout, as opposed to stderr, which is not what the EmacsLispReference says. On the other hand, that is the only way at this time (we think) that you can print to stdout through an emacs batch script, so we hope that this “bug” is not fixed, but retained as a feature.
This is not a bug. princ function and all the print functions) direct their output depending on the variable standard-output. This variable can be set to a buffer, a marker, any function of 1 argument or the symbol t. The last case is the default. In interactive mode the output goes to the echo area. In batch mode it is directed to the normal stdout. The message function prints to stderr in batch mode. Perhaps there is an error in the documentation you referenced above (I have not checked)
Example:
@"c:\Program Files\Emacs\emacs-21.3\bin\emacs.exe" -batch -no-site-file -q ^ -eval "(unless (y-or-n-p \"Do you want to continue? \") (kill-emacs 1)) @if %errorlevel% GTR 0 goto fin
We need a term more descriptive than “scripting” for this, since some people think that writing an emacs package is scripting. “batch mode” kind of implies no interactivity, which isn’t true. “command line or executable scripting with emacs lisp” is a mouthful. Maybe “scripting” is the best.
Scripting is within a hair of opening up a huge new market for emacs. People who use bash or Python or whatever could be using emacs:
The EASILY FIXABLE THINGS holding it back are:
Does anybody agree? Drop me a line just to let me know somebody read this.
(gambarimasu who is at gmail.com)
See also EmacsScripts.