* 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).
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
\f
* 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'.
;; 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.
;; 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)
(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
-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\
",
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;
}
/* (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 },