emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master fac640ee86: Make it easier to use Emacs as a script interpreter


From: Lars Ingebrigtsen
Subject: master fac640ee86: Make it easier to use Emacs as a script interpreter
Date: Mon, 18 Apr 2022 06:59:09 -0400 (EDT)

branch: master
commit fac640ee8608748f0c4b867080d554c1b94121bd
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    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).
---
 doc/emacs/cmdargs.texi | 16 ++++++++++++++++
 etc/NEWS               | 11 +++++++++++
 lisp/startup.el        | 23 +++++++++++++++++++++--
 src/emacs.c            | 16 +++++++++++++++-
 4 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi
index de1d5e0b2c..946afb6fc1 100644
--- a/doc/emacs/cmdargs.texi
+++ b/doc/emacs/cmdargs.texi
@@ -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
diff --git a/etc/NEWS b/etc/NEWS
index ec56839c06..3e7788277d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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'.
 
diff --git a/lisp/startup.el b/lisp/startup.el
index ab7b81a707..353b5c78f1 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -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
diff --git a/src/emacs.c b/src/emacs.c
index 2fb62cb69a..3100852b2c 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -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 },



reply via email to

[Prev in Thread] Current Thread [Next in Thread]