Search code examples
emacselisp

Run elisp program without Emacs?


elisp is a good language, I find it can handle all kind of jobs, but can I use it like a shell script?

i.e. execute some *.el files from the console, without launching Emacs. Or launch Emacs, but don't enter interactive mode.


Solution

  • You can most definitely run elisp scripts in Emacs without starting the editor interface.

    Here are the notes I've made/copied from a few extremely useful Q&As on the subject here at S.O. (and the following two in particular).

    Much of this information, and more besides, is also covered in the following excellent overview, which is recommended reading:

    ;;;; Elisp executable scripts
    
    ;; --batch vs --script
    ;; M-: (info "(emacs) Initial Options") RET
    ;; M-: (info "(elisp) Batch Mode") RET
    
    ;; Processing command-line arguments (boiler-plate)
    ;; http://stackoverflow.com/questions/6238331/#6259330 (and others)
    ;;
    ;; For robustness, it's important to both pass '--' as an argument
    ;; (to prevent Emacs from trying to process option arguments intended
    ;; for the script), and also to exit explicitly with `kill-emacs' at
    ;; the end of the script (to prevent Emacs from carrying on with other
    ;; processing, and/or visiting non-option arguments as files).
    ;;
    ;; #!/bin/sh
    ;; ":"; exec emacs -Q --script "$0" -- "$@" # -*-emacs-lisp-*-
    ;; (pop argv) ; Remove the "--" argument
    ;; ;; (setq debug-on-error t) ; if a backtrace is wanted
    ;; (defun stdout (msg &optional args) (princ (format msg args)))
    ;; (defun stderr (msg &optional args) (princ (format msg args)
    ;;                                           #'external-debugging-output))
    ;; ;; [script body here]
    ;; Always exit explicitly. This returns the desired exit
    ;; status, and also avoids the need to (setq argv nil).
    ;; (kill-emacs 0)
    
    ;; Processing with STDIN and STDOUT via --script:
    ;; https://stackoverflow.com/questions/2879746/#2906967
    ;;
    ;; #!/bin/sh
    ;; ":"; exec emacs -Q --script "$0" -- "$@" # -*-emacs-lisp-*-
    ;; (pop argv) ; Remove the "--" argument
    ;; (setq debug-on-error t) ; if a backtrace is wanted
    ;; (defun stdout (msg &optional args) (princ (format msg args)))
    ;; (defun stderr (msg &optional args) (princ (format msg args)
    ;;                                           #'external-debugging-output))
    ;; (defun process (string)
    ;;   "Reverse STRING."
    ;;   (concat (nreverse (string-to-list string))))
    ;;
    ;; (condition-case nil
    ;;     (let (line)
    ;;       (while (setq line (read-from-minibuffer ""))
    ;;         (stdout "%s\n" (process line))))
    ;;   (error nil))
    ;;
    ;; ;; Always exit explicitly. This returns the desired exit
    ;; ;; status, and also avoids the need to (setq argv nil).
    ;; (kill-emacs 0)
    

    Emacs aside, the only other elisp interpreter/compiler I'm aware of is Guile. If you're keen on general coding in elisp, that should be worth a look (especially if performance is a concern).