doomemacs/bin/doom
2020-09-01 15:32:01 -04:00

132 lines
6.5 KiB
Bash
Executable File

#!/usr/bin/env sh
:; set -e # -*- mode: emacs-lisp; lexical-binding: t -*-
:; case "$EMACS" in *term*) EMACS=emacs ;; *) EMACS="${EMACS:-emacs}" ;; esac
:; $EMACS --version >/dev/null 2>&1 || { >&2 echo "Can't find emacs in your PATH"; exit 1; }
:; $EMACS --no-site-file --script "$0" -- "$@" || __DOOMCODE=$?
:; [ "${__DOOMCODE:-0}" -eq 128 ] && { "`$EMACS -Q --batch --eval '(princ temporary-file-directory)'`/doom.sh" "$0" "$@" && true; __DOOMCODE=$?; }
:; exit $__DOOMCODE
;; The garbage collector isn't important during CLI ops. A higher threshold
;; makes it 15-30% faster, but set it too high and we risk spiralling memory
;; usage in longer sessions.
(setq gc-cons-threshold 134217728) ; 128mb
;; Prioritize non-byte-compiled source files in non-interactive sessions to
;; prevent loading stale byte-code.
(setq load-prefer-newer t)
;; Ensure Doom runs out of this file's parent directory, where Doom is
;; presumably installed. EMACSDIR is set in the shell script preamble earlier in
;; this file.
(setq user-emacs-directory
(if (getenv "EMACSDIR")
(file-name-as-directory (expand-file-name (getenv "EMACSDIR")))
(expand-file-name
"../" (file-name-directory (file-truename load-file-name)))))
;; Handle some potential issues early
(when (version< emacs-version "26.1")
(error (concat "Detected Emacs %s (at %s).\n\n"
"Doom only supports Emacs 26.1 and newer. 27.1 is highly recommended. A guide\n"
"to install a newer version of Emacs can be found at:\n\n "
(cond ((eq system-type 'darwin)
"https://github.com/hlissner/doom-emacs/blob/develop/docs/getting_started.org#on-macos")
((memq system-type '(cygwin windows-nt ms-dos))
"https://github.com/hlissner/doom-emacs/blob/develop/docs/getting_started.org#on-windows")
("https://github.com/hlissner/doom-emacs/blob/develop/docs/getting_started.org#on-linux"))
"Aborting...")
emacs-version
(car command-line-args)))
(unless (file-exists-p (expand-file-name "core/core.el" user-emacs-directory))
(error (concat "Couldn't find Doom Emacs in %S.\n\n"
"This is likely because this script (or its parent directory) is a symlink.\n"
"If you must use a symlink, you'll need to specify an EMACSDIR so Doom knows\n"
"where to find itself. e.g.\n\n "
(if (string-match-p "/fish$" (getenv "SHELL"))
"env EMACSDIR=~/.emacs.d doom"
"EMACSDIR=~/.emacs.d doom sync")
"\n\n"
"Aborting...")
(abbreviate-file-name (file-truename user-emacs-directory))
(abbreviate-file-name load-file-name)))
(when (and (equal (user-real-uid) 0)
(not (file-in-directory-p user-emacs-directory "/root")))
(error (concat "This script is running as root. This likely wasn't intentional and\n"
"will cause file permissions errors later if this Doom install is\n"
"ever used on a non-root account.\n\n"
"Aborting...")))
;; Load the heart of the beast and its CLI processing library
(load (expand-file-name "core/core.el" user-emacs-directory) nil t)
(require 'core-cli)
;; Use our own home-grown debugger to display and log errors + backtraces.
;; Control over its formatting is important, because Emacs produces
;; difficult-to-read debug information otherwise. By making its errors more
;; presentable (and storing them somewhere users can access later) we go a long
;; way toward making it easier for users to write better bug reports.
(setq debugger #'doom-cli--debugger
debug-on-error t
debug-ignored-errors nil)
;; HACK Load `cl' and site files manually to prevent polluting logs and stdout
;; with deprecation and/or file load messages.
(quiet! (if EMACS27+ (require 'cl))
(load "site-start" t t))
(kill-emacs
(pcase
(catch 'exit
;; Process the arguments passed to this script. `doom-cli-execute' should
;; return a boolean, integer (error code) or throw an 'exit event, which
;; we handle specially.
(apply #'doom-cli-execute :doom (cdr (member "--" argv))))
;; Any non-zero integer is treated as an error code.
((and (pred integerp) code) code)
;; If, instead, we were given a list or string, copy these as shell script
;; commands to a temp script file which this script will execute after this
;; session finishes. Also accepts special keywords, like `:restart', to rerun
;; the current command.
((and (or (pred consp)
(pred stringp)
(pred keywordp))
command)
(let ((script (expand-file-name "doom.sh" temporary-file-directory))
(coding-system-for-write 'utf-8-unix)
(coding-system-for-read 'utf-8-unix))
(with-temp-file script
(insert "#!/usr/bin/env sh\n"
"_postscript() {\n"
" rm -f " (shell-quote-argument script) "\n "
(cond ((eq command :restart)
"$@")
((stringp command)
command)
((string-join
(if (listp (car-safe command))
(cl-loop for line in (doom-enlist command)
collect (mapconcat #'shell-quote-argument (remq nil line) " "))
(list (mapconcat #'shell-quote-argument (remq nil command) " ")))
"\n ")))
"\n}\n"
(save-match-data
(cl-loop for env
in (cl-set-difference process-environment
doom--initial-process-environment
:test #'equal)
if (string-match "^\\([a-zA-Z0-9_]+\\)=\\(.+\\)$" env)
concat (format "%s=%s \\\n"
(match-string 1 env)
(shell-quote-argument (match-string 2 env)))))
(format "PATH=\"%s%s$PATH\" \\\n" (concat doom-emacs-dir "bin/") path-separator)
"_postscript $@\n"))
(set-file-modes script #o700))
;; Error code 128 is special: it means run the post-script after this
;; session ends.
128)
;; Anything else (e.g. booleans) is treated as a successful run. Yes, a `nil'
;; indicates a successful run too!
(_ 0)))