Make it easier to use Emacs as a script interpreter

* doc/emacs/cmdargs.texi (Initial Options): Document -x.
* lisp/startup.el (command-line-1): Add new -scripteval.
(command-line--eval-script): New function.

* src/emacs.c (main): Transform -x to -scripteval.
(standard_args): Add -x (bug#20682).
This commit is contained in:
Lars Ingebrigtsen 2022-04-18 12:58:54 +02:00
parent 89a5aa4ca7
commit fac640ee86
4 changed files with 63 additions and 3 deletions

View file

@ -294,6 +294,22 @@ which will invoke Emacs with @samp{--script} and supply the name of
the script file as @var{file}. Emacs Lisp then treats the @samp{#!}
on this first line as a comment delimiter.
@item -x
@opindex -x
This option can only be used in executable script files, and should be
invoked like this:
@example
#!/usr/bin/emacs -x
@end example
This is like @samp{--script}, but suppresses loading the init files
(like @code{--quick}), and can't be used on a normal command line
(since it doesn't specify the script to load). In addition, when it
reaches the end of the script, it exits Emacs and uses the value of
the final form as the exit value from the script (if the final value
is numerical). Otherwise, it will always exit with a zero value.
@item --no-build-details
@opindex --no-build-details
@cindex build details

View file

@ -100,6 +100,17 @@ Saving Emacs Sessions" node in the Emacs manual for more details.
* Startup Changes in Emacs 29.1
+++
** Emacs can now be used more easily in an executable script.
If you start an executable script with
#!/usr/bin/emacs -x
Emac will start without reading any init files (like with --quick),
and then execute the rest of the script file as Emacs Lisp. When it
reaches the end of the script, Emacs will exit with an exit code from
the value of the final form.
+++
** Emacs now supports setting 'user-emacs-directory' via '--init-directory'.

View file

@ -2664,7 +2664,7 @@ nil default-directory" name)
;; This is used to handle -script. It's not clear
;; we need to document it (it is totally internal).
((member argi '("-scriptload"))
((member argi '("-scriptload" "-scripteval"))
(let* ((file (command-line-normalize-file-name
(or argval (pop command-line-args-left))))
;; Take file from default dir.
@ -2677,7 +2677,10 @@ nil default-directory" name)
;; actually exist on some systems.
(when (file-exists-p truename)
(setq file-ex truename))
(command-line--load-script file-ex)))
(if (equal argi "-scripteval")
;; This will kill Emacs.
(command-line--eval-script file-ex)
(command-line--load-script file-ex))))
((equal argi "-insert")
(setq inhibit-startup-screen t)
@ -2879,6 +2882,22 @@ nil default-directory" name)
(delete-line))
(eval-buffer buffer nil file nil t)))))
(defun command-line--eval-script (file)
(load-with-code-conversion
file file nil t
(lambda (buffer _)
(with-current-buffer buffer
(goto-char (point-min))
(when (looking-at "#!")
(forward-line))
(let (value form)
(while (ignore-error 'end-of-file
(setq form (read (current-buffer))))
(setq value (eval form t)))
(kill-emacs (if (numberp value)
value
0)))))))
(defun command-line-normalize-file-name (file)
"Collapse multiple slashes to one, to handle non-Emacs file names."
(save-match-data

View file

@ -296,7 +296,10 @@ Initialization options:\n\
-q --no-site-file --no-site-lisp --no-splash\n\
--no-x-resources\n\
--script FILE run FILE as an Emacs Lisp script\n\
--terminal, -t DEVICE use DEVICE for terminal I/O\n\
-x to be used in #!/usr/bin/emacs -x\n\
and has approximately the same meaning\n\
as -Q --script\n\
--terminal, -t DEVICE use DEVICE for terminal I/O\n \
--user, -u USER load ~USER/.emacs instead of your own\n\
\n\
",
@ -2063,6 +2066,16 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
no_site_lisp = 1;
}
if (argmatch (argv, argc, "-x", 0, 1, &junk, &skip_args))
{
noninteractive = 1;
no_site_lisp = 1;
/* This is picked up in startup.el. */
argv[skip_args - 1] = (char *) "-scripteval";
skip_args -= 1;
sort_args (argc, argv);
}
/* Don't actually discard this arg. */
skip_args = count_before;
}
@ -2504,6 +2517,7 @@ static const struct standard_args standard_args[] =
/* (Note that to imply -nsl, -Q is partially handled here.) */
{ "-Q", "--quick", 55, 0 },
{ "-quick", 0, 55, 0 },
{ "-x", 0, 55, 0 },
{ "-q", "--no-init-file", 50, 0 },
{ "-no-init-file", 0, 50, 0 },
{ "-init-directory", "--init-directory", 30, 1 },