Merge branch 'develop' into solidity-mode

This commit is contained in:
Henrik Lissner 2018-05-25 18:37:38 +02:00 committed by GitHub
commit a814c833a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
146 changed files with 3283 additions and 2560 deletions

104
Makefile
View file

@ -1,12 +1,8 @@
# Ensure emacs always runs from this makefile's PWD
EMACS = emacs -q --eval "(setq user-emacs-directory default-directory load-prefer-newer t)"
DOOM = $(EMACS) --batch -l init.el
DOOMI = $(subst --batch,,$(DOOM))
DOOM = bin/doom
MODULES = $(patsubst modules/%/, %, $(sort $(dir $(wildcard modules/*/ modules/*/*/))))
all:
@$(DOOM) -f doom//reload-packages
@$(DOOM) refresh
## Shortcuts
a: autoloads
@ -16,88 +12,66 @@ U: upgrade
r: autoremove
c: compile
cc: compile-core
ce: compile-elpa
cp: compile-plugins
re: recompile
d: doctor
quickstart: | ~/.doom.d/init.el all recompile
~/.doom.d/init.el:
@echo "Creating ~/.doom.d directory"
@mkdir ~/.doom.d && cp init.example.el ~/.doom.d/init.el
@touch ~/.doom.d/config.el
quickstart:
@$(DOOM) quickstart
## Package management
install: | .local/autoloads.el
@$(DOOM) -f doom//packages-install
update: | .local/autoloads.el
@$(DOOM) -f doom//packages-update
autoremove: | .local/autoloads.el
@$(DOOM) -f doom//packages-autoremove
install:
@$(DOOM) install
update:
@$(DOOM) update
autoremove:
@$(DOOM) autoremove
autoloads:
@$(DOOM) -f doom//reload-autoloads
upgrade: | _upgrade recompile all
_upgrade:
@git pull origin $(shell git rev-parse --abbrev-ref HEAD)
@$(DOOM) autoloads
upgrade:
@$(DOOM) upgrade
## Byte compilation
# compile
# compile-core
compile:
@$(DOOM) compile
compile-core:
@$(DOOM) compile :core
compile-private:
@$(DOOM) compile :private
compile-plugins:
@$(DOOM) compile :plugins
recompile:
@$(DOOM) recompile
clean:
@$(DOOM) clean
# compile-module
# compile-module/submodule
compile: | clean
@$(DOOM) -f doom//byte-compile
compile-core: | clean
@$(DOOM) -f doom//byte-compile-core
compile-elpa:
@$(DOOM) -f doom//byte-recompile-plugins
$(patsubst %, compile-%, $(MODULES)): | .local/autoloads.el
@$(DOOM) -f doom//byte-compile -- $(patsubst compile-%, %, $@)
recompile:
@$(DOOM) -f doom//byte-compile -- -r
clean:
@$(DOOM) -f doom//clean-byte-compiled-files
@$(DOOM) $@ $(subst compile-, , $@)
## Unit tests
# test
# test-core
test:
@$(DOOM) test
test-core:
@$(DOOM) test :core
# test-module
# test-module/submodule
test: | .local/autoloads.el
@$(DOOM) -f doom//run-tests
test-core $(patsubst %, test-%, $(MODULES)): | .local/autoloads.el
@$(DOOM) -f doom//run-tests -- $(subst test-, , $@)
# run tests interactively
testi: | .local/autoloads.el
@$(DOOMI) -f doom//run-tests
$(patsubst %, test-%, $(MODULES)):
@$(DOOM) test $(subst test-, , $@)
## Utility tasks
# Runs Emacs from a different folder than ~/.emacs.d; only use this for testing!
run:
@$(DOOMI) $(ARGS) --eval "(run-hooks 'after-init-hook 'emacs-startup-hook 'window-setup-hook)"
@$(DOOM) run $(ARGS)
# Prints debug info about your current setup
info:
@$(DOOM) info
# Diagnoses potential OS/environment issues
doctor:
@$(EMACS) --script bin/doom-doctor
# Prints debug info about your current setup
info:
@$(EMACS) --batch -l core/core.el -l core/autoload/util.el -f doom/info
## Internal tasks
.local/autoloads.el:
@$(DOOM) -f doom-initialize-autoloads
@$(DOOM) doctor
.PHONY: all compile test testi clean

73
bin/doom Executable file
View file

@ -0,0 +1,73 @@
#!/usr/bin/env bash
":"; command -v emacs >/dev/null || { >&2 echo "Emacs isn't installed"; exit 1; } # -*-emacs-lisp-*-
":"; VERSION=$(emacs --version | head -n1)
":"; [[ $VERSION == *\ 2[0-2].[0-1].[0-9] ]] && { echo "You're running $VERSION"; echo "That version is too old to run Doom. Check your PATH"; echo; exit 2; }
":"; DOOMDIR=$(dirname "${BASH_SOURCE:-${(%):-%x}}")/..
":"; [[ $1 == doc || $1 == doctor ]] && { cd "$DOOMDIR"; exec emacs --script bin/doom-doctor; exit 0; }
":"; [[ $1 == run ]] && { cd "$DOOMDIR"; shift; exec emacs -Q -l bin/doom "$@"; exit 0; }
":"; exec emacs --quick --script "$0" -- $@
":"; exit 0
(defun usage ()
(with-temp-buffer
(insert (format! "%s %s [COMMAND] [ARGS...]\n"
(bold "Usage:")
(file-name-nondirectory load-file-name))
"\n"
"A command line interfacing for managing Doom Emacs; including\n"
"package management, diagnostics, unit tests, and byte-compilation.\n"
"\n"
"This tool also makes it trivial to launch Emacs out of a different\n"
"folder or with a different private module.\n"
"\n"
(format! (bold "Example:\n"))
" doom install\n"
" doom help update\n"
" doom compile :core lang/php lang/python\n"
" doom run\n"
" doom run -nw file.txt file2.el\n"
" doom run -p ~/.other.doom.d -e ~/.other.emacs.d -nw file.txt\n"
"\n"
(format! (bold "Options:\n"))
" -d --debug\t\tTurns on doom-debug-mode (and debug-on-error)\n"
" -e --emacsd DIR\tUse the emacs config at DIR (e.g. ~/.emacs.d)\n"
" -p --private DIR\tUse the private module at DIR (e.g. ~/.doom.d)\n"
" -y --yes\t\tAuto-accept all confirmation prompts\n\n")
(princ (buffer-string)))
(doom--dispatch-help))
;;
(let ((args (cdr (cdr (cdr command-line-args))))
(emacs-dir (expand-file-name "../" (file-name-directory load-file-name))))
;; Parse options
(while (ignore-errors (string-prefix-p "-" (car args)))
(pcase (pop args)
((or "-d" "--debug")
(setq doom-debug-mode t))
((or "-p" "--private")
(setq doom-private-dir (expand-file-name (pop args)))
(or (file-directory-p doom-private-dir)
(error "%s does not exist" doom-private-dir)))
((or "-e" "--emacsd")
(setq emacs-dir (expand-file-name (pop args)))
(or (file-directory-p emacs-dir)
(error "%s does not exist" emacs-dir)))
((or "-y" "--yes")
(setq doom-auto-accept t))))
;; Bootstrap Doom
(load (expand-file-name "init" emacs-dir)
nil 'nomessage)
(cond ((not noninteractive)
(doom|run-all-startup-hooks))
((and (not (cdr args))
(member (car args) '("help" "h")))
(usage))
((not args)
(error "Expecting a command"))
((let ((default-directory user-emacs-directory))
(setq argv nil
noninteractive 'doom)
(doom-dispatch args)))))

View file

@ -1,6 +1,8 @@
#!/usr/bin/env bash
":"; command -v emacs >/dev/null || { >&2 echo "Emacs isn't installed"; exit 1; } # -*-emacs-lisp-*-
":"; [[ $(emacs --version | head -n1) == *\ 2[0-2].[0-1].[0-9] ]] && { echo "You're running $(emacs --version | head -n1)"; echo "That version is too old to run the doctor. Check your PATH"; echo; exit 2; } || exec emacs --quick --script "$0"
":"; VERSION=$(emacs --version | head -n1)
":"; [[ $VERSION == *\ 2[0-2].[0-1].[0-9] ]] && { echo "You're running $VERSION"; echo "That version is too old to run the doctor. Check your PATH"; echo; exit 2; }
":"; exec emacs --quick --script "$0"; exit 0
;; Uses a couple simple heuristics to locate issues with your environment that
;; could interfere with running or setting up DOOM Emacs.
@ -18,6 +20,7 @@
;;
(defvar doom-init-p nil)
(defvar doom-warnings 0)
(defvar doom-errors 0)
(defmacro when! (cond &rest body)
(declare (indent defun))
@ -62,7 +65,7 @@
(format (concat prefix ,msg)
,@args))))
(defmacro error! (&rest args) `(progn (msg! (color 31 ,@args)) (setq doom-errors (+ doom-errors 1))))
(defmacro warn! (&rest args) `(progn (msg! (color 33 ,@args)) (setq doom-errors (+ doom-errors 1))))
(defmacro warn! (&rest args) `(progn (msg! (color 33 ,@args)) (setq doom-warnings (+ doom-warnings 1))))
(defmacro success! (&rest args) `(msg! (color 32 ,@args)))
(defmacro section! (&rest args)
`(msg! (color 1 (color 34 ,@args))))
@ -112,11 +115,8 @@
(message "Compiled with:\n%s" (indented 2 system-configuration-features)))
(message "uname -a:\n%s\n" (indented 2 (sh "uname -a")))
(msg! "----\n")
;; --- is emacs set up properly? ------------------------------
(section! "test-emacs")
(when (version< emacs-version "25.1")
(error! "Important: Emacs %s detected [%s]" emacs-version (executable-find "emacs"))
(explain!
@ -125,7 +125,6 @@
(concat "\nMacOS users should use homebrew (https://brew.sh) to install Emacs\n"
" brew install emacs --with-modules --with-imagemagick --with-cocoa"))))
(section! "test-private-config")
(let ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME")
"~/.config")
"/doom/"))
@ -140,14 +139,14 @@
;; --- is the environment set up properly? --------------------
;; windows? windows
(section! "test-windows")
;; on windows?
(section! "Checking your OS...")
(when (memq system-type '(windows-nt ms-dos cygwin))
(warn! "Warning: Windows detected")
(explain! "DOOM was designed for MacOS and Linux. Expect a bumpy ride!"))
;; are all default fonts present
(section! "test-fonts")
;; are all default fonts present?
(section! "Checking your fonts...")
(if (not (fboundp 'find-font))
(progn
(warn! "Warning: unable to detect font")
@ -170,7 +169,7 @@
"case, ignore this warning."))))))
;; gnutls-cli & openssl
(section! "test-gnutls")
(section! "Checking gnutls/openssl...")
(cond ((executable-find "gnutls-cli"))
((executable-find "openssl")
(let* ((output (sh "openssl ciphers -v"))
@ -205,7 +204,8 @@
"network, provider, government, neckbearded mother-in-laws, geeky roommates, "
"or just about anyone who knows more about computers than you do!")))
(section! "test-tls")
;; are certificates validated properly?
(section! "Testing your root certificates...")
(cond ((not (string-match-p "\\_<GNUTLS\\_>" system-configuration-features))
(warn! "Warning: You didn't install Emacs with gnutls support")
(explain!
@ -227,8 +227,7 @@
(gnutls-verify-error t))
(dolist (url '("https://elpa.gnu.org" "https://melpa.org"))
(when! (condition-case-unless-debug e
(if (let ((inhibit-message t)) (url-retrieve-synchronously url))
(ignore (success! "Validated %s" url))
(unless (let ((inhibit-message t)) (url-retrieve-synchronously url))
'empty)
('timed-out 'timeout)
('error e))
@ -245,7 +244,7 @@
t
'empty)
('timed-out 'timeout)
('error (ignore (success! "Successfully rejected %s" url))))
('error))
(pcase it
(`empty (error! "Couldn't reach %s" url))
(`timeout (error! "Timed out trying to contact %s" ex))
@ -254,8 +253,8 @@
((error! "Nope!")))
;; bsd vs gnu tar
(section! "test-tar")
;; which variant of tar is on your system? bsd or gnu tar?
(section! "Checking for GNU/BSD tar...")
(let ((tar-bin (or (executable-find "gtar")
(executable-find "tar"))))
(if tar-bin
@ -276,14 +275,11 @@
;; --- are your modules set up properly? ----------------------
(message "\n----")
(let (doom-core-packages doom-debug-mode)
(condition-case ex
(let ((inhibit-message t))
(load "~/.emacs.d/core/core.el" nil t)
(let (noninteractive)
(doom-initialize t)
(doom|finalize))
(load (concat user-emacs-directory "init.el") nil t)
(doom-initialize-modules)
(success! "Attempt to load DOOM: success! Loaded v%s" doom-version))
('error
(warn! "Attempt to load DOOM: failed\n %s\n"
@ -291,14 +287,14 @@
(setq doom-modules nil))))
(when (bound-and-true-p doom-modules)
(section! "test-modules")
(section! "Checking your enabled modules...")
(let ((indent 4))
(advice-add #'require :around #'doom*shut-up)
(maphash
(lambda (key plist)
(condition-case ex
(let ((doctor-file (doom-module-expand-file (car key) (cdr key) "doctor.el"))
(packages-file (doom-module-expand-file (car key) (cdr key) "packages.el"))
(let ((doctor-file (doom-module-path (car key) (cdr key) "doctor.el"))
(packages-file (doom-module-path (car key) (cdr key) "packages.el"))
doom-packages)
(when (or (file-exists-p doctor-file)
(file-exists-p packages-file))
@ -306,7 +302,8 @@
(doom--stage 'packages))
(when (load packages-file t t)
(dolist (package (cl-remove-if #'package-installed-p doom-packages :key #'car))
(error! "%s is not installed" (car package))))
(unless (package-built-in-p (car package))
(error! "%s is not installed" (car package)))))
(let ((doom--stage 'doctor))
(load doctor-file t t)))))
('error
@ -314,7 +311,13 @@
doom-modules)))
;;
(message "\n----")
(if (> doom-errors 0)
(warn! "There were %s issues!" doom-errors)
(message "\n")
(dolist (msg (list (list doom-errors "error" 31)
(list doom-warnings "warning" 33)))
(when (> (car msg) 0)
(message (color (nth 2 msg) (if (= (car msg) 1) "There is %d %s!" "There are %d %ss!")
(car msg) (nth 1 msg)))))
(when (and (zerop doom-errors)
(zerop doom-warnings))
(success! "Everything seems fine, happy Emacs'ing!"))

14
bin/doom.cmd Normal file
View file

@ -0,0 +1,14 @@
:: Forward the ./doom script to Emacs
@ECHO OFF
PUSHD "%~dp0" >NUL
IF %1=="run" (
SHIFT
emacs -Q $* -l init.el -f "doom|run-all-startup-hooks"
) ELSE (
emacs --quick --script ./doom -- $*
)
POPD >NUL
ECHO ON

View file

@ -12,8 +12,6 @@
;; Like persistent-soft, caches assume a 2-tier structure, where all caches are
;; namespaced by location.
(require 'persistent-soft)
(defvar doom-cache-alists ()
"An alist of alists, containing lists of variables for the doom cache library
to persist across Emacs sessions.")

303
core/autoload/debug.el Normal file
View file

@ -0,0 +1,303 @@
;;; core/autoload/debug.el -*- lexical-binding: t; -*-
(defun doom-template-insert (template)
"TODO"
(let ((file (expand-file-name (format "templates/%s" template) doom-core-dir)))
(when (file-exists-p file)
(insert-file-contents file))))
;;;###autoload
(defun doom-info ()
"Returns diagnostic information about the current Emacs session in markdown,
ready to be pasted in a bug report on github."
(doom-initialize)
(require 'vc-git)
(let ((default-directory doom-emacs-dir)
(doom-modules (doom-module-table)))
(format
(concat "- OS: %s (%s)\n"
"- Emacs: %s (%s)\n"
"- Doom: %s (%s %s)\n"
"- Graphic display: %s (daemon: %s)\n"
"- System features: %s\n"
"- Details:\n"
" ```elisp\n"
" uname -a: %s\n"
" modules: %s\n"
" packages: %s\n"
" elc dirs: %s\n"
" exec-path: %s\n"
" ```")
system-type system-configuration
emacs-version (format-time-string "%b %d, %Y" emacs-build-time)
doom-version
(if-let* ((branch (vc-git--symbolic-ref "core/core.el")))
branch
"n/a")
(if-let* ((rev (vc-git-working-revision "core/core.el")))
rev
"n/a")
(display-graphic-p) (daemonp)
(bound-and-true-p system-configuration-features)
;; details
(with-temp-buffer
(unless (zerop (call-process "uname" nil t nil "-a"))
(insert (format "%s" system-type)))
(string-trim (buffer-string)))
(or (cl-loop with cat = nil
for key being the hash-keys of doom-modules
if (or (not cat) (not (eq cat (car key))))
do (setq cat (car key)) and collect cat
else collect
(let ((flags (doom-module-get cat (cdr key) :flags)))
(if flags
`(,(cdr key) ,@flags)
(cdr key))))
"n/a")
(or (let (packages)
(ignore-errors
(require 'async)
;; collect these in another session to protect this
;; session's state
(async-get
(async-start
`(lambda ()
(let ((noninteractive t)
(load-path ',load-path)
(package-alist ',package-alist))
(load ,(expand-file-name "init.el" doom-emacs-dir))
(doom-get-packages)))
(lambda (p) (setq packages p))))
(cl-loop for pkg in (cl-sort packages #'string-lessp
:key (lambda (x) (symbol-name (car x))))
collect (if (cdr pkg)
(format "%s" pkg)
(symbol-name (car pkg))))))
"n/a")
(or (ignore-errors
(cl-delete-duplicates
(cl-loop for file in (append (reverse (directory-files-recursively doom-core-dir "\\.elc$"))
(cl-loop for dir in doom-modules-dirs
nconc (directory-files-recursively dir "\\.elc$")))
collect (file-relative-name (file-name-directory file) doom-emacs-dir))
:test #'equal))
"n/a")
;; abbreviate $HOME to hide username
(mapcar #'abbreviate-file-name exec-path))))
;;
;; Commands
;;
;;;###autoload
(defun doom/info ()
"Collects some debug information about your Emacs session, formats it into
markdown and copies it to your clipboard, ready to be pasted into bug reports!"
(declare (interactive-only t))
(interactive)
(message "Generating Doom info...")
(if noninteractive
(print! (doom-info))
(kill-new (doom-info))
(message "Done! Copied to clipboard.")))
;;;###autoload
(defun doom/am-i-secure ()
"Test to see if your root certificates are securely configured in emacs."
(declare (interactive-only t))
(interactive)
(unless (string-match-p "\\_<GNUTLS\\_>" system-configuration-features)
(warn "gnutls support isn't built into Emacs, there may be problems"))
(if-let* ((bad-hosts
(cl-loop for bad
in '("https://wrong.host.badssl.com/"
"https://self-signed.badssl.com/")
if (condition-case _e
(url-retrieve-synchronously bad)
(error nil))
collect bad)))
(error "tls seems to be misconfigured (it got %s)."
bad-hosts)
(url-retrieve "https://badssl.com"
(lambda (status)
(if (or (not status) (plist-member status :error))
(warn "Something went wrong.\n\n%s" (pp-to-string status))
(message "Your trust roots are set up properly.\n\n%s" (pp-to-string status))
t)))))
;;;###autoload
(defun doom/version ()
"Display the current version of Doom & Emacs, including the current Doom
branch and commit."
(interactive)
(require 'vc-git)
(print! "Doom v%s (Emacs v%s)\nBranch: %s\nCommit: %s."
doom-version
emacs-version
(or (vc-git--symbolic-ref doom-core-dir)
"n/a")
(or (vc-git-working-revision doom-core-dir)
"n/a")))
;;
;; Vanilla sandbox
;;
(defun doom--run-vanilla-sandbox ()
"TODO"
(interactive)
(when (equal (buffer-name) "*doom:vanilla-sandbox*")
(let ((file (make-temp-file "doom-eval-")))
(write-file file)
(require 'pp)
(require 'restart-emacs)
(restart-emacs--launch-other-emacs
(list "-Q"
"--eval"
(prin1-to-string
`(setq user-emacs-directory ,doom-emacs-dir
package--init-file-ensured t
package-user-dir ,package-user-dir
package-archives ',package-archives
debug-on-error t))
"-f" "package-initialize"
"-l" file
"--eval" (prin1-to-string `(delete-file ,file)))))))
;;;###autoload
(defun doom/open-vanilla-sandbox ()
"Open an Emacs Lisp buffer destinated to run in a blank Emacs session.
This vanilla sandbox is started with emacs -Q, and provides a testbed for
debugging code without Doom standing in the way, and without sacrificing
access to the installed packages."
(interactive)
(let ((buf (get-buffer-create "*doom:vanilla-sandbox*")))
(with-current-buffer buf
(emacs-lisp-mode)
(local-set-key (kbd "C-c C-c") #'doom--run-vanilla-sandbox)
(local-set-key (kbd "C-c C-k") #'kill-this-buffer)
(setq header-line-format "C-c C-c to run the session / C-c C-k to abort it")
(setq-local default-directory doom-emacs-dir)
(doom-template-insert "VANILLA_SANDBOX")
(goto-char (point-max)))
(pop-to-buffer buf)))
;;
;; Reporting bugs
;;
(defun doom--open-bug-report ()
"TODO"
(interactive)
(let ((url "https://github.com/hlissner/doom-emacs/issues/new?body="))
;; TODO Refactor me
(save-restriction
(widen)
(goto-char (point-min))
(re-search-forward "^-------------------------------------------------------------------\n" nil t)
(skip-chars-forward " \n\t")
(condition-case e
(progn
(save-excursion
(when (and (re-search-backward "\\+ [ ] " nil t)
(not (y-or-n-p "You haven't checked all the boxes. Continue anyway?")))
(error "Aborted submit")))
(narrow-to-region (point) (point-max))
(let ((text (buffer-string)))
;; `url-encode-url' doesn't encode ampersands
(setq text (replace-regexp-in-string "&" "%26" text))
(setq url (url-encode-url (concat url text)))
;; HACK: encode some characters according to HTML URL Encoding Reference
;; http://www.w3schools.com/tags/ref_urlencode.asp
(setq url (replace-regexp-in-string "#" "%23" url))
(setq url (replace-regexp-in-string ";" "%3B" url))
(browse-url url)))
(error (signal (car e) (car e)))))))
;;;###autoload
(defun doom/open-bug-report ()
"Open a markdown buffer destinated to populate the New Issue page on Doom
Emacs' issue tracker.
If called when a backtrace buffer is present, it and the output of `doom-info'
will be automatically appended to the result."
(interactive)
;; TODO Refactor me
(let ((backtrace
(when (get-buffer "*Backtrace*")
(with-current-buffer "*Backtrace*"
(string-trim
(buffer-substring-no-properties
(point-min)
(min (point-max) 1000))))))
(buf (get-buffer-create "*doom:vanilla-sandbox*")))
(with-current-buffer buf
(erase-buffer)
(condition-case _ (gfm-mode)
(error (text-mode)))
(doom-template-insert "SUBMIT_BUG_REPORT")
(goto-char (point-max))
(let ((pos (point)))
(save-excursion
(insert
"\n" (doom-info) "\n"
(if (and backtrace (not (string-empty-p backtrace)))
(format "\n<details>\n<summary>Backtrace</summary>\n\n```\n%s\n```\n</details>\n"
backtrace)
"")))
(local-set-key (kbd "C-c C-c") #'doom--open-bug-report)
(local-set-key (kbd "C-c C-k") #'kill-this-buffer)
(setq header-line-format "C-c C-c to submit / C-c C-k to close")
;;
(narrow-to-region (point-min) pos)
(goto-char (point-min)))
(pop-to-buffer buf))))
;;
;; Profiling
;;
(defvar doom--profiler nil)
;;;###autoload
(defun doom/toggle-profiler ()
"Toggle the Emacs profiler. Run it again to see the profiling report."
(interactive)
(if (not doom--profiler)
(profiler-start 'cpu+mem)
(profiler-report)
(profiler-stop))
(setq doom--profiler (not doom--profiler)))
;;;###autoload
(defun doom/profile-emacs ()
"Profile the startup time of Emacs in the background with ESUP.
If INIT-FILE is non-nil, profile that instead of USER-INIT-FILE."
(interactive)
(require 'esup)
(let ((init-file esup-user-init-file))
(message "Starting esup...")
(esup-reset)
(setq esup-server-process (esup-server-create (esup-select-port)))
(setq esup-server-port (process-contact esup-server-process :service))
(message "esup process started on port %s" esup-server-port)
(let ((process-args `("*esup-child*"
"*esup-child*"
,esup-emacs-path
"-q"
"-L" ,esup-load-path
"-l" "esup-child"
,(format "--eval=(esup-child-run \"%s\" \"%s\" %d)"
init-file
esup-server-port
esup-depth)
"--eval=(run-hooks 'after-init-hook 'emacs-startup-hook 'window-setup-hook)")))
(when esup-run-as-batch-p
(setq process-args (append process-args '("--batch"))))
(setq esup-child-process (apply #'start-process process-args)))
(set-process-sentinel esup-child-process 'esup-child-process-sentinel)))

View file

@ -215,17 +215,21 @@ possible, or just one char if that's not possible."
(t (delete-char (- n) killflag))))
;;;###autoload
(defun doom/retab (&optional beg end)
(defun doom/retab (arg &optional beg end)
"Converts tabs-to-spaces or spaces-to-tabs within BEG and END (defaults to
buffer start and end, to make indentation consistent. Which it does depends on
the value of `indent-tab-mode'."
(interactive "r")
the value of `indent-tab-mode'.
If ARG (universal argument) is non-nil, retab the current buffer using the
opposite indentation style."
(interactive "Pr")
(unless (and beg end)
(setq beg (point-min)
end (point-max)))
(let ((indent-tabs-mode (if arg (not indent-tabs-mode) indent-tabs-mode)))
(if indent-tabs-mode
(tabify beg end)
(untabify beg end)))
(untabify beg end))))
(defvar-local doom--buffer-narrowed-origin nil)
;;;###autoload

View file

@ -56,9 +56,10 @@
(not force-p)
(not (y-or-n-p (format "File already exists at %s, overwrite?" short-new-name))))
(throw 'status 'aborted))
(t
((file-exists-p old-path)
(copy-file old-path new-path t)
short-new-name))))
short-new-name)
(short-new-name))))
;;;###autoload
(defun doom/delete-this-file (&optional path force-p)
@ -74,8 +75,7 @@ kills the buffer. If FORCE-P, force the deletion (don't ask for confirmation)."
((not (or force-p (y-or-n-p (format "Really delete %s?" fbase))))
(message "Aborted")
nil)
(t
(unwind-protect
((unwind-protect
(progn (delete-file path) t)
(let ((short-path (file-relative-name path (doom-project-root))))
(if (file-exists-p path)
@ -107,7 +107,8 @@ file if it exists, without confirmation."
(let ((old-path (buffer-file-name))
(new-path (expand-file-name new-path)))
(when-let* ((dest (doom--copy-file old-path new-path force-p)))
(delete-file old-path)
(when (file-exists-p old-path)
(delete-file old-path))
(kill-this-buffer)
(find-file new-path)
(doom--forget-file old-path new-path)

View file

@ -1,22 +1,5 @@
;;; core/autoload/help.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom/describe-setting (setting)
"Open the documentation of SETTING (a keyword defined with `def-setting!').
Defaults to the "
(interactive
(let ((sym (symbol-at-point)))
(list (completing-read "Describe setting: "
(sort (mapcar #'car doom-settings) #'string-lessp)
nil t (if (keywordp sym) (symbol-name sym))))))
(let ((fn (cdr (assq (intern setting) doom-settings))))
(unless fn
(error "'%s' is not a valid DOOM setting" setting))
(describe-function fn)))
;;
(defvar doom--module-mode-alist
'((c-mode :lang cc)
(c++-mode :lang cc)
@ -58,6 +41,42 @@ Defaults to the "
(stylus-mode :lang web))
"TODO")
(defvar doom-docs-dir (concat doom-emacs-dir "docs/")
"TODO")
;;
;; Helpers
;;
;;;###autoload
(defun doom-active-minor-modes ()
"Return a list of active minor-mode symbols."
(cl-loop for mode in minor-mode-list
if (and (boundp mode) (symbol-value mode))
collect mode))
;;
;; Commands
;;
;;;###autoload
(defun doom/describe-setting (setting)
"Open the documentation of SETTING (a keyword defined with `def-setting!').
Defaults to the "
(interactive
(let ((sym (symbol-at-point)))
(list (completing-read "Describe setting: "
(sort (mapcar #'car doom-settings) #'string-lessp)
nil t (if (keywordp sym) (symbol-name sym))))))
(let ((fn (cdr (assq (intern setting) doom-settings))))
(unless fn
(error "'%s' is not a valid DOOM setting" setting))
(describe-function fn)))
;;;###autoload
(defun doom/describe-module (module)
"Open the documentation of MODULE (a string that represents the category and
@ -75,6 +94,7 @@ in, or d) the module associated with the current major mode (see
"init.el")
(thing-at-point 'sexp t)))
((save-excursion
(require 'smartparens)
(ignore-errors
(sp-beginning-of-sexp)
(unless (eq (char-after) ?\()
@ -97,22 +117,58 @@ in, or d) the module associated with the current major mode (see
(mapcar #'intern (split-string module " "))
(unless (doom-module-p category submodule)
(error "'%s' isn't a valid module" module))
(let ((doc-path (doom-module-expand-file category submodule "README.org")))
(let ((doc-path (doom-module-path category submodule "README.org")))
(unless (file-exists-p doc-path)
(error "There is no documentation for this module"))
(find-file doc-path))))
;;;###autoload
(defun doom/version ()
"Display the current version of Doom & Emacs, including the current Doom
branch and commit."
(defun doom/describe-active-minor-mode (mode)
"Get information on an active minor mode. Use `describe-minor-mode' for a
selection of all minor-modes, active or not."
(interactive
(list (completing-read "Minor mode: "
(doom-active-minor-modes))))
(describe-minor-mode-from-symbol
(cl-typecase mode
(string (intern mode))
(symbol mode)
(t (error "Expected a symbol/string, got a %s" (type-of mode))))))
;;;###autoload
(defun doom/what-face (&optional pos)
"Shows all faces and overlay faces at point.
Interactively prints the list to the echo area. Noninteractively, returns a list
whose car is the list of faces and cadr is the list of overlay faces."
(interactive)
(message "Doom v%s (Emacs v%s). Branch: %s. Commit: %s."
doom-version
emacs-version
(if-let* ((branch (vc-git--symbolic-ref "core/core.el")))
branch
(let* ((pos (or pos (point)))
(faces (let ((face (get-text-property pos 'face)))
(if (keywordp (car-safe face))
(list face)
(cl-loop for f in (doom-enlist face) collect f))))
(overlays (cl-loop for ov in (overlays-at pos (1+ pos))
nconc (doom-enlist (overlay-get ov 'face)))))
(cond ((called-interactively-p 'any)
(message "%s %s\n%s %s"
(propertize "Faces:" 'face 'font-lock-comment-face)
(if faces
(cl-loop for face in faces
if (listp face)
concat (format "'%s " face)
else
concat (concat (propertize (symbol-name face) 'face face) " "))
"n/a ")
(if-let* ((rev (vc-git-working-revision "core/core.el")))
rev
(propertize "Overlays:" 'face 'font-lock-comment-face)
(if overlays
(cl-loop for ov in overlays
concat (concat (propertize (symbol-name ov) 'face ov) " "))
"n/a")))
(t
(and (or faces overlays)
(list faces overlays))))))
;;;###autoload
(defun doom//open-manual ()
(interactive)
(find-file (expand-file-name "index.org" doom-docs-dir)))

View file

@ -1,55 +1,68 @@
;;; core/autoload/message.el -*- lexical-binding: t; -*-
(defconst doom-message-fg
'((reset . 0)
(black . 30)
(red . 31)
(green . 32)
(yellow . 33)
(blue . 34)
(magenta . 35)
(cyan . 36)
(white . 37))
'((black 30 term-color-black)
(red 31 term-color-red)
(green 32 term-color-green)
(yellow 33 term-color-yellow)
(blue 34 term-color-blue)
(magenta 35 term-color-magenta)
(cyan 36 term-color-cyan)
(white 37 term-color-white))
"List of text colors.")
(defconst doom-message-bg
'((on-black . 40)
(on-red . 41)
(on-green . 42)
(on-yellow . 43)
(on-blue . 44)
(on-magenta . 45)
(on-cyan . 46)
(on-white . 47))
'((on-black 40 term-color-black)
(on-red 41 term-color-red)
(on-green 42 term-color-green)
(on-yellow 43 term-color-yellow)
(on-blue 44 term-color-blue)
(on-magenta 45 term-color-magenta)
(on-cyan 46 term-color-cyan)
(on-white 47 term-color-white))
"List of colors to draw text on.")
(defconst doom-message-fx
'((bold . 1)
(dark . 2)
(italic . 3)
(underscore . 4)
(blink . 5)
(rapid . 6)
(contrary . 7)
(concealed . 8)
(strike . 9))
'((bold 1 :weight bold)
(dark 2)
(italic 3 :slant italic)
(underscore 4 :underline t)
(blink 5)
(rapid 6)
(contrary 7)
(concealed 8)
(strike 9 :strike-through t))
"List of styles.")
;;;###autoload
(defun doom-ansi-apply (code message &rest args)
"Apply the ansi CODE to formatted MESSAGE with ARGS."
(let ((rule (or (assq code doom-message-fg)
(assq code doom-message-bg)
(assq code doom-message-fx))))
"Apply CODE to formatted MESSAGE with ARGS. CODE is derived from any of
`doom-message-fg', `doom-message-bg' or `doom-message-fx'.
In a noninteractive session, this wraps the result in ansi color codes.
Otherwise, it maps colors to a term-color-* face."
(let ((text (apply #'format message args)))
(if noninteractive
(format "\e[%dm%s\e[%dm"
(cdr rule)
(apply #'format message args)
0)))
(cadr
(or (assq code doom-message-fg)
(assq code doom-message-bg)
(assq code doom-message-fx)))
text 0)
(require 'term) ; piggyback on term's color faces
(propertize
text 'face
(let (spec)
(cond ((setq spec (caddr (assq code doom-message-fg)))
`(:foreground ,(face-foreground spec)))
((setq spec (caddr (assq code doom-message-bg)))
`(:background ,(face-background spec)))
((cddr (assq code doom-message-fx)))))))))
;;;###autoload
(defmacro format! (message &rest args)
"An alternative to `format' that strips out ANSI codes if used in an
interactive session."
"An alternative to `format' that understands (color ...) and converts them
into faces or ANSI codes depending on the type of sesssion we're in."
`(cl-flet*
(,@(cl-loop for rule
in (append doom-message-fg doom-message-bg doom-message-fx)
@ -63,19 +76,19 @@ interactive session."
(format ,message ,@args)))
;;;###autoload
(defmacro message! (message &rest args)
"An alternative to `message' that strips out ANSI codes if used in an
interactive session."
`(if noninteractive
(defmacro print! (message &rest args)
"Uses `message' in interactive sessions and `princ' otherwise (prints to
standard out).
Can be colored using (color ...) blocks:
(print! \"Hello %s %s\" (bold (blue \"How are you?\")))
(print! \"Hello %s %s\" (red \"World\"))
(print! (green \"Great %s!\" \"success\"))
Uses faces in interactive sessions and ANSI codes otherwise."
`(if (not noninteractive)
(message (format! ,message ,@args))
(let ((buf (get-buffer-create " *doom messages*")))
(with-current-buffer buf
(goto-char (point-max))
(let ((beg (point))
end)
(insert (format! ,message ,@args))
(insert "\n")
(setq end (point))
(ansi-color-apply-on-region beg end)))
(pop-to-buffer buf)
(goto-char (point-max)))))
;; princ prints to stdout, message to stderr
(princ (format! ,message ,@args))
(terpri)))

378
core/autoload/modules.el Normal file
View file

@ -0,0 +1,378 @@
;;; core/autoload/modules.el -*- lexical-binding: t; -*-
(autoload 'print! "autoload/message" nil 'macro)
(defun doom--server-eval (body)
(require 'server)
(when (server-running-p)
(server-eval-at server-name body)))
;;;###autoload
(defun doom//reload (&optional force-p)
"Reloads your config. This is experimental!
If called from a noninteractive session, this will try to communicate with a
live server (if one is found) to tell it to run this function.
If called from an interactive session, tries to reload autoloads files (if
necessary), reinistalize doom (via `doom-initialize') and reloads your private
init.el and config.el. Then runs `doom-reload-hook'."
(interactive)
(unless doom--inhibit-reload
(cond ((and noninteractive (not (daemonp)))
(require 'server)
(if (not (server-running-p))
(doom//reload-autoloads force-p)
(print! "Reloading active Emacs session...")
(print!
(bold "%%s")
(if (server-eval-at server-name '(doom//reload))
(green "Done!")
(red "There were issues!")))))
((let ((load-prefer-newer t))
(doom//reload-autoloads force-p)
(doom-initialize t)
(doom-initialize-modules t)
(print! (green "%d packages reloaded" (length package-alist)))
(run-hooks 'doom-reload-hook)
t)))))
;;
;; Autoload file generation
;;
(defvar doom-autoload-excluded-packages '(marshal gh)
"Packages that have silly or destructive autoload files that try to load
everyone in the universe and their dog, causing errors that make babies cry. No
one wants that.")
(defun doom--byte-compile (file)
(let ((short-name (file-name-nondirectory file)))
(condition-case-unless-debug ex
(when (byte-compile-file file)
(load (byte-compile-dest-file file) nil t)
(unless noninteractive
(message "Finished compiling %s" short-name)))
('error
(doom-delete-autoloads-file file)
(error "Error in %s: %s -- %s"
short-name
(car ex) (error-message-string ex))))))
;;;###autoload
(defun doom-delete-autoloads-file (file)
"Delete FILE (an autoloads file), and delete the accompanying *.elc file, if
it exists."
(or (stringp file)
(signal 'wrong-type-argument (list 'stringp file)))
(when (file-exists-p file)
(delete-file file)
(ignore-errors (delete-file (byte-compile-dest-file file)))
(print! "Deleted old %s" (file-name-nondirectory file))))
;;;###autoload
(defun doom//reload-autoloads (&optional file force-p)
"Reloads FILE (an autoload file), if it needs reloading.
FILE should be one of `doom-autoload-file' or `doom-package-autoload-file'. If
it is nil, it will try to reload both. If FORCE-P (universal argument) do it
even if it doesn't need reloading!"
(interactive
(list nil current-prefix-arg))
(or (null file)
(stringp file)
(signal 'wrong-type-argument (list 'stringp file)))
(cond ((equal file doom-autoload-file)
(doom//reload-doom-autoloads force-p))
((equal file doom-package-autoload-file)
(doom//reload-package-autoloads force-p))
((progn
(doom//reload-doom-autoloads force-p)
(doom//reload-package-autoloads force-p)))))
(defvar generated-autoload-load-name)
;;;###autoload
(defun doom//reload-doom-autoloads (&optional force-p)
"Refreshes the autoloads.el file, specified by `doom-autoload-file', if
necessary (or if FORCE-P is non-nil).
It scans and reads core/autoload/*.el, modules/*/*/autoload.el and
modules/*/*/autoload/*.el, and generates `doom-autoload-file'. This file tells
Emacs where to find lazy-loaded functions.
This should be run whenever your `doom!' block, or a module autoload file, is
modified."
(interactive)
(let ((doom-modules (doom-module-table))
(default-directory doom-emacs-dir)
(targets
(file-expand-wildcards
(expand-file-name "autoload/*.el" doom-core-dir))))
(dolist (path (doom-module-load-path))
(let ((auto-dir (expand-file-name "autoload" path))
(auto-file (expand-file-name "autoload.el" path)))
(when (file-exists-p auto-file)
(push auto-file targets))
(when (file-directory-p auto-dir)
(dolist (file (doom-files-in auto-dir :match "\\.el$" :full t))
(push file targets)))))
(if (and (not force-p)
(file-exists-p doom-autoload-file)
(not (cl-loop for file in targets
if (file-newer-than-file-p file doom-autoload-file)
return t)))
(ignore (print! (green "Doom core autoloads is up-to-date"))
(doom-initialize-autoloads doom-autoload-file))
(doom-delete-autoloads-file doom-autoload-file)
;; in case the buffer is open somewhere and modified
(when-let* ((buf (find-buffer-visiting doom-autoload-file)))
(with-current-buffer buf
(set-buffer-modified-p nil))
(kill-buffer buf))
(message "Generating new autoloads.el")
(dolist (file (nreverse targets))
(let* ((file (file-truename file))
(generated-autoload-load-name (file-name-sans-extension file))
(noninteractive (not doom-debug-mode)))
(print!
(cond ((not (doom-file-cookie-p file))
"⚠ Ignoring %s")
((update-file-autoloads file nil doom-autoload-file)
(yellow "✕ Nothing in %%s"))
((green "✓ Scanned %%s")))
(if (file-in-directory-p file default-directory)
(file-relative-name file)
(abbreviate-file-name file)))))
(make-directory (file-name-directory doom-autoload-file) t)
(let ((buf (find-file-noselect doom-autoload-file t))
case-fold-search)
(unwind-protect
(with-current-buffer buf
(goto-char (point-min))
(insert ";;; -*- lexical-binding:t -*-\n"
";; This file is autogenerated by `doom//reload-doom-autoloads', DO NOT EDIT !!\n\n")
(save-excursion
;; Replace autoload paths (only for module autoloads) with
;; absolute paths for faster resolution during load and
;; simpler `load-path'
(let ((load-path (append doom-psuedo-module-dirs
doom-modules-dirs
load-path))
cache)
(save-excursion
(while (re-search-forward "^\\s-*(autoload\\s-+'[^ ]+\\s-+\"\\([^\"]*\\)\"" nil t)
(let ((path (match-string 1)))
(replace-match
(or (cdr (assoc path cache))
(when-let* ((libpath (locate-library path))
(libpath (file-name-sans-extension libpath)))
(push (cons path (abbreviate-file-name libpath)) cache)
libpath)
path)
t t nil 1)))
(print! (green "✓ Autoload paths expanded")))))
;; Remove byte-compile inhibiting file variables so we can
;; byte-compile the file.
(when (re-search-forward "^;; no-byte-compile: t\n" nil t)
(replace-match "" t t))
;; Byte compile it to give the file a chance to reveal errors.
(save-buffer)
(doom--byte-compile doom-autoload-file)
(when (and noninteractive (not (daemonp)))
(doom--server-eval `(load-file ,doom-autoload-file)))
t)
(kill-buffer buf))))))
;;;###autoload
(defun doom//reload-package-autoloads (&optional force-p)
"Compiles `doom-package-autoload-file' from the autoloads files of all
installed packages. It also caches `load-path', `Info-directory-list',
`doom-disabled-packages', `package-activated-list' and `auto-mode-alist'.
Will do nothing if none of your installed packages have been modified. If
FORCE-P (universal argument) is non-nil, regenerate it anyway.
This should be run whenever your `doom!' block or update your packages."
(interactive)
(if (and (not force-p)
(file-exists-p doom-package-autoload-file)
(not (cl-loop initially do (doom-ensure-packages-initialized t)
for (_pkg desc) in package-alist
for autoload-file = (concat (package--autoloads-file-name desc) ".el")
if (file-newer-than-file-p autoload-file doom-package-autoload-file)
return t)))
(ignore (print! (green "Doom package autoloads is up-to-date"))
(doom-initialize-autoloads doom-package-autoload-file))
(doom-delete-autoloads-file doom-package-autoload-file)
(with-temp-file doom-package-autoload-file
(insert ";;; -*- lexical-binding:t -*-\n"
";; This file is autogenerated by `doom//reload-package-autoloads', DO NOT EDIT !!\n\n")
(save-excursion
;; Cache the important and expensive-to-initialize state here.
(doom-initialize-packages 'internal)
(prin1 `(setq load-path ',load-path
auto-mode-alist ',auto-mode-alist
Info-directory-list ',Info-directory-list
doom-disabled-packages ',doom-disabled-packages
package-activated-list ',package-activated-list)
(current-buffer))
(print! (green "✓ Cached package state"))
;; insert package autoloads
(dolist (spec package-alist)
(cl-destructuring-bind (pkg desc) spec
(unless (memq pkg doom-autoload-excluded-packages)
(let ((file
(abbreviate-file-name
(concat (package--autoloads-file-name desc) ".el"))))
(when (file-exists-p file)
(insert "(let ((load-file-name " (prin1-to-string file) "))\n")
(insert-file-contents file)
(while (re-search-forward "^\\(?:;;\\(.*\n\\)\\|\n\\)" nil t)
(unless (nth 8 (syntax-ppss))
(replace-match "" t t)))
(unless (bolp) (insert "\n"))
(insert ")\n")))))))
(print! (green "✓ Package autoloads included"))
;; Remove `load-path' and `auto-mode-alist' modifications (most of them,
;; at least); they are cached later, so all those membership checks are
;; unnecessary overhead.
(while (re-search-forward "^\\s-*\\((\\(?:add-to-list\\|when (boundp \\)\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)" nil t)
(goto-char (match-beginning 1))
(kill-sexp))
(print! (green "✓ Removed load-path/auto-mode-alist entries")))
(doom--byte-compile doom-package-autoload-file)
(when (and noninteractive (not (daemonp)))
(doom--server-eval `(load-file ,doom-package-autoload-file)))
t))
;;
;; Byte compilation
;;
;;;###autoload
(defun doom//byte-compile (&optional modules recompile-p)
"Byte compiles your emacs configuration.
init.el is always byte-compiled by this.
If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are
byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom
core. It always ignores unit tests and files with `no-byte-compile' enabled.
Doom was designed to benefit from byte-compilation, but the process may take a
while. Also, while your config files are byte-compiled, changes to them will not
take effect! Use `doom//clean-byte-compiled-files' or `make clean' to remove
these files.
If RECOMPILE-P is non-nil, only recompile out-of-date files."
(interactive
(list nil current-prefix-arg))
(let ((default-directory doom-emacs-dir))
(unless recompile-p
(doom//clean-byte-compiled-files))
(let ((total-ok 0)
(total-fail 0)
(total-noop 0)
compile-plugins-p
targets)
(dolist (module (delete-dups modules) (nreverse targets))
(pcase module
(":core" (push doom-core-dir targets))
(":private" (push doom-private-dir targets))
(":plugins"
(byte-recompile-directory package-user-dir 0 t)
(setq compile-plugins-p t))
((pred file-directory-p)
(push module targets))
((pred (string-match "^\\([^/]+\\)/\\([^/]+\\)$"))
(push (doom-module-locate-path
(intern (format ":%s" (match-string 1 module)))
(intern (match-string 2 module)))
targets))))
(unless (equal modules (list ":plugins"))
(let ((inhibit-message t)
noninteractive)
;; But first we must be sure that Doom and your private config have been
;; fully loaded. Which usually aren't so in an noninteractive session.
(doom//reload-autoloads)
(doom-initialize t)
(unless (equal modules (list ":core"))
(doom-initialize-modules t))))
;; If no targets were supplied, then we use your module list.
(unless targets
(setq targets (append (list doom-core-dir)
(doom-module-load-path))))
;; Assemble el files we want to compile; taking into account that MODULES
;; may be a list of MODULE/SUBMODULE strings from the command line.
(let ((target-files (doom-files-in targets :depth 2 :match "\\.el$")))
(if (not target-files)
(unless compile-plugins-p
(message "No targets to %scompile" (if recompile-p "re" "")))
(condition-case ex
(let ((use-package-expand-minimally t))
;; Always compile private init file
(cl-pushnew (expand-file-name "init.el" doom-private-dir)
target-files :test #'equal)
(cl-pushnew (expand-file-name "init.el" doom-emacs-dir)
target-files :test #'equal)
(dolist (target (cl-delete-duplicates (mapcar #'file-truename target-files) :test #'equal))
(if (or (not recompile-p)
(let ((elc-file (byte-compile-dest-file target)))
(and (file-exists-p elc-file)
(file-newer-than-file-p target elc-file))))
(let ((result (if (or (string-match-p "/\\(?:packages\\|doctor\\)\\.el$" target)
(not (doom-file-cookie-p target)))
'no-byte-compile
(byte-compile-file target)))
(short-name (if (file-in-directory-p target doom-emacs-dir)
(file-relative-name target doom-emacs-dir)
(abbreviate-file-name target))))
(cl-incf
(cond ((eq result 'no-byte-compile)
(print! (dark (white "⚠ Ignored %s" short-name)))
total-noop)
((null result)
(print! (red "✕ Failed to compile %s" short-name))
total-fail)
(t
(print! (green "✓ Compiled %s" short-name))
(quiet! (load target t t))
total-ok))))
(cl-incf total-noop)))
(print!
(bold
(color (if (= total-fail 0) 'green 'red)
"%s %d/%d file(s) (%d ignored)"
(if recompile-p "Recompiled" "Compiled")
total-ok (- (length target-files) total-noop)
total-noop))))
(error
(print! (red "\n%%s\n\n%%s\n\n%%s")
"There were breaking errors."
(error-message-string ex)
"Reverting changes...")
(quiet! (doom//clean-byte-compiled-files))
(print! (yellow "Finished (nothing was byte-compiled)")))))))))
;;;###autoload
(defun doom//clean-byte-compiled-files ()
"Delete all the compiled elc files in your Emacs configuration and private
module. This does not include your byte-compiled, third party packages.'"
(interactive)
(cl-loop with default-directory = doom-emacs-dir
for path in (append (doom-files-in doom-emacs-dir :match "\\.elc$" :depth 1)
(doom-files-in doom-psuedo-module-dirs :match "\\.elc$" :depth 1)
(doom-files-in doom-core-dir :match "\\.elc$")
(doom-files-in doom-modules-dirs :match "\\.elc$" :depth 4))
for truepath = (file-truename path)
if (file-exists-p path)
do (delete-file path)
and do
(print! (green "✓ Deleted %%s")
(if (file-in-directory-p truepath default-directory)
(file-relative-name truepath)
(abbreviate-file-name truepath)))
finally do (print! (bold (green "Everything is clean")))))

View file

@ -1,15 +1,8 @@
;;; core/autoload/packages.el -*- lexical-binding: t; -*-
(load! cache)
(require 'use-package)
(require 'quelpa)
(require 'package)
(require 'async)
;;; Private functions
(defsubst doom--sort-alpha (it other)
(string-lessp (symbol-name (car it))
(symbol-name (car other))))
(defun doom--packages-choose (prompt)
(let ((table (cl-loop for pkg in package-alist
@ -26,15 +19,15 @@
(condition-case ex2
(progn ,@body)
('file-error
(message! (bold (red " FILE ERROR: %s" (error-message-string ex2))))
(message! " Trying again...")
(print! (bold (red " FILE ERROR: %s" (error-message-string ex2))))
(print! " Trying again...")
(quiet! (doom-refresh-packages-maybe t))
,@body))
('user-error
(message! (bold (red " ERROR: %s" ex))))
(print! (bold (red " ERROR: %s" ex))))
('error
(doom--refresh-pkg-cache)
(message! (bold (red " FATAL ERROR: %s" ex))))))
(print! (bold (red " FATAL ERROR: %s" ex))))))
(defun doom--refresh-pkg-cache ()
"Clear the cache for `doom-refresh-packages-maybe'."
@ -57,7 +50,7 @@
(progn
(message "Refreshing package archives")
(package-refresh-contents)
(doom-cache-set 'last-pkg-refresh t 900))
(doom-cache-set 'last-pkg-refresh t 1200))
('error
(doom--refresh-pkg-cache)
(message "Failed to refresh packages: (%s) %s"
@ -147,7 +140,7 @@ Warning: this function is expensive; it re-evaluates all of doom's config files.
Be careful not to use it in a loop.
If INSTALLED-ONLY-P, only return packages that are installed."
(doom-initialize-packages (not noninteractive))
(doom-initialize-packages t)
(cl-loop with packages = (append doom-core-packages (mapcar #'car doom-packages))
for sym in (cl-delete-duplicates packages)
if (and (or (not installed-only-p)
@ -180,7 +173,8 @@ containing (PACKAGE-SYMBOL OLD-VERSION-LIST NEW-VERSION-LIST).
If INCLUDE-FROZEN-P is non-nil, check frozen packages as well.
Used by `doom//packages-update'."
(doom-initialize-packages (not noninteractive))
(doom-initialize-packages t)
(doom-refresh-packages-maybe doom-debug-mode)
(require 'async)
(let (quelpa-pkgs elpa-pkgs)
;; Separate quelpa from elpa packages
@ -201,9 +195,12 @@ Used by `doom//packages-update'."
(message "New thread for: %s" pkg))
(push (async-start
`(lambda ()
(let ((doom-init-p 'internal)
(let ((doom-init-p t)
(noninteractive t)
(load-path ',load-path)
(package-alist ',package-alist)
(package-archive-contents ',package-archive-contents)
(package-selected-packages ',package-selected-packages)
(doom-packages ',doom-packages)
(doom-modules ',doom-modules)
(quelpa-cache ',quelpa-cache)
@ -211,6 +208,8 @@ Used by `doom//packages-update'."
doom-private-dir)
(load ,(expand-file-name "core.el" doom-core-dir))
(load ,(expand-file-name "autoload/packages.el" doom-core-dir))
(require 'package)
(require 'quelpa)
(doom-package-outdated-p ',pkg))))
futures))
(delq nil
@ -223,7 +222,7 @@ Used by `doom//packages-update'."
depended on.
Used by `doom//packages-autoremove'."
(doom-initialize-packages (not noninteractive))
(doom-initialize-packages t)
(let ((package-selected-packages
(append (mapcar #'car doom-packages) doom-core-packages)))
(append (package--removable-packages)
@ -243,7 +242,6 @@ If INCLUDE-IGNORED-P is non-nil, includes missing packages that are ignored,
i.e. they have an :ignore property.
Used by `doom//packages-install'."
(doom-initialize-packages (not noninteractive))
(cl-loop for desc in (doom-get-packages)
for (name . plist) = desc
if (and (or include-ignored-p
@ -260,6 +258,7 @@ Used by `doom//packages-install'."
;; Main functions
;;
;;;###autoload
(defun doom-install-package (name &optional plist)
"Installs package NAME with optional quelpa RECIPE (see `quelpa-recipe' for an
example; the package name can be omitted)."
@ -283,6 +282,7 @@ example; the package name can be omitted)."
(map-put doom-packages name plist)
name)))
;;;###autoload
(defun doom-update-package (name &optional force-p)
"Updates package NAME (a symbol) if it is out of date, using quelpa or
package.el as appropriate."
@ -310,6 +310,7 @@ package.el as appropriate."
(delete-directory old-dir t)))
t))))
;;;###autoload
(defun doom-delete-package (name &optional force-p)
"Uninstalls package NAME if it exists, and clears it from `quelpa-cache'."
(unless (package-installed-p name)
@ -328,162 +329,6 @@ package.el as appropriate."
t)))
;;
;; Batch/interactive commands
;;
;;;###autoload
(defun doom//packages-install ()
"Interactive command for installing missing packages."
(interactive)
(if (not noninteractive)
(doom-packages--async-run 'doom//packages-install)
(message! "Looking for packages to install...")
(let ((packages (reverse (doom-get-missing-packages))))
(cond ((not packages)
(message! (green "No packages to install!"))
nil)
((not (or (getenv "YES")
(y-or-n-p
(format "%s packages will be installed:\n\n%s\n\nProceed?"
(length packages)
(mapconcat
(lambda (pkg)
(format "+ %s (%s)"
(car pkg)
(cond ((doom-package-different-recipe-p (car pkg))
"new recipe")
((doom-package-different-backend-p (car pkg))
(if (plist-get (cdr pkg) :recipe)
"ELPA -> QUELPA"
"QUELPA -> ELPA"))
((plist-get (cdr pkg) :recipe)
"QUELPA")
(t
"ELPA"))))
(sort (cl-copy-list packages) #'doom--sort-alpha)
"\n")))))
(message! (yellow "Aborted!"))
nil)
(t
(doom-refresh-packages-maybe doom-debug-mode)
(dolist (pkg packages)
(message! "Installing %s" (car pkg))
(doom--condition-case!
(message! "%s%s"
(if (and (package-installed-p (car pkg))
(not (doom-package-different-backend-p (car pkg)))
(not (doom-package-different-recipe-p (car pkg))))
(dark (white "⚠ ALREADY INSTALLED"))
(condition-case e
(if (doom-install-package (car pkg) (cdr pkg))
(green "✓ DONE")
(red "✕ FAILED"))
(error
(red "✕ ERROR (%s)" e))))
(if (plist-member (cdr pkg) :pin)
(format " [pinned: %s]" (plist-get (cdr pkg) :pin))
""))))
(message! (bold (green "Finished!")))
(doom//reload-load-path)
t)))))
;;;###autoload
(defun doom//packages-update ()
"Interactive command for updating packages."
(interactive)
(if (not noninteractive)
(doom-packages--async-run 'doom//packages-update)
(message! "Looking for outdated packages...")
(doom-refresh-packages-maybe doom-debug-mode)
(let ((packages (sort (doom-get-outdated-packages) #'doom--sort-alpha)))
(cond ((not packages)
(message! (green "Everything is up-to-date"))
nil)
((not (or (getenv "YES")
(y-or-n-p
(format "%s packages will be updated:\n\n%s\n\nProceed?"
(length packages)
(let ((max-len
(or (car (sort (mapcar (lambda (it) (length (symbol-name (car it)))) packages)
(lambda (it other) (> it other))))
10)))
(mapconcat
(lambda (pkg)
(format (format "+ %%-%ds %%-%ds -> %%s" (+ max-len 2) 14)
(symbol-name (car pkg))
(package-version-join (cadr pkg))
(package-version-join (cl-caddr pkg))))
packages
"\n"))))))
(message! (yellow "Aborted!"))
nil)
(t
(dolist (pkg packages)
(message! "Updating %s" (car pkg))
(doom--condition-case!
(message!
(let ((result (doom-update-package (car pkg) t)))
(color (if result 'green 'red)
(if result "✓ DONE" "✕ FAILED"))))))
(message! (bold (green "Finished!")))
(doom//reload-load-path)
t)))))
;;;###autoload
(defun doom//packages-autoremove ()
"Interactive command for auto-removing orphaned packages."
(interactive)
(if (not noninteractive)
(doom-packages--async-run 'doom//packages-autoremove)
(message! "Looking for orphaned packages...")
(let ((packages (doom-get-orphaned-packages)))
(cond ((not packages)
(message! (green "No unused packages to remove"))
nil)
((not
(or (getenv "YES")
(y-or-n-p
(format
"%s packages will be deleted:\n\n%s\n\nProceed?"
(length packages)
(mapconcat
(lambda (sym)
(format "+ %s (%s)" sym
(let ((backend (doom-package-backend sym)))
(if (doom-package-different-backend-p sym)
(pcase backend
(`quelpa "QUELPA->ELPA")
(`elpa "ELPA->QUELPA")
(_ "removed"))
(upcase (symbol-name backend))))))
(sort (cl-copy-list packages) #'string-lessp)
"\n")))))
(message! (yellow "Aborted!"))
nil)
(t
(dolist (pkg packages)
(doom--condition-case!
(message!
(let ((result (doom-delete-package pkg t)))
(color (if result 'green 'red)
"%s %s"
(if result "✓ Removed" "✕ Failed to remove")
pkg)))))
(message! (bold (green "Finished!")))
(doom//reload-load-path)
t)))))
;;
;; Interactive commands
;;
@ -533,3 +378,148 @@ calls."
(when (file-exists-p path)
(delete-directory path t))))))
;;
;; Package Management
;;
;;;###autoload
(defun doom//packages-install (&optional auto-accept-p)
"Interactive command for installing missing packages."
(interactive "P")
(print! "Looking for packages to install...")
(let ((packages (reverse (doom-get-missing-packages))))
(cond ((not packages)
(print! (green "No packages to install!"))
nil)
((not (or auto-accept-p
(y-or-n-p
(format "%s packages will be installed:\n\n%s\n\nProceed?"
(length packages)
(mapconcat
(lambda (pkg)
(format "+ %s (%s)"
(car pkg)
(cond ((doom-package-different-recipe-p (car pkg))
"new recipe")
((doom-package-different-backend-p (car pkg))
(if (plist-get (cdr pkg) :recipe)
"ELPA -> QUELPA"
"QUELPA -> ELPA"))
((plist-get (cdr pkg) :recipe)
"QUELPA")
(t
"ELPA"))))
(cl-sort (cl-copy-list packages) #'string-lessp
:key #'car)
"\n")))))
(error "Aborted!"))
((let (success)
(doom-refresh-packages-maybe doom-debug-mode)
(dolist (pkg packages)
(print! "Installing %s" (car pkg))
(doom--condition-case!
(print! "%s%s"
(cond ((and (package-installed-p (car pkg))
(not (doom-package-different-backend-p (car pkg)))
(not (doom-package-different-recipe-p (car pkg))))
(dark (white "⚠ ALREADY INSTALLED")))
((doom-install-package (car pkg) (cdr pkg))
(setq success t)
(green "✓ DONE"))
((red "✕ FAILED")))
(if (plist-member (cdr pkg) :pin)
(format " [pinned: %s]" (plist-get (cdr pkg) :pin))
""))))
(print! (bold (green "Finished!")))
(if success (doom-delete-autoloads-file doom-package-autoload-file))
success)))))
;;;###autoload
(defun doom//packages-update (&optional auto-accept-p)
"Interactive command for updating packages."
(interactive "P")
(print! "Looking for outdated packages...")
(let ((packages (cl-sort (cl-copy-list (doom-get-outdated-packages)) #'string-lessp
:key #'car)))
(cond ((not packages)
(print! (green "Everything is up-to-date"))
nil)
((not (or auto-accept-p
(y-or-n-p
(format "%s packages will be updated:\n\n%s\n\nProceed?"
(length packages)
(let ((max-len
(or (car (sort (mapcar (lambda (it) (length (symbol-name (car it)))) packages)
#'>))
10)))
(mapconcat
(lambda (pkg)
(format (format "+ %%-%ds %%-%ds -> %%s" (+ max-len 2) 14)
(symbol-name (car pkg))
(package-version-join (cadr pkg))
(package-version-join (cl-caddr pkg))))
packages
"\n"))))))
(error "Aborted!"))
((let (success)
(dolist (pkg packages)
(print! "Updating %s" (car pkg))
(doom--condition-case!
(print!
(let ((result (doom-update-package (car pkg) t)))
(when result (setq success t))
(color (if result 'green 'red)
(if result "✓ DONE" "✕ FAILED"))))))
(print! (bold (green "Finished!")))
(if success (doom-delete-autoloads-file doom-package-autoload-file))
success)))))
;;;###autoload
(defun doom//packages-autoremove (&optional auto-accept-p)
"Interactive command for auto-removing orphaned packages."
(interactive "P")
(print! "Looking for orphaned packages...")
(let ((packages (doom-get-orphaned-packages)))
(cond ((not packages)
(print! (green "No unused packages to remove"))
nil)
((not
(or auto-accept-p
(y-or-n-p
(format
"%s packages will be deleted:\n\n%s\n\nProceed?"
(length packages)
(mapconcat
(lambda (sym)
(format "+ %s (%s)" sym
(let ((backend (doom-package-backend sym)))
(if (doom-package-different-backend-p sym)
(pcase backend
(`quelpa "QUELPA->ELPA")
(`elpa "ELPA->QUELPA")
(_ "removed"))
(upcase (symbol-name backend))))))
(sort (cl-copy-list packages) #'string-lessp)
"\n")))))
(error "Aborted!"))
((let (success)
(dolist (pkg packages)
(doom--condition-case!
(print!
(let ((result (doom-delete-package pkg t)))
(when result (setq success t))
(color (if result 'green 'red)
"%s %s"
(if result "✓ Removed" "✕ Failed to remove")
pkg)))))
(print! (bold (green "Finished!")))
(if success (doom-delete-autoloads-file doom-package-autoload-file))
success)))))

View file

@ -1,6 +1,5 @@
;;; core/autoload/test.el -*- lexical-binding: t; no-byte-compile: t; -*-
;;;###autoload
(defun doom//run-tests (&optional modules)
"Run all loaded tests, specified by MODULES (a list of module cons cells) or
command line args following a double dash (each arg should be in the
@ -8,21 +7,21 @@ command line args following a double dash (each arg should be in the
If neither is available, run all tests in all enabled modules."
(interactive)
(let ((doom-modules (make-hash-table :test #'equal)))
;; ensure DOOM is initialized
(doom//reload-autoloads)
(let (noninteractive)
;; Core libraries aren't fully loaded in a noninteractive session, so we
;; reload it with `noninteractive' set to nil to force them to.
(doom-initialize t)
(run-hooks 'doom-init-hook 'pre-command-hook 'doom-after-switch-buffer-hook))
(doom-initialize-modules t))
(condition-case-unless-debug ex
(let ((target-paths
(let* ((doom-modules (doom-module-table))
(target-paths
;; Convert targets (either from MODULES or `argv') into a list of
;; string paths, pointing to the root directory of modules
(cond ((string= (car argv) "--") ; command line
(cond ((stringp (car modules)) ; command line
(save-match-data
(cl-loop for arg in (cdr argv)
if (string= arg "core") collect doom-core-dir
(cl-loop for arg in modules
if (string= arg ":core") collect doom-core-dir
else if (string-match-p "/" arg)
nconc (cl-loop for dir in doom-modules-dirs
collect (expand-file-name arg dir))
@ -38,26 +37,26 @@ If neither is available, run all tests in all enabled modules."
(modules ; cons-cells given to MODULES
(cl-loop for (module . submodule) in modules
if (doom-module-find-path module submodule)
if (doom-module-locate-path module submodule)
collect it))
((let (noninteractive)
(load (expand-file-name "init.test.el" user-emacs-directory) nil t)
(append (list doom-core-dir) (doom-module-load-path)))))))
((append (list doom-core-dir)
(doom-module-load-path))))))
;; Load all the unit test files...
(dolist (path target-paths)
(let ((test-path (expand-file-name "test/" path)))
(when (file-directory-p test-path)
(dolist (test-file (reverse (doom-packages--files test-path "\\.el$")))
(dolist (test-file (reverse (doom-files-in test-path :match "\\.el$" :full t)))
(load test-file nil :noerror)))))
;; ... then run them
(switch-to-buffer (get-buffer-create "*blank*"))
(if noninteractive
(ert-run-tests-batch-and-exit)
(call-interactively #'ert-run-tests-interactively)))
('error
(lwarn 'doom-test :error
"%s -> %s"
(car ex) (error-message-string ex))))))
(car ex) (error-message-string ex)))))
;; --- Test helpers -----------------------

View file

@ -1,212 +0,0 @@
;;; core/autoload/util.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom/what-face (&optional pos)
"Shows all faces and overlay faces at point.
Interactively prints the list to the echo area. Noninteractively, returns a list
whose car is the list of faces and cadr is the list of overlay faces."
(interactive)
(let* ((pos (or pos (point)))
(faces (let ((face (get-text-property pos 'face)))
(if (keywordp (car-safe face))
(list face)
(cl-loop for f in (doom-enlist face) collect f))))
(overlays (cl-loop for ov in (overlays-at pos (1+ pos))
nconc (doom-enlist (overlay-get ov 'face)))))
(cond ((called-interactively-p 'any)
(message "%s %s\n%s %s"
(propertize "Faces:" 'face 'font-lock-comment-face)
(if faces
(cl-loop for face in faces
if (listp face)
concat (format "'%s " face)
else
concat (concat (propertize (symbol-name face) 'face face) " "))
"n/a ")
(propertize "Overlays:" 'face 'font-lock-comment-face)
(if overlays
(cl-loop for ov in overlays
concat (concat (propertize (symbol-name ov) 'face ov) " "))
"n/a")))
(t
(and (or faces overlays)
(list faces overlays))))))
;;;###autoload
(defun doom-active-minor-modes ()
"Get a list of active minor-mode symbols."
(cl-loop for mode in minor-mode-list
if (and (boundp mode) (symbol-value mode))
collect mode))
;;;###autoload
(defun doom/what-minor-mode (mode)
"Get information on an active minor mode. Use `describe-minor-mode' for a
selection of all minor-modes, active or not."
(interactive
(list (completing-read "Minor mode: "
(doom-active-minor-modes))))
(describe-minor-mode-from-symbol
(cl-typecase mode
(string (intern mode))
(symbol mode)
(t (error "Expected a symbol/string, got a %s" (type-of mode))))))
;;;###autoload
(defun doom/am-i-secure ()
"Test to see if your root certificates are securely configured in emacs."
(declare (interactive-only t))
(interactive)
(unless (string-match-p "\\_<GNUTLS\\_>" system-configuration-features)
(warn "gnutls support isn't built into Emacs, there may be problems"))
(if-let* ((bad-hosts
(cl-loop for bad
in '("https://wrong.host.badssl.com/"
"https://self-signed.badssl.com/")
if (condition-case _e
(url-retrieve-synchronously bad)
(error nil))
collect bad)))
(error (format "tls seems to be misconfigured (it got %s)."
bad-hosts))
(url-retrieve "https://badssl.com"
(lambda (status)
(if (or (not status) (plist-member status :error))
(warn "Something went wrong.\n\n%s" (pp-to-string status))
(message "Your trust roots are set up properly.\n\n%s" (pp-to-string status))
t)))))
(defvar doom--profiler nil)
;;;###autoload
(defun doom/toggle-profiler ()
"Toggle the Emacs profiler. Starts it if isn't running. Stops it and pops up
the profiling report otherwise."
(interactive)
(if (not doom--profiler)
(profiler-start 'cpu+mem)
(profiler-report)
(profiler-stop))
(setq doom--profiler (not doom--profiler)))
;;;###autoload
(defun doom/profile-emacs ()
"Profile the startup time of Emacs in the background.
If INIT-FILE is non-nil, profile that instead of USER-INIT-FILE."
(interactive)
(require 'esup)
(let ((init-file esup-user-init-file))
(message "Starting esup...")
(esup-reset)
(setq esup-server-process (esup-server-create (esup-select-port)))
(setq esup-server-port (process-contact esup-server-process :service))
(message "esup process started on port %s" esup-server-port)
(let ((process-args `("*esup-child*"
"*esup-child*"
,esup-emacs-path
"-q"
"-L" ,esup-load-path
"-l" "esup-child"
,(format "--eval=(esup-child-run \"%s\" \"%s\" %d)"
init-file
esup-server-port
esup-depth)
"--eval=(run-hooks 'after-init-hook 'emacs-startup-hook 'window-setup-hook)")))
(when esup-run-as-batch-p
(setq process-args (append process-args '("--batch"))))
(setq esup-child-process (apply #'start-process process-args)))
(set-process-sentinel esup-child-process 'esup-child-process-sentinel)))
;;;###autoload
(defun doom-info ()
"Returns diagnostic information about the current Emacs session in markdown,
ready to be pasted in a bug report on github."
(require 'vc-git)
(let ((default-directory doom-emacs-dir))
(format
(concat "- OS: %s (%s)\n"
"- Emacs: %s (%s)\n"
"- Doom: %s (%s %s)\n"
"- Graphic display: %s (daemon: %s)\n"
"- System features: %s\n"
"- Details:\n"
" ```elisp\n"
" uname -a: %s\n"
" modules: %s\n"
" packages: %s\n"
" elc dirs: %s\n"
" exec-path: %s\n"
" ```\n")
system-type system-configuration
emacs-version (format-time-string "%b %d, %Y" emacs-build-time)
doom-version
(if-let* ((branch (vc-git--symbolic-ref "core/core.el")))
branch
"n/a")
(if-let* ((rev (vc-git-working-revision "core/core.el")))
(format "https://github.com/hlissner/doom-emacs/commit/%s" rev)
"n/a")
(display-graphic-p) (daemonp)
(bound-and-true-p system-configuration-features)
;; details
(with-temp-buffer
(unless (zerop (call-process "uname" nil t nil "-a"))
(insert (format "%s" system-type)))
(string-trim (buffer-string)))
(or (cl-loop with cat = nil
for key being the hash-keys of doom-modules
if (or (not cat) (not (eq cat (car key))))
do (setq cat (car key)) and collect cat
else collect
(let ((flags (doom-module-get cat (cdr key) :flags)))
(if flags
`(,(cdr key) ,@flags)
(cdr key))))
"n/a")
(or (let (packages)
(ignore-errors
(require 'async)
;; collect these in another session to protect this
;; session's state
(async-get
(async-start
`(lambda ()
(setq load-path ',load-path)
(load ,(expand-file-name "core/core.el" doom-emacs-dir))
(load ,(expand-file-name "init.el" doom-emacs-dir))
(load ,(expand-file-name "core/autoload/packages.el" doom-emacs-dir))
(doom-get-packages))
(lambda (p) (setq packages p))))
(mapcar (lambda (x)
(if (cdr x)
(format "%s" x)
(symbol-name (car x))))
(cl-sort packages #'string-lessp :key (lambda (x) (symbol-name (car x)))))))
"n/a")
(or (ignore-errors
(cl-delete-duplicates
(cl-loop for file in (append (reverse (directory-files-recursively doom-core-dir "\\.elc$"))
(cl-loop for dir in doom-modules-dirs
nconc (directory-files-recursively dir "\\.elc$")))
collect (file-relative-name (file-name-directory file) doom-emacs-dir))
:test #'equal))
"n/a")
exec-path)))
;;;###autoload
(defun doom/info ()
"Collects some debug information about your Emacs session, formats it into
markdown and copies it to your clipboard, ready to be pasted into bug reports!"
(declare (interactive-only t))
(interactive)
(if noninteractive
(message "%s" (doom-info))
(message "Generating Doom info...")
(kill-new (doom-info))
(message "Done! Copied to clipboard.")))
;;;###autoload
(defun doom/toggle-debug-mode ()
(interactive)
(setq doom-debug-mode (not doom-debug-mode))
(toggle-debug-on-error))

286
core/core-dispatcher.el Normal file
View file

@ -0,0 +1,286 @@
;;; -*- lexical-binding: t; no-byte-compile: t; -*-
;; Eagerly load these libraries because this module may be loaded in a session
;; that hasn't been fully initialized (where autoloads files haven't been
;; generated or `load-path' populated).
(load! autoload/packages)
(load! autoload/modules)
(load! autoload/debug)
(load! autoload/message)
;;
;; Dispatcher API
;;
(defvar doom-auto-accept (getenv "YES")
"If non-nil, Doom will auto-accept any confirmation prompts during batch
commands like `doom//packages-install', `doom//packages-update' and
`doom//packages-autoremove'.")
(defconst doom--dispatch-command-alist ())
(defconst doom--dispatch-alias-alist ())
(defun doom--dispatch-format (desc &optional short)
(if (equal desc "TODO")
(format! (yellow "TODO"))
(with-temp-buffer
(let ((fill-column 72))
(insert desc)
(goto-char (point-min))
(while (re-search-forward "\n\n[^ \n]" nil t)
(fill-paragraph)))
(if (not short)
(buffer-string)
(goto-char (point-min))
(buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))))
(defun doom--dispatch-help (&optional command desc &rest args)
"Display help documentation for a dispatcher command. If COMMAND and DESC are
omitted, show all available commands, their aliases and brief descriptions."
(if command
(princ (doom--dispatch-format desc))
(print! (bold "%-10s\t%s\t%s" "Command:" "Alias" "Description"))
(dolist (spec (sort doom--dispatch-command-alist
(lambda (x y) (string-lessp (car x) (car y)))))
(cl-destructuring-bind (command &key desc _body) spec
(let ((aliases (cl-loop for (alias . cmd) in doom--dispatch-alias-alist
if (eq cmd command)
collect (symbol-name alias))))
(print! " %-10s\t%s\t%s"
command (if aliases (string-join aliases ",") "")
(doom--dispatch-format desc t)))))))
(defun doom-dispatch (args)
"Invoke a dispatcher command and pass ARGS to it."
(let ((help (equal (car args) "help")))
(if help (pop args))
(cl-destructuring-bind (command &key desc body)
(let ((sym (intern (car args))))
(or (assq sym doom--dispatch-command-alist)
(assq (cdr (assq sym doom--dispatch-alias-alist)) doom--dispatch-command-alist)
(error "Invalid command: %s" (car args))))
(if help
(apply #'doom--dispatch-help command desc (cdr args))
(funcall body (cdr args))))))
;; FIXME Clumsy way of registering commands, refactor!
(defmacro def-dispatcher! (command desc &rest body)
"Define a dispatcher command. COMMAND is a symbol or a list of symbols
representing the aliases for this command. DESC is a string description. The
first line should be short (under 60 letters), as it will be displayed for
bin/doom help.
BODY will be run when this dispatcher is called."
(declare (doc-string 2))
(let* ((command (doom-enlist command))
(cmd (car command))
(aliases (cdr command)))
`(progn
,(when aliases
`(dolist (alias ',aliases)
(map-put doom--dispatch-alias-alist alias ',cmd)))
(map-put doom--dispatch-command-alist
',cmd (list :desc ,desc
;; FIXME Implicit args var; ew
:body (lambda (args) ,@body))))))
;;
;; Dispatch commands
;;
;; Dummy dispatchers (no-op because they're handled especially)
(def-dispatcher! run
"Run Doom Emacs from bin/doom's parent directory.
All arguments are passed on to Emacs (except for -p and -e).
doom run
doom run -nw init.el
WARNING: this command exists for convenience and testing. Doom will suffer
additional overhead for be started this way. For the best performance, it
is best to run Doom out of ~/.emacs.d and ~/.doom.d.")
(def-dispatcher! (doctor doc)
"Checks for issues with your current Doom config.")
(def-dispatcher! (help h)
"Look up additional information about a command.")
;; Real dispatchers
(def-dispatcher! (quickstart qs)
"Quickly deploy a private module and Doom.
This deploys a barebones config to ~/.doom.d. The destination can be changed
with the -p option, e.g.
doom -p ~/.config/doom quickstart
This command will refuse to overwrite the private directory if it already
exists."
(doom//quickstart))
(def-dispatcher! (install i)
"Installs requested plugins that aren't installed."
(doom//reload-doom-autoloads)
(when (doom//packages-install doom-auto-accept)
(doom//reload-package-autoloads)))
(def-dispatcher! (update u)
"Checks for and updates outdated plugins."
(doom//reload-doom-autoloads)
(when (doom//packages-update doom-auto-accept)
(doom//reload-package-autoloads)))
(def-dispatcher! (autoremove r)
"Removes orphaned plugins."
(doom//reload-doom-autoloads)
(when (doom//packages-autoremove doom-auto-accept)
(doom//reload-package-autoloads)))
(def-dispatcher! (autoloads a)
"Regenerates Doom's autoloads file.
This file tells Emacs where to find your module's autoloaded functions and
plugins."
(doom//reload-autoloads nil 'force))
(def-dispatcher! (upgrade up)
"Checks out the latest Doom on this branch."
(doom//upgrade))
(def-dispatcher! (compile c)
"Byte-compiles your config or selected modules.
compile [TARGETS...]
compile :core :private lang/python
compile feature lang
Accepts :core, :private and :plugins as special arguments, indicating you want
to byte-compile Doom's core files, your private config or your ELPA plugins,
respectively."
(doom//byte-compile args))
(def-dispatcher! (recompile rc)
"Re-byte-compiles outdated *.elc files."
(doom//byte-compile args 'recompile))
(def-dispatcher! clean
"Delete all *.elc files."
(doom//clean-byte-compiled-files))
(def-dispatcher! test
"Run Doom unit tests."
(load! autoload/test)
(doom//run-tests args))
(def-dispatcher! info
"Output system info in markdown for bug reports."
(doom/info))
(def-dispatcher! (version v)
"Reports the version of Doom and Emacs."
(doom/version))
(def-dispatcher! (refresh re)
"Refresh Doom. Same as autoremove+install+autoloads.
This is the equivalent of running autoremove, install, autoloads, then
recompile. Run this whenever you:
1. Modify your `doom!' block,
2. Add or remove `package!' blocks to your config,
3. Add or remove autoloaded functions in module autoloaded files.
4. Update Doom outside of Doom (e.g. with git)"
(let ((doom--inhibit-reload t))
(with-demoted-errors "%s" (doom//packages-autoremove))
(with-demoted-errors "%s" (doom//packages-install)))
(doom//reload-autoloads)
(doom//byte-compile nil 'recompile))
;;
;; Quality of Life Commands
;;
;; FIXME Detect & enforce remote
(defvar doom-remote "origin"
"TODO")
(defun doom//upgrade ()
"Upgrade Doom to the latest version."
(interactive)
(require 'vc-git)
(let ((core-file (expand-file-name "init.el" doom-core-dir))
(branch (vc-git--symbolic-ref core-file))
(default-directory doom-emacs-dir))
(unless (file-exists-p core-file)
(error "Couldn't find %s, was Doom cloned properly?"
(abbreviate-file-name core-file)))
(unless branch
(error "Couldn't detect what branch you're using. Is %s a repo?"
(abbreviate-file-name doom-emacs-dir)))
(unless (eq (vc-state core-file 'Git) 'up-to-date)
(user-error "Doom has been modified; refusing to upgrade. Stash or undo your changes"))
(with-temp-buffer
(let ((buf (current-buffer)))
(when (zerop (process-file "git" nil buf nil
"fetch" "--tags" doom-remote branch))
(let ((current-rev (vc-git-working-revision core-file))
(rev (shell-command-to-string (format "git rev-parse %s/%s" doom-remote branch))))
(unless rev
(error "Couldn't detect Doom's version. Is %s a repo?"
(abbreviate-file-name doom-emacs-dir)))
(if (equal current-rev rev)
(message "Doom is up to date!")
(when (or doom-auto-accept
(y-or-n-p "Doom is out of date, update?"))
(unless (zerop (process-file "git" nil buf nil
"checkout" (format "%s/%s" doom-remote branch)))
(error "An error occurred while checking out the latest commit"))
(when (file-exists-p (byte-compile-dest-file core-file))
(message "Your config is byte-compiled, removing byte-compiled files")
(doom//clean-byte-compiled-files))
(doom//reload)
(message "Done! Please restart Emacs for changes to take effect")))))))))
(defun doom//quickstart ()
"Quickly deploy a private module and Doom.
This deploys a barebones config to `doom-private-dir', installs all missing
packages and regenerates the autoloads file."
(interactive)
(let ((short-private-dir (abbreviate-file-name doom-private-dir)))
(if (file-directory-p doom-private-dir)
(print! (yellow "%s directory already exists. Skipping." short-private-dir))
(print! "Creating %s" short-private-dir)
(make-directory doom-private-dir t)
(print! (green "Done!")))
(let ((init-file (expand-file-name "init.el" doom-private-dir)))
(if (file-exists-p init-file)
(print! (yellow "%sinit.el already exists. Skipping." short-private-dir))
(print! "Copying init.example.el to %s" short-private-dir)
(copy-file (expand-file-name "init.example.el" doom-emacs-dir)
init-file)
(print! (green "Done!"))))
(let ((config-file (expand-file-name "config.el" doom-private-dir)))
(if (file-exists-p config-file)
(print! "%sconfig.el already exists. Skipping." short-private-dir)
(print! "Deploying empty config.el file in %s" short-private-dir)
(with-temp-file config-file (insert ""))
(print! (green "Done!")))))
(print! "Installing plugins")
(doom//packages-install)
(print! "Regenerating autoloads files")
(doom//reload-autoloads nil 'force-p)
(print! (bold (green "\nFinished! Doom is ready to go!\n")))
(with-temp-buffer
(doom-template-insert "QUICKSTART_INTRO")
(print! (buffer-string))))
(provide 'core-dispatcher)
;;; core-dispatcher.el ends here

View file

@ -70,7 +70,7 @@ fundamental-mode) for performance sake."
;; Built-in plugins
;;
(push '("/[A-Z]+$" . text-mode) auto-mode-alist)
(push '("/LICENSE\\'" . text-mode) auto-mode-alist)
(electric-indent-mode -1) ; enabled by default in Emacs 25+. No thanks.
@ -83,14 +83,15 @@ fundamental-mode) for performance sake."
;; revert buffers for changed files
(def-package! autorevert
:defer doom-before-switch-buffer-hook
:after-call doom-before-switch-buffer-hook
:config
(setq auto-revert-verbose nil)
(global-auto-revert-mode +1))
;; persist variables across sessions
(def-package! savehist
:defer (pre-command-hook . 1)
:defer 1
:after-call post-command-hook
:config
(setq savehist-file (concat doom-cache-dir "savehist")
savehist-save-minibuffer-history t
@ -100,7 +101,7 @@ fundamental-mode) for performance sake."
;; persistent point location in buffers
(def-package! saveplace
:defer doom-before-switch-buffer-hook
:after-call doom-before-switch-buffer-hook
:config
(setq save-place-file (concat doom-cache-dir "saveplace"))
(defun doom*recenter-on-load-saveplace (&rest _)
@ -112,20 +113,21 @@ fundamental-mode) for performance sake."
;; Keep track of recently opened files
(def-package! recentf
:defer (pre-command-hook . 1)
:defer 1
:after-call find-file-hook
:commands recentf-open-files
:config
(setq recentf-save-file (concat doom-cache-dir "recentf")
recentf-auto-cleanup 60
recentf-auto-cleanup 120
recentf-max-menu-items 0
recentf-max-saved-items 300
recentf-filename-handlers '(file-truename)
recentf-exclude
(list #'file-remote-p "\\.\\(gz\\|gif\\|svg\\|png\\|jpe?g\\)$"
(list #'file-remote-p "\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\)$"
"^/tmp/" "^/ssh:" "\\.?ido\\.last$" "\\.revive$" "/TAGS$"
"^/var/folders/.+$"
;; ignore private DOOM temp files (but not all of them)
(concat "^" (file-truename doom-local-dir))))
(lambda (file) (file-in-directory-p file doom-local-dir))))
(recentf-mode +1))
@ -135,7 +137,7 @@ fundamental-mode) for performance sake."
;; Auto-close delimiters and blocks as you type
(def-package! smartparens
:defer doom-before-switch-buffer-hook
:after-call doom-before-switch-buffer-hook
:commands (sp-pair sp-local-pair sp-with-modes)
:config
(require 'smartparens-config)
@ -155,7 +157,7 @@ fundamental-mode) for performance sake."
;; Branching undo
(def-package! undo-tree
:defer doom-before-switch-buffer-hook
:after-call doom-before-switch-buffer-hook
:config
;; persistent undo history is known to cause undo history corruption, which
;; can be very destructive! So disable it!
@ -176,13 +178,15 @@ fundamental-mode) for performance sake."
command-log-mode-open-log-turns-on-mode t))
(def-package! dtrt-indent
:after-call doom-before-switch-buffer-hook
:config
(setq dtrt-indent-verbosity (if doom-debug-mode 2 0))
(defun doom|detect-indentation ()
(unless (or doom-inhibit-indent-detection (eq major-mode 'fundamental-mode))
(dtrt-indent-mode +1)))
(add-hook 'after-change-major-mode-hook #'doom|detect-indentation))
(unless noninteractive
(add-hook 'after-change-major-mode-hook #'doom|detect-indentation)))
(def-package! expand-region
:commands (er/expand-region er/contract-region er/mark-symbol er/mark-word)

View file

@ -56,19 +56,15 @@ If any hook returns non-nil, all hooks after it are ignored.")
;; embolden local bindings
(set-face-attribute 'which-key-local-map-description-face nil :weight 'bold)
(which-key-setup-side-window-bottom)
(add-hook 'doom-init-hook #'which-key-mode))
(add-hook 'doom-post-init-hook #'which-key-mode))
(def-package! hydra
:commands (defhydra defhydradio)
:init
;; In case I later need to wrap defhydra in any special functionality.
(defalias 'def-hydra! 'defhydra)
(defalias 'def-hydra-radio! 'defhydradio)
:defer t
:config
(setq lv-use-seperator t)
(def-hydra! doom@text-zoom (:hint t :color red)
(defhydra doom@text-zoom (:hint t :color red)
"
Text zoom: _j_:zoom in, _k_:zoom out, _0_:reset
"
@ -76,7 +72,7 @@ If any hook returns non-nil, all hooks after it are ignored.")
("k" text-scale-decrease "out")
("0" (text-scale-set 0) "reset"))
(def-hydra! doom@window-nav (:hint nil)
(defhydra doom@window-nav (:hint nil)
"
Split: _v_ert _s_:horz
Delete: _c_lose _o_nly

View file

@ -1,8 +1,15 @@
;;; core-lib.el -*- lexical-binding: t; -*-
;; Built in packages we use a lot of
(require 'subr-x)
(require 'cl-lib)
(require 'map)
(eval-and-compile
(unless EMACS26+
(with-no-warnings
;; if-let and when-let are deprecated in Emacs 26+ in favor of their
;; if-let* variants, so we alias them for 25 users.
(defalias 'if-let* #'if-let)
(defalias 'when-let* #'when-let))))
@ -11,18 +18,40 @@
;; Helpers
;;
(defun doom--resolve-path-forms (paths &optional root)
(cond ((stringp paths)
(defun doom--resolve-path-forms (spec &optional directory)
"Converts a simple nested series of or/and forms into a series of
`file-exists-p' checks.
For example
(doom--resolve-path-forms
'(or \"some-file\" (and path-var \"/an/absolute/path\"))
\"~\")
Returns
'(or (file-exists-p (expand-file-name \"some-file\" \"~\"))
(and (file-exists-p (expand-file-name path-var \"~\"))
(file-exists-p \"/an/absolute/path\")))
This is used by `associate!', `file-exists-p!' and `project-file-exists-p!'."
(cond ((stringp spec)
`(file-exists-p
(expand-file-name
,paths ,(if (or (string-prefix-p "./" paths)
(string-prefix-p "../" paths))
'default-directory
(or root `(doom-project-root))))))
((listp paths)
(cl-loop for i in paths
collect (doom--resolve-path-forms i root)))
(t paths)))
,(if (file-name-absolute-p spec)
spec
`(expand-file-name ,spec ,directory))))
((symbolp spec)
`(file-exists-p ,(if directory
`(expand-file-name ,spec ,directory)
path)))
((and (listp spec)
(memq (car spec) '(or and)))
`(,(car spec)
,@(cl-loop for i in (cdr spec)
collect (doom--resolve-path-forms i directory))))
((listp spec)
(doom--resolve-path-forms (eval spec t) directory))
(t spec)))
(defun doom--resolve-hook-forms (hooks)
(cl-loop with quoted-p = (eq (car-safe hooks) 'quote)
@ -33,6 +62,11 @@
collect hook
else collect (intern (format "%s-hook" (symbol-name hook)))))
;;
;; Functions
;;
(defun doom-unquote (exp)
"Return EXP unquoted."
(while (memq (car-safe exp) '(quote function))
@ -43,6 +77,94 @@
"Return EXP wrapped in a list, or as-is if already a list."
(if (listp exp) exp (list exp)))
(defun doom-file-cookie-p (file)
"Returns the return value of the ;;;###if predicate form in FILE."
(with-temp-buffer
(insert-file-contents-literally file nil 0 256)
(if (and (re-search-forward "^;;;###if " nil t)
(<= (line-number-at-pos) 3))
(let ((load-file-name file))
(eval (sexp-at-point)))
t)))
(defun doom-keyword-intern (str)
"Converts STR (a string) into a keyword (`keywordp')."
(or (stringp str)
(signal 'wrong-type-argument (list 'stringp str)))
(intern (concat ":" str)))
(defun doom-keyword-name (keyword)
"Returns the string name of KEYWORD (`keywordp') minus the leading colon."
(or (keywordp keyword)
(signal 'wrong-type-argument (list 'keywordp keyword)))
(substring (symbol-name keyword) 1))
(cl-defun doom-files-in
(path-or-paths &rest rest
&key
filter
map
full
(follow-symlinks t)
(type 'files)
(relative-to (unless full default-directory))
(depth 99999)
(match "^[^.]"))
"Returns a list of files/directories in PATH-OR-PATHS (one string path or a
list of them).
FILTER is a function or symbol that takes one argument (the path). If it returns
non-nil, the entry will be excluded.
MAP is a function or symbol which will be used to transform each entry in the
results.
TYPE determines what kind of path will be included in the results. This can be t
(files and folders), 'files or 'dirs.
By default, this function returns paths relative to PATH-OR-PATHS if it is a
single path. If it a list of paths, this function returns absolute paths.
Otherwise, by setting RELATIVE-TO to a path, the results will be transformed to
be relative to it.
The search recurses up to DEPTH and no further. DEPTH is an integer.
MATCH is a string regexp. Only entries that match it will be included."
(cond
((listp path-or-paths)
(cl-loop for path in path-or-paths
if (file-directory-p path)
nconc (apply #'doom-files-in path (plist-put rest :relative-to relative-to))))
((let ((path path-or-paths)
result)
(dolist (file (file-name-all-completions "" path))
(unless (member file '("./" "../"))
(let ((fullpath (expand-file-name file path)))
(cond ((directory-name-p fullpath)
(when (and (memq type '(t dirs))
(string-match-p match file)
(not (and filter (funcall filter fullpath)))
(not (and (file-symlink-p fullpath)
(not follow-symlinks))))
(setq result
(nconc result
(list (cond (map (funcall map fullpath))
(relative-to (file-relative-name fullpath relative-to))
(fullpath))))))
(unless (<= depth 1)
(setq result
(nconc result (apply #'doom-files-in fullpath
(append `(:depth ,(1- depth) :relative-to ,relative-to)
rest))))))
((and (memq type '(t files))
(string-match-p match file)
(not (and filter (funcall filter fullpath))))
(push (if relative-to
(file-relative-name fullpath relative-to)
fullpath)
result))))))
result))))
(defun doom*shut-up (orig-fn &rest args)
"Generic advisor for silencing noisy functions."
(quiet! (apply orig-fn args)))
@ -61,8 +183,10 @@
(defmacro after! (targets &rest body)
"A smart wrapper around `with-eval-after-load'. Supresses warnings during
compilation."
compilation. This will no-op on features that have been disabled by the user."
(declare (indent defun) (debug t))
(unless (and (symbolp targets)
(memq targets doom-disabled-packages))
(list (if (or (not (bound-and-true-p byte-compile-current-file))
(dolist (next (doom-enlist targets))
(if (symbolp next)
@ -83,7 +207,7 @@ compilation."
(setq body `(after! ,next ,@body)))
body)
((listp targets)
`(after! (:all ,@targets) ,@body)))))
`(after! (:all ,@targets) ,@body))))))
(defmacro quiet! (&rest forms)
"Run FORMS without making any output."
@ -121,10 +245,11 @@ HOOK can be a quoted hook or a sharp-quoted function (which will be advised)."
,@forms
(cond ((functionp ,hook) (advice-remove ,hook #',fn))
((symbolp ,hook) (remove-hook ,hook #',fn)))
(unintern ',fn nil)))
(fmakunbound ',fn)))
(cond ((functionp ,hook)
(advice-add ,hook ,(if append :after :before) #',fn))
((symbolp ,hook)
(put ',fn 'permanent-local-hook t)
(add-hook ,hook #',fn ,append))))))
(defmacro add-hook! (&rest args)
@ -138,7 +263,7 @@ HOOK can be a quoted hook or a sharp-quoted function (which will be advised)."
3. A function, list of functions, or body forms to be wrapped in a lambda.
Examples:
(add-hook! 'some-mode-hook 'enable-something)
(add-hook! 'some-mode-hook 'enable-something) (same as `add-hook')
(add-hook! some-mode '(enable-something and-another))
(add-hook! '(one-mode-hook second-mode-hook) 'enable-something)
(add-hook! (one-mode second-mode) 'enable-something)
@ -201,7 +326,19 @@ Body forms can access the hook's arguments through the let-bound variable
(nreverse forms))))
(defmacro associate! (mode &rest plist)
"Associate a minor mode to certain patterns and project files."
"Enables a minor mode if certain conditions are met.
The available conditions are:
:modes SYMBOL_LIST
A list of major/minor modes in which this minor mode may apply.
:match REGEXP
A regexp to be tested against the current file path.
:files SPEC
Accepts what `project-file-exists-p!' accepts. Checks if certain files exist
relative to the project root.
:when FORM
Whenever FORM returns non-nil."
(declare (indent 1))
(unless noninteractive
(let ((modes (plist-get plist :modes))
@ -220,7 +357,7 @@ Body forms can access the hook's arguments through the let-bound variable
(not ,mode)
(and buffer-file-name (not (file-remote-p buffer-file-name)))
,(if match `(if buffer-file-name (string-match-p ,match buffer-file-name)) t)
,(if files (doom--resolve-path-forms files) t)
,(if files (doom--resolve-path-forms files '(doom-project-root)) t)
,(or pred-form t))
(,mode 1)))
,@(if (and modes (listp modes))
@ -232,5 +369,19 @@ Body forms can access the hook's arguments through the let-bound variable
(t (user-error "associate! invalid rules for mode [%s] (modes %s) (match %s) (files %s)"
mode modes match files))))))
(defmacro file-exists-p! (spec &optional directory)
"Returns t if the files in SPEC all exist.
SPEC can be a single file or a list of forms/files. It understands nested (and
...) and (or ...), as well.
DIRECTORY is where to look for the files in SPEC if they aren't absolute. This
doesn't apply to variables, however.
For example:
(file-exists-p (or doom-core-dir \"~/.config\" \"some-file\") \"~\")"
(doom--resolve-path-forms spec directory))
(provide 'core-lib)
;;; core-lib.el ends here

View file

@ -30,10 +30,12 @@
;; Don't open files from the workspace in a new frame
ns-pop-up-frames nil)
(cond ((display-graphic-p)
(if (not (display-graphic-p))
(add-hook 'doom-post-init-hook #'osx-clipboard-mode)
;; A known problem with GUI Emacs on MacOS: it runs in an isolated
;; environment, so envvars will be wrong. That includes the PATH
;; Emacs picks up. `exec-path-from-shell' fixes this.
;; environment, so envvars will be wrong. That includes the PATH Emacs
;; picks up. `exec-path-from-shell' fixes this.
(defun doom|init-exec-path ()
(when (require 'exec-path-from-shell nil t)
(def-setting! :env (&rest vars)
"Inject VARS from your shell environment into Emacs."
@ -42,8 +44,7 @@
exec-path-from-shell-arguments (delete "-i" exec-path-from-shell-arguments))
(defvaralias 'exec-path-from-shell-debug 'doom-debug-mode)
(exec-path-from-shell-initialize)))
((require 'osx-clipboard nil t)
(osx-clipboard-mode +1))))
(add-hook 'doom-pre-init-hook #'doom|init-exec-path)))
(IS-LINUX
(setq x-gtk-use-system-tooltips nil ; native tooltips are ugly!

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,7 @@
:config
(add-hook 'dired-before-readin-hook #'projectile-track-known-projects-find-file-hook)
(add-hook 'find-file-hook #'doom|autoload-project-mode)
(add-hook 'find-file-hook #'doom|init-project-mode)
(projectile-mode +1)
;; a more generic project root file
@ -94,12 +94,12 @@ If NOCACHE, don't fetch a cached answer."
(defalias 'doom-project-expand #'projectile-expand-root)
(defmacro doom-project-has! (files)
(defmacro project-file-exists-p! (files)
"Checks if the project has the specified FILES.
Paths are relative to the project root, unless they start with ./ or ../ (in
which case they're relative to `default-directory'). If they start with a slash,
they are absolute."
(doom--resolve-path-forms files (doom-project-root)))
(doom--resolve-path-forms files '(doom-project-root)))
(defun doom-project-find-file (dir)
"Fuzzy-find a file under DIR."
@ -131,7 +131,7 @@ for .dir-locals.el.")
"Hook run when a project is enabled. The name of the project's mode and its
state are passed in.")
(defun doom|autoload-project-mode ()
(defun doom|init-project-mode ()
"Auto-enable the project(s) listed in `doom-project'."
(when doom-project
(if (symbolp doom-project)

View file

@ -24,6 +24,7 @@ Expects a `font-spec'.")
return a string). This changes the 'long' name of a major-mode, allowing for
shorter major mode name in the mode-line. See `doom|set-mode-name'.")
;;
(defvar doom-init-ui-hook nil
"List of hooks to run when the UI has been initialized.")
@ -57,7 +58,7 @@ with `doom//reload-theme').")
compilation-scroll-output 'first-error
confirm-nonexistent-file-or-buffer t
cursor-in-non-selected-windows nil ; hide cursors in other windows
custom-theme-directory (concat doom-private-dir "themes/")
custom-theme-directory (expand-file-name "themes/" doom-private-dir)
display-line-numbers-width 3
enable-recursive-minibuffers nil
frame-inhibit-implied-resize t
@ -177,15 +178,11 @@ DEFAULT is non-nil, set the default mode-line for all buffers."
;; Plugins
;;
(def-package! ace-link
:commands (ace-link-help ace-link-org ace-link-addr ace-link-mu4e))
(def-package! avy
:commands (avy-goto-char-2 avy-goto-line)
:config
;; `avy'
(setq avy-all-windows nil
avy-background t))
avy-background t)
;; `all-the-icons'
(def-package! all-the-icons
:commands (all-the-icons-octicon all-the-icons-faicon all-the-icons-fileicon
all-the-icons-wicon all-the-icons-material all-the-icons-alltheicon
@ -200,19 +197,41 @@ DEFAULT is non-nil, set the default mode-line for all buffers."
all-the-icons-wicon all-the-icons-alltheicon))
(advice-add fn :around #'doom*disable-all-the-icons-in-tty)))
(def-package! hideshow ; built-in
:commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p)
:config (setq hs-hide-comments-when-hiding-all nil))
;; `hide-mode-line-mode'
(add-hook 'completion-list-mode-hook #'hide-mode-line-mode)
(def-package! hide-mode-line
:commands hide-mode-line-mode
:init (add-hook 'completion-list-mode-hook #'hide-mode-line-mode))
;; `rainbow-delimiters' Helps us distinguish stacked delimiter pairs. Especially
;; in parentheses-drunk languages like Lisp.
(def-package! rainbow-delimiters
:hook (lisp-mode . rainbow-delimiters-mode)
:config (setq rainbow-delimiters-max-face-count 3))
(def-package! highlight-indentation
:commands (highlight-indentation-mode highlight-indentation-current-column-mode))
;; `restart-emacs'
(setq restart-emacs--args (list "--restore"))
;; For modes with sub-par number fontification
(def-package! highlight-numbers :commands highlight-numbers-mode)
;; `visual-fill-column' For a distractions-free-like UI, that dynamically
;; resizes margins and can center a buffer.
(setq visual-fill-column-center-text t
visual-fill-column-width
;; take Emacs 26 line numbers into account
(+ (if (boundp 'display-line-numbers) 6 0)
fill-column))
;;
;; Built-in packages
;;
;; `hideshow'
(setq hs-hide-comments-when-hiding-all nil)
;; show typed keystrokes in minibuffer
(defun doom|enable-ui-keystrokes () (setq echo-keystrokes 0.02))
(defun doom|disable-ui-keystrokes () (setq echo-keystrokes 0))
(doom|enable-ui-keystrokes)
;; ...but hide them while isearch is active
(add-hook 'isearch-mode-hook #'doom|disable-ui-keystrokes)
(add-hook 'isearch-mode-end-hook #'doom|enable-ui-keystrokes)
;; Highlights the current line
(def-package! hl-line ; built-in
@ -253,50 +272,15 @@ DEFAULT is non-nil, set the default mode-line for all buffers."
(add-hook 'evil-visual-state-entry-hook #'doom|disable-hl-line)
(add-hook 'evil-visual-state-exit-hook #'doom|enable-hl-line-maybe)))
;; Helps us distinguish stacked delimiter pairs. Especially in parentheses-drunk
;; languages like Lisp.
(def-package! rainbow-delimiters
:hook (lisp-mode . rainbow-delimiters-mode)
:config (setq rainbow-delimiters-max-face-count 3))
(def-package! restart-emacs
:commands restart-emacs
:config (setq restart-emacs--args (list "--restore")))
;; For a distractions-free-like UI, that dynamically resizes margins and can
;; center a buffer.
(def-package! visual-fill-column
:commands visual-fill-column-mode
:config
(setq-default
visual-fill-column-center-text t
visual-fill-column-width
;; take Emacs 26 line numbers into account
(+ (if (boundp 'display-line-numbers) 6 0)
fill-column)))
;;
;; Built-in packages
;;
;; show typed keystrokes in minibuffer
(defun doom|enable-ui-keystrokes () (setq echo-keystrokes 0.02))
(defun doom|disable-ui-keystrokes () (setq echo-keystrokes 0))
(doom|enable-ui-keystrokes)
;; ...but hide them while isearch is active
(add-hook 'isearch-mode-hook #'doom|disable-ui-keystrokes)
(add-hook 'isearch-mode-end-hook #'doom|enable-ui-keystrokes)
;; undo/redo changes to Emacs' window layout
(def-package! winner
:defer doom-before-switch-window-hook
:after-call doom-before-switch-window-hook
:preface (defvar winner-dont-bind-my-keys t) ; I'll bind keys myself
:config (winner-mode +1))
;; highlight matching delimiters
(def-package! paren
:defer doom-before-switch-buffer-hook
:after-call doom-before-switch-buffer-hook
:config
(setq show-paren-delay 0.1
show-paren-highlight-openparen t
@ -316,7 +300,7 @@ DEFAULT is non-nil, set the default mode-line for all buffers."
(remove-hook 'kill-buffer-query-functions #'server-kill-buffer-query-function))
(add-hook 'server-visit-hook #'server-remove-kill-buffer-hook)
;; whitespace-mode settings
;; `whitespace-mode'
(setq whitespace-line-column nil
whitespace-style
'(face indentation tabs tab-mark spaces space-mark newline newline-mark
@ -371,7 +355,7 @@ from the default."
(advice-add #'switch-to-buffer :around #'doom*switch-buffer-hooks)
(advice-add #'display-buffer :around #'doom*switch-buffer-hooks)
(advice-add #'pop-to-buffer :around #'doom*switch-buffer-hooks))
(add-hook 'doom-init-hook #'doom|init-custom-hooks)
(add-hook 'doom-post-init-hook #'doom|init-custom-hooks)
(defun doom*load-theme-hooks (theme &rest _)
(setq doom-theme theme)
@ -704,7 +688,7 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
;;
(run-hooks 'doom-init-ui-hook))
(add-hook 'doom-init-hook #'doom|init-ui)
(add-hook 'doom-post-init-hook #'doom|init-ui)
(provide 'core-ui)
;;; core-ui.el ends here

View file

@ -1,5 +1,10 @@
;;; core.el --- the heart of the beast -*- lexical-binding: t; -*-
(eval-when-compile
(when (version< emacs-version "25")
(error "Doom only supports Emacs 25.1 and higher!")))
;;
(defvar doom-version "2.0.9"
"Current version of DOOM emacs.")
@ -15,7 +20,7 @@ line or use --debug-init to enable this.")
;;
(defvar doom-emacs-dir
(eval-when-compile (file-truename user-emacs-directory))
"The path to this emacs.d directory.")
"The path to this emacs.d directory. Must end in a slash.")
(defvar doom-core-dir (concat doom-emacs-dir "core/")
"Where essential files are stored.")
@ -44,14 +49,29 @@ Use this for files that change often, like cache files.")
(defvar doom-private-dir
(eval-when-compile
(or (let ((xdg-path (concat (or (getenv "XDG_CONFIG_HOME")
"~/.config")
"/doom/")))
(or (let ((xdg-path
(expand-file-name "doom/"
(or (getenv "XDG_CONFIG_HOME")
"~/.config"))))
(if (file-directory-p xdg-path) xdg-path))
"~/.doom.d/"))
"Where your private customizations are placed. Must end in a slash. Respects
XDG directory conventions if ~/.config/doom exists.")
;; Doom hooks
(defvar doom-pre-init-hook nil
"Hooks run after Doom is first initialized; after Doom's core files are
loaded, but before your private init.el file or anything else is loaded.")
(defvar doom-init-hook nil
"Hooks run after all init.el files are loaded, including your private and all
module init.el files, but before their config.el files are loaded.")
(defvar doom-post-init-hook nil
"A list of hooks run when Doom is fully initialized. Fires at the end of
`emacs-startup-hook', as late as possible. Guaranteed to run after everything
else (except for `window-setup-hook').")
;;;
;; UTF-8 as the default coding system
@ -70,6 +90,13 @@ XDG directory conventions if ~/.config/doom exists.")
debug-on-error doom-debug-mode
ffap-machine-p-known 'reject ; don't ping things that look like domain names
idle-update-delay 2 ; update ui less often
auto-mode-case-fold nil
;; be quiet at startup; don't load or display anything unnecessary
inhibit-startup-message t
inhibit-startup-echo-area-message user-login-name
inhibit-default-init t
initial-major-mode 'fundamental-mode
initial-scratch-message nil
;; keep the point out of the minibuffer
minibuffer-prompt-properties '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt)
;; History & backup settings (save nothing, that's what git is for)
@ -93,20 +120,6 @@ XDG directory conventions if ~/.config/doom exists.")
url-cache-directory (concat doom-cache-dir "url/")
url-configuration-directory (concat doom-etc-dir "url/"))
;; be quiet at startup; don't load or display anything unnecessary
(unless noninteractive
(advice-add #'display-startup-echo-area-message :override #'ignore)
(setq inhibit-startup-message t
inhibit-startup-echo-area-message user-login-name
inhibit-default-init t
initial-major-mode 'fundamental-mode
initial-scratch-message nil))
;; Custom init hooks; clearer than `after-init-hook', `emacs-startup-hook', and
;; `window-setup-hook'.
(defvar doom-init-hook nil
"A list of hooks run when DOOM is initialized.")
;;
;; Emacs fixes/hacks
@ -148,9 +161,12 @@ with functions that require it (like modeline segments)."
buffer))
(advice-add #'make-indirect-buffer :around #'doom*set-indirect-buffer-filename)
;; Truly silence startup message
(fset #'display-startup-echo-area-message #'ignore)
;;
;; Bootstrap
;; Optimize startup
;;
(defvar doom--file-name-handler-alist file-name-handler-alist)
@ -167,20 +183,28 @@ with functions that require it (like modeline segments)."
"Resets garbage collection settings to reasonable defaults (if you don't do
this, you'll get stuttering and random freezes) and resets
`file-name-handler-alist'."
(unless noninteractive
(run-hooks 'doom-init-hook))
(setq file-name-handler-alist doom--file-name-handler-alist
gc-cons-threshold 16777216
gc-cons-percentage 0.15))
gc-cons-threshold 8388608
gc-cons-percentage 0.1))
(add-hook 'emacs-startup-hook #'doom|finalize)
(add-hook 'doom-reload-hook #'doom|finalize)
;;
(require 'core-packages (concat doom-core-dir "core-packages"))
(doom-initialize noninteractive)
;; Bootstrap Doom
;;
(add-hook! '(emacs-startup-hook doom-reload-hook)
#'doom|finalize)
(when doom-private-dir
(load (concat doom-private-dir "init") t t))
(add-to-list 'load-path doom-core-dir)
(require 'core-lib)
(require 'core-packages)
(require 'core-os)
(doom-initialize noninteractive)
(if noninteractive
(require 'core-dispatcher)
(doom-initialize-modules))
(provide 'core)
;;; core.el ends here

View file

@ -36,3 +36,6 @@
;; core-keybinds.el
(package! which-key)
(package! hydra)
;; autoload/debug.el
(package! esup)

29
core/templates/BUG_REPORT Normal file
View file

@ -0,0 +1,29 @@
Please read through the following before you submit your issue.
+ [ ] Running `make` (then restarting Emacs) did not fix my issue
+ [ ] If I have byte-compiled, I've tried recompiling with `make compile`
+ [ ] If I changed the version of Emacs installed, I've recompiled by plugins
with `make compile-elpa`
+ [ ] I ran `make doctor` and it produced no leads
+ [ ] My issue cannot be found [on the wiki](/docs/troubleshoot.org)
+ [ ] I filled out the four fields in the template below
-------------------------------------------------------------------
### Observed behavior
<!-- What happened -->
### Expected behavior
<!-- What *should* have happened -->
### Steps to reproduce
<!-- Tell us how to reproduce the issue in steps -->
### Extra details
<!-- Include backtraces & screenshots if possible -->
-------------------------------------------------------------------

View file

@ -0,0 +1,30 @@
Before you doom yourself, there are a few things you should know:
1. If you use GUI Emacs, run `M-x all-the-icons-install-fonts` so you don't get
weird symbols all over the place.
2. When you edit ~/.doom.d/init.el or modify modules, run:
bin/doom refresh
This will ensure all needed packages are installed, all orphaned packages are
removed, and your autoloads files are up to date. This is important! If you
forget to do this you will get errors!
3. If something inexplicably goes wrong, it's a good idea to try:
bin/doom doctor
It will diagnose common issues with your environment and setup, and may give
you clues about what is wrong.
4. To update doom, run
bin/doom upgrade
Doing it any other way will require you run `bin/doom refresh` otherwise,
5. Check out `bin/doom help` to see what else it can do (it is also safe to add
~/.emacs.d/bin to your PATH).
Have fun!

View file

@ -0,0 +1,7 @@
;; Welcome to the vanilla sanbox!
;;
;; This is a test bed for Emacs Lisp to be run in a blank instance of Emacs
;; (free of Doom's clutches). This is equivalent to using emacs -Q with
;; package.el initialized and nothing else (so you have access to installed
;; plugins).

View file

@ -7,7 +7,8 @@
(dolist (bsym buffer-args)
(push `(,bsym (get-buffer-create ,(symbol-name bsym)))
buffers))
`(cl-flet ((buffer-list
`(save-window-excursion
(cl-flet ((buffer-list
(lambda ()
(cl-remove-if-not #'buffer-live-p (list ,@(reverse (mapcar #'car buffers)))))))
(let* ((split-width-threshold 0)
@ -17,7 +18,7 @@
(delete-other-windows)
,@body
(let (kill-buffer-query-functions kill-buffer-hook)
(mapc #'kill-buffer (buffer-list)))))))
(mapc #'kill-buffer (buffer-list))))))))
;;
(def-test! get-buffers
@ -93,7 +94,7 @@
(with-temp-buffers!! (a b c d e)
(dolist (buf (list a b))
(with-current-buffer buf
(emacs-lisp-mode)))
(delay-mode-hooks (emacs-lisp-mode))))
(dolist (buf (list c d e))
(with-current-buffer buf
(text-mode)))

View file

@ -1,5 +1,5 @@
;; -*- no-byte-compile: t; -*-
;;; core/test/autoload-debug.el
;;; core/test/autoload-help.el
(def-test! what-face
(insert (propertize "Hello " 'face 'font-lock-keyword-face))

View file

@ -10,15 +10,15 @@
"Hello World"))
(should (equal (format! (green "Hello %s" "World"))
(format "\e[%dm%s\e[0m"
(cdr (assq 'green doom-message-fg))
(cadr (assq 'green doom-message-fg))
"Hello World")))
(should (equal (format! (on-red "Hello %s" "World"))
(format "\e[%dm%s\e[0m"
(cdr (assq 'on-red doom-message-bg))
(cadr (assq 'on-red doom-message-bg))
"Hello World")))
(should (equal (format! (bold "Hello %s" "World"))
(format "\e[%dm%s\e[0m"
(cdr (assq 'bold doom-message-fx))
(cadr (assq 'bold doom-message-fx))
"Hello World")))))
(def-test! ansi-format-nested

View file

@ -1,6 +1,9 @@
;; -*- no-byte-compile: t; -*-
;;; core/test/autoload-package.el
(require 'package)
(require 'quelpa)
(defun -pkg (name version &optional reqs)
(package-desc-create :name name :version version :reqs reqs))

View file

@ -7,8 +7,8 @@
(def-test! resolve-path-forms
(should
(equal (doom--resolve-path-forms '(and "fileA" "fileB"))
'(and (file-exists-p (expand-file-name "fileA" (doom-project-root)))
(file-exists-p (expand-file-name "fileB" (doom-project-root)))))))
'(and (file-exists-p (expand-file-name "fileA" nil))
(file-exists-p (expand-file-name "fileB" nil))))))
;; `doom--resolve-hook-forms'
(def-test! resolve-hook-forms

View file

@ -33,15 +33,15 @@
(should (equal (doom-project-expand "init.el")
(expand-file-name "init.el" (doom-project-root))))))
;; `doom-project-has!'
;; `project-file-exists-p!'
(def-test! project-has!
:minor-mode projectile-mode
(let ((default-directory doom-core-dir))
;; Resolve from project root
(should (doom-project-has! "init.el"))
(should (project-file-exists-p! "init.el"))
;; Chained file checks
(should (doom-project-has! (and "init.el" "LICENSE")))
(should (doom-project-has! (or "init.el" "does-not-exist")))
(should (doom-project-has! (and "init.el" (or "LICENSE" "does-not-exist"))))
(should (project-file-exists-p! (and "init.el" "LICENSE")))
(should (project-file-exists-p! (or "init.el" "does-not-exist")))
(should (project-file-exists-p! (and "init.el" (or "LICENSE" "does-not-exist"))))
;; Should resolve relative paths from `default-directory'
(should (doom-project-has! (and "./core.el" "../init.el")))))
(should (project-file-exists-p! (and "core/core.el" "./init.el")))))

View file

@ -1,16 +0,0 @@
;;; debug.el -*- lexical-binding: t; -*-
;; To test something in a blank, vanilla Emacs session (Emacs -Q) load me:
;;
;; emacs -Q -l debug.el
(setq user-emacs-directory (file-name-directory load-file-name)
package--init-file-ensured t
package-user-dir (expand-file-name ".local/packages/elpa" user-emacs-directory)
package-archives
'(("gnu" . "https://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")))
(package-initialize)
;; Then you can test packages in isolation here...

View file

@ -11,7 +11,8 @@
;; Faster to disable these here (before they've been initialized)
(setq tool-bar-mode nil
menu-bar-mode nil)
(set-scroll-bar-mode nil)
menu-bar-mode nil
scroll-bar-mode nil)
(modify-all-frames-parameters '((vertical-scroll-bars)))
;; TODO Once Emacs 27 hits stable, perhaps replace init.el with early-init.el

View file

@ -27,4 +27,7 @@
;;
;;; License: MIT
(setq user-emacs-directory (file-name-directory load-file-name)
load-prefer-newer noninteractive)
(require 'core (concat user-emacs-directory "core/core"))

View file

@ -26,9 +26,6 @@
+childframe) ; uses childframes for popups (Emacs 26+ only)
:ui
(popup ; tame sudden yet inevitable temporary windows
+all ; catch all popups that start with an asterix
+defaults) ; default popup rules
doom ; what makes DOOM look the way it does
doom-dashboard ; a nifty splash screen for Emacs
doom-modeline ; a snazzy Atom-inspired mode-line
@ -37,6 +34,9 @@
hl-todo ; highlight TODO/FIXME/NOTE tags
nav-flash ; blink the current line after jumping
neotree ; a project drawer, like NERDTree for vim
(popup ; tame sudden yet inevitable temporary windows
+all ; catch all popups that start with an asterix
+defaults) ; default popup rules
;tabbar ; FIXME an (incomplete) tab bar for Emacs
;unicode ; extended unicode support for various languages
vi-tilde-fringe ; fringe tildes to mark beyond EOB
@ -45,69 +45,67 @@
:tools
dired ; making dired pretty [functional]
editorconfig ; let someone else argue about tabs vs spaces
ein ; tame Jupyter notebooks with emacs
electric-indent ; smarter, keyword-based electric-indent
;ein ; tame Jupyter notebooks with emacs
eshell ; a consistent, cross-platform shell (WIP)
gist ; interacting with github gists
;gist ; interacting with github gists
imenu ; an imenu sidebar and searchable code index
;macos ; MacOS-specific commands
make ; run make tasks from Emacs
;make ; run make tasks from Emacs
;magit ;
password-store ; password manager for nerds
;password-store ; password manager for nerds
pdf ; pdf enhancements
prodigy ; Managing external services
;prodigy ; FIXME managing external services & code builders
;rgb ; creating color strings
rotate-text ; cycle region at point between text candidates
term ; terminals in Emacs
;term ; terminals in Emacs
tmux ; an API for interacting with tmux
upload ; map local to remote projects via ssh/ftp
:lang
assembly ; assembly for fun or debugging
cc ; C/C++/Obj-C madness
crystal ; ruby at the speed of c
clojure ; java with a lisp
csharp ; unity, .NET, and mono shenanigans
;assembly ; assembly for fun or debugging
;cc ; C/C++/Obj-C madness
;crystal ; ruby at the speed of c
;clojure ; java with a lisp
;csharp ; unity, .NET, and mono shenanigans
data ; config/data formats
;erlang ; an elegant language for a more civilized age
elixir ; erlang done right
elm ; care for a cup of TEA?
;elixir ; erlang done right
;elm ; care for a cup of TEA?
emacs-lisp ; drown in parentheses
ess ; emacs speaks statistics
go ; the hipster dialect
(haskell +intero) ; a language that's lazier than I am
hy ; readability of scheme w/ speed of python
(java +meghanada) ; the poster child for carpal tunnel syndrome
javascript ; all(hope(abandon(ye(who(enter(here))))))
julia ; a better, faster MATLAB
latex ; writing papers in Emacs has never been so fun
ledger ; an accounting system in Emacs
lua ; one-based indices? one-based indices
;ess ; emacs speaks statistics
;go ; the hipster dialect
;(haskell +intero) ; a language that's lazier than I am
;hy ; readability of scheme w/ speed of python
;(java +meghanada) ; the poster child for carpal tunnel syndrome
;javascript ; all(hope(abandon(ye(who(enter(here))))))
;julia ; a better, faster MATLAB
;latex ; writing papers in Emacs has never been so fun
;ledger ; an accounting system in Emacs
;lua ; one-based indices? one-based indices
markdown ; writing docs for people to ignore
nim ; python + lisp at the speed of c
nix ; I hereby declare "nix geht mehr!"
ocaml ; an objective camel
;nim ; python + lisp at the speed of c
;nix ; I hereby declare "nix geht mehr!"
;ocaml ; an objective camel
(org ; organize your plain life in plain text
+attach ; custom attachment system
+babel ; running code in org
+capture ; org-capture in and outside of Emacs
+export ; Exporting org to whatever you want
+present ; Emacs for presentations
+publish) ; Emacs+Org as a static site generator
perl ; write code no one else can comprehend
php ; perl's insecure younger brother
plantuml ; diagrams for confusing people more
purescript ; javascript, but functional
python ; beautiful is better than ugly
rest ; Emacs as a REST client
ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
scala ; java, but good
+present) ; Emacs for presentations
;perl ; write code no one else can comprehend
;php ; perl's insecure younger brother
;plantuml ; diagrams for confusing people more
;purescript ; javascript, but functional
;python ; beautiful is better than ugly
;rest ; Emacs as a REST client
;ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
;rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
;scala ; java, but good
sh ; she sells (ba|z)sh shells on the C xor
solidity ; do you need a blockchain? No.
swift ; who asked for emoji variables?
typescript ; javascript, but better
web ; the tubes
;solidity ; do you need a blockchain? No.
;swift ; who asked for emoji variables?
;web ; the tubes
;; Applications are complex and opinionated modules that transform Emacs
;; toward a specific purpose. They may have additional dependencies and

View file

@ -2,9 +2,8 @@
;;;###autoload
(defun +impatient-mode/toggle ()
"TODO"
"Toggle `impatient-mode' in the current buffer."
(interactive)
(require 'simple-httpd)
(unless (process-status "httpd")
(httpd-start))
(impatient-mode)

View file

@ -1,6 +0,0 @@
;;; collab/impatient-mode/config.el -*- lexical-binding: t; -*-
;; Show off code as you write it
(def-package! impatient-mode
:commands impatient-mode)

View file

@ -24,8 +24,7 @@ MODES should be one major-mode symbol or a list of them."
;;
(def-package! company
:commands (company-mode global-company-mode company-complete
company-complete-common company-manual-begin company-grab-line)
:commands (company-complete-common company-manual-begin company-grab-line)
:init
(setq company-idle-delay nil
company-tooltip-limit 14
@ -48,7 +47,8 @@ MODES should be one major-mode symbol or a list of them."
(def-package! company
:when (featurep! +auto)
:defer pre-command-hook
:defer 2
:after-call pre-command-hook
:config (setq company-idle-delay 0.2))
@ -73,27 +73,12 @@ MODES should be one major-mode symbol or a list of them."
(def-package! company-dict
:commands company-dict
:defer t
:config
(defun +company|enable-project-dicts (mode &rest _)
"Enable per-project dictionaries."
(if (symbol-value mode)
(cl-pushnew mode company-dict-minor-mode-list :test #'eq)
(add-to-list 'company-dict-minor-mode-list mode #'eq)
(setq company-dict-minor-mode-list (delq mode company-dict-minor-mode-list))))
(add-hook 'doom-project-hook #'+company|enable-project-dicts))
;;
;; Included with company.el
;;
(autoload 'company-capf "company-capf")
(autoload 'company-dabbrev "company-dabbrev")
(autoload 'company-dabbrev-code "company-dabbrev-code")
(autoload 'company-elisp "company-elisp")
(autoload 'company-etags "company-etags")
(autoload 'company-files "company-files")
(autoload 'company-gtags "company-gtags")
(autoload 'company-ispell "company-ispell")
(autoload 'company-yasnippet "company-yasnippet")

View file

@ -11,7 +11,24 @@
;;
(def-package! helm-mode
:defer (pre-command-hook . 1)
:defer 1
:after-call pre-command-hook
:init
(map! :map global-map
[remap apropos] #'helm-apropos
[remap bookmark-jump] #'helm-bookmarks
[remap bookmark-jump] #'helm-bookmarks
[remap execute-extended-command] #'helm-M-x
[remap find-file] #'helm-find-files
[remap imenu-anywhere] #'helm-imenu-anywhere
[remap imenu-anywhere] #'helm-imenu-anywhere
[remap imenu] #'helm-semantic-or-imenu
[remap noop-show-kill-ring] #'helm-show-kill-ring
[remap projectile-find-file] #'helm-projectile-find-file
[remap projectile-recentf] #'helm-projectile-recentf
[remap projectile-switch-project] #'helm-projectile-switch-project
[remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer
[remap recentf-open-files] #'helm-recentf)
:config
(helm-mode +1)
;; helm is too heavy for find-file-at-point
@ -40,7 +57,6 @@
helm-move-to-line-cycle-in-source t)
:config
(load "helm-autoloads" nil t)
(setq projectile-completion-system 'helm)
(defvar helm-projectile-find-file-map (make-sparse-keymap))
@ -72,20 +88,7 @@
(setq-local cursor-type nil))))
(add-hook 'helm-minibuffer-set-up-hook #'+helm*hide-minibuffer-maybe)
(map! :map global-map
[remap apropos] #'helm-apropos
[remap find-file] #'helm-find-files
[remap recentf-open-files] #'helm-recentf
[remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer
[remap projectile-recentf] #'helm-projectile-recentf
[remap projectile-find-file] #'helm-projectile-find-file
[remap imenu] #'helm-semantic-or-imenu
[remap bookmark-jump] #'helm-bookmarks
[remap noop-show-kill-ring] #'helm-show-kill-ring
[remap projectile-switch-project] #'helm-projectile-switch-project
[remap projectile-find-file] #'helm-projectile-find-file
[remap imenu-anywhere] #'helm-imenu-anywhere
[remap execute-extended-command] #'helm-M-x))
)
(def-package! helm-locate
@ -94,40 +97,28 @@
:config (set-keymap-parent helm-generic-files-map helm-map))
(def-package! helm-bookmark
:commands helm-bookmark
:config (setq-default helm-bookmark-show-location t))
(after! helm-bookmark
(setq-default helm-bookmark-show-location t))
(def-package! helm-files
:defer t
:config
(after! helm-files
(setq helm-boring-file-regexp-list
(append (list "\\.projects$" "\\.DS_Store$")
helm-boring-file-regexp-list)))
(def-package! helm-ag
:defer t
:config
(map! :map helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort))
;; `helm-ag'
(map! :after helm-ag
:map helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort)
(def-package! helm-css-scss ; https://github.com/ShingoFukuyama/helm-css-scss
:commands (helm-css-scss
helm-css-scss-multi
helm-css-scss-insert-close-comment)
:config
(after! helm-css-scss ; https://github.com/ShingoFukuyama/helm-css-scss
(setq helm-css-scss-split-direction #'split-window-vertically
helm-css-scss-split-with-multiple-windows t))
(def-package! helm-for-files
:commands (helm-for-files helm-recentf helm-multi-files))
(def-package! helm-swoop ; https://github.com/ShingoFukuyama/helm-swoop
:commands (helm-swoop helm-multi-swoop helm-multi-swoop-all)
:commands helm-multi-swoop-all
:config
(setq helm-swoop-use-line-number-face t
helm-swoop-candidate-number-limit 200
@ -135,9 +126,6 @@
helm-swoop-pre-input-function (lambda () "")))
(def-package! helm-describe-modes :commands helm-describe-modes)
(def-package! wgrep
:commands (wgrep-setup wgrep-change-to-wgrep-mode)
:commands wgrep-change-to-wgrep-mode
:config (setq wgrep-auto-save-buffer t))

View file

@ -116,7 +116,7 @@ If ARG (universal argument), open selection in other-window."
"\\):?\\s-*\\(.+\\)")
x)
(error
(message! (red "Error matching task in file: (%s) %s"
(print! (red "Error matching task in file: (%s) %s"
(error-message-string ex)
(car (split-string x ":"))))
nil))
@ -202,7 +202,6 @@ search current file. See `+ivy-task-tags' to customize what this searches for."
;; File searching
;;
(defvar +ivy--file-last-search nil)
(defvar +ivy--file-search-recursion-p t)
(defvar +ivy--file-search-all-files-p nil)
@ -220,8 +219,7 @@ search current file. See `+ivy-task-tags' to customize what this searches for."
(let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning)))
(end (or (bound-and-true-p evil-visual-end) (region-end))))
(when (> (abs (- end beg)) 1)
(rxt-quote-pcre (buffer-substring-no-properties beg end)))))
+ivy--file-last-search))
(rxt-quote-pcre (buffer-substring-no-properties beg end)))))))
(prompt
(format "%s%%s %s"
(symbol-name engine)
@ -232,7 +230,6 @@ search current file. See `+ivy-task-tags' to customize what this searches for."
(t
(file-relative-name directory project-root)))))
(default-directory directory))
(setq +ivy--file-last-search query)
(require 'counsel)
(cl-letf (((symbol-function 'counsel-ag-function)
(symbol-function '+ivy*counsel-ag-function))

View file

@ -24,9 +24,10 @@ immediately runs it on the current candidate (ending the ivy session)."
;;
(def-package! ivy
:defer (pre-command-hook . 1)
:defer 1
:after-call pre-command-hook
:config
(setq ivy-height 12
(setq ivy-height 15
ivy-do-completion-in-region nil
ivy-wrap t
ivy-fixed-height-minibuffer t
@ -141,7 +142,7 @@ immediately runs it on the current candidate (ending the ivy session)."
"C-o" #'+ivy@coo/body
"M-o" #'ivy-dispatching-done-hydra)
:config
(def-hydra! +ivy@coo (:hint nil :color pink)
(defhydra +ivy@coo (:hint nil :color pink)
"
Move ^^^^^^^^^^ | Call ^^^^ | Cancel^^ | Options^^ | Action _w_/_s_/_a_: %s(ivy-action-name)
----------^^^^^^^^^^-+--------------^^^^-+-------^^-+--------^^-+---------------------------------
@ -184,7 +185,7 @@ immediately runs it on the current candidate (ending the ivy session)."
(def-package! wgrep
:commands (wgrep-setup wgrep-change-to-wgrep-mode)
:commands wgrep-change-to-wgrep-mode
:config (setq wgrep-auto-save-buffer t))

View file

@ -197,8 +197,10 @@
:desc "Magit status" :n "g" #'magit-status
:desc "List gists" :n "G" #'+gist:list
:desc "Initialize repo" :n "i" #'magit-init
:desc "Browse issues tracker" :n "I" #'+vcs/git-browse-issues
:desc "Magit buffer log" :n "l" #'magit-log-buffer-file
:desc "List repositories" :n "L" #'magit-list-repositories
:desc "Browse remote" :n "o" #'+vcs/git-browse
:desc "Magit push popup" :n "p" #'magit-push-popup
:desc "Magit pull popup" :n "P" #'magit-pull-popup
:desc "Git revert hunk" :n "r" #'git-gutter:revert-hunk
@ -213,9 +215,11 @@
(:desc "help" :prefix "h"
:n "h" help-map
:desc "Apropos" :n "a" #'apropos
:desc "Open Bug Report" :n "b" #'doom/open-bug-report
:desc "Describe char" :n "c" #'describe-char
:desc "Describe DOOM module" :n "d" #'doom/describe-module
:desc "Open Doom manual" :n "D" #'doom/help
:desc "Open Doom manual" :n "D" #'doom//open-manual
:desc "Open vanilla sandbox" :n "E" #'doom/open-vanilla-sandbox
:desc "Describe function" :n "f" #'describe-function
:desc "Describe face" :n "F" #'describe-face
:desc "Info" :n "i" #'info-lookup-symbol
@ -233,7 +237,7 @@
:desc "Print Doom version" :n "V" #'doom/version
:desc "Describe at point" :n "." #'helpful-at-point
:desc "What face" :n "'" #'doom/what-face
:desc "What minor modes" :n ";" #'doom/what-minor-mode)
:desc "What minor modes" :n ";" #'doom/describe-active-minor-mode)
(:desc "insert" :prefix "i"
:desc "From kill-ring" :nv "y" #'counsel-yank-pop
@ -251,7 +255,7 @@
:desc "REPL" :n "r" #'+eval/open-repl
:v "r" #'+eval:repl
:desc "Neotree" :n "n" #'+neotree/open
:desc "Neotree: on this file" :n "N" #'+neotree/find-this-file
:desc "Neotree: find file" :n "N" #'+neotree/find-this-file
:desc "Imenu sidebar" :nv "i" #'imenu-list-smart-toggle
:desc "Terminal" :n "t" #'+term/open-popup-in-project
@ -295,11 +299,13 @@
:desc "Browse remote files" :n "." #'ssh-deploy-browse-remote-handler
:desc "Detect remote changes" :n ">" #'ssh-deploy-remote-changes-handler))
(:when (featurep! :feature snippets)
(:desc "snippets" :prefix "s"
:desc "New snippet" :n "n" #'yas-new-snippet
:desc "Insert snippet" :nv "i" #'yas-insert-snippet
:desc "Find snippet for mode" :n "s" #'yas-visit-snippet-file
:desc "Find snippet" :n "S" #'+default/find-in-snippets)
:desc "Find snippet" :n "s" #'+default/find-in-snippets
:desc "Find snippet for mode" :n "S" #'+default/browse-snippets
:desc "Find global snippet" :n "/" #'yas-visit-snippet-file))
(:desc "toggle" :prefix "t"
:desc "Flyspell" :n "s" #'flyspell-mode
@ -387,11 +393,12 @@
[escape] #'company-search-abort))
;; counsel
(:when (featurep! :completion ivy)
(:after counsel
(:map counsel-ag-map
[backtab] #'+ivy/wgrep-occur ; search/replace on results
"C-SPC" #'ivy-call-and-recenter ; preview
"M-RET" (+ivy-do-action! #'+ivy-git-grep-other-window-action)))
"M-RET" (+ivy-do-action! #'+ivy-git-grep-other-window-action))))
;; easymotion
:m "gs" #'+default/easymotion ; lazy-load `evil-easymotion'
@ -766,14 +773,16 @@
;; Evil-collection fixes
;;
(when (featurep 'evil-collection)
(defun +config|deal-with-evil-collections-bs (_feature keymaps)
"Unmap keys that conflict with Doom's defaults."
(dolist (map keymaps)
(evil-define-key '(normal visual motion) map
doom-leader-key nil
"C-j" nil "C-k" nil
"gd" nil "gf" nil
"K" nil
"]" nil "[" nil)))
(add-hook 'evil-collection-setup-hook #'+config|deal-with-evil-collections-bs))
(evil-delay `(and (boundp ',map) (keymapp ,map))
`(evil-define-key* '(normal visual motion) ,map
(kbd doom-leader-key) nil
(kbd "C-j") nil (kbd "C-k") nil
"gd" nil "gf" nil "K" nil
"]" nil "[" nil)
'after-load-functions t nil
(format "+default-redefine-key-in-%s" map))))
(add-hook 'evil-collection-setup-hook #'+config|deal-with-evil-collections-bs)

View file

@ -36,8 +36,10 @@
;;;###autoload
(defun +default/browse-snippets ()
(interactive) (doom-project-browse emacs-snippets-dir))
;; NOTE No need for a browse-snippets variant, use `yas-visit-snippet-file'
(interactive) (doom-project-browse +snippets-dir))
;;;###autoload
(defun +default/find-in-snippets ()
(interactive) (doom-project-find-file +snippets-dir))
;;;###autoload
(defun +default/find-in-config ()

View file

@ -35,6 +35,15 @@
(sp-pair "'" nil :unless unless-list)
(sp-pair "\"" nil :unless unless-list))
;; Major-mode specific fixes
(sp-local-pair 'ruby-mode "{" "}"
:pre-handlers '(:rem sp-ruby-prehandler)
:post-handlers '(:rem sp-ruby-posthandler))
;; sp's default rules for these modes are obnoxious, so disable them
(provide 'smartparens-latex)
(provide 'smartparens-elixir)
(provide 'smartparens-lua)
;; Expand {|} => { | }
;; Expand {|} => {
;; |

View file

@ -3,7 +3,8 @@
(def-package! realgud
:commands (realgud:gdb realgud:trepanjs realgud:bashdb realgud:zshdb)
:config
(set! :popup "^\\*\\(?trepanjs:\\(?:g\\|zsh\\|bash\\)db\\)" '((size . 20)))
(set! :popup "^\\*\\(?trepanjs:\\(?:g\\|zsh\\|bash\\)db\\)"
'((size . 20)))
;; TODO Temporary Ex commands for the debugger
;; (def-tmp-excmd! doom:def-debug-on doom:def-debug-off

View file

@ -10,12 +10,7 @@
;;
(def-package! quickrun
:commands (quickrun
quickrun-region
quickrun-with-arg
quickrun-shell
quickrun-compile-only
quickrun-replace-region)
:defer t
:init
(unless (boundp 'display-line-numbers)
(add-hook 'quickrun--mode-hook #'nlinum-mode))

View file

@ -1,6 +1,21 @@
;; feature/evil/autoload/evil.el -*- lexical-binding: t; -*-
;;;###if (featurep! :feature evil)
;;;###autoload
(def-setting! :evil-state (modes state)
"Set the initialize STATE of MODE using `evil-set-initial-state'."
(let ((unquoted-modes (doom-unquote modes)))
(if (listp unquoted-modes)
`(progn
,@(cl-loop for mode in unquoted-modes
collect `(evil-set-initial-state ',mode ,state)))
`(evil-set-initial-state ,modes ,state))))
;;
;; Commands
;;
;;;###autoload
(defun +evil/visual-indent ()
"vnoremap < <gv"
@ -80,6 +95,11 @@ evil-window-move-* (e.g. `evil-window-move-far-left')"
;;;###autoload
(defun +evil/window-move-down () "See `+evil--window-swap'" (interactive) (+evil--window-swap 'down))
;;
;; Evil commands/operators
;;
;;;###autoload (autoload '+evil:apply-macro "feature/evil/autoload/evil" nil t)
(evil-define-operator +evil:apply-macro (beg end)
"Apply macro to each line."

View file

@ -3,27 +3,10 @@
;; I'm a vimmer at heart. Its modal philosophy suits me better, and this module
;; strives to make Emacs a much better vim than vim was.
(def-setting! :evil-state (modes state)
"Set the initialize STATE of MODE using `evil-set-initial-state'."
(let ((unquoted-modes (doom-unquote modes)))
(if (listp unquoted-modes)
`(progn
,@(cl-loop for mode in unquoted-modes
collect `(evil-set-initial-state ',mode ,state)))
`(evil-set-initial-state ,modes ,state))))
;;
;; evil-mode
;;
(autoload 'goto-last-change "goto-chg")
(autoload 'goto-last-change-reverse "goto-chg")
(def-package! evil-collection
:when (featurep! +everywhere)
:defer pre-command-hook
:defer 1
:after-call post-command-hook
:preface
;; must be set before evil/evil-collcetion is loaded
(setq evil-want-integration nil
@ -61,7 +44,7 @@
evil-visual-state-cursor 'hollow)
:config
(add-hook 'doom-init-hook #'evil-mode)
(add-hook 'doom-post-init-hook #'evil-mode)
(evil-select-search-module 'evil-search-module 'evil-search)
(set! :popup "^\\*evil-registers" '((size . 0.3)))
@ -235,7 +218,7 @@
evil-escape-excluded-major-modes '(neotree-mode)
evil-escape-key-sequence "jk"
evil-escape-delay 0.25)
(add-hook 'pre-command-hook 'evil-escape-pre-command-hook)
(add-hook 'pre-command-hook #'evil-escape-pre-command-hook)
(map! :irvo "C-g" #'evil-escape)
:config
;; no `evil-escape' in minibuffer
@ -325,7 +308,7 @@ the new algorithm is confusing, like in python or ruby."
(def-package! evil-snipe
:commands (evil-snipe-mode evil-snipe-override-mode
evil-snipe-local-mode evil-snipe-override-local-mode)
:defer pre-command-hook
:after-call pre-command-hook
:init
(setq evil-snipe-smart-case t
evil-snipe-scope 'line
@ -385,19 +368,6 @@ the new algorithm is confusing, like in python or ruby."
(push ">" evil-args-closers)))
(def-package! evil-indent-plus
:commands (evil-indent-plus-i-indent
evil-indent-plus-a-indent
evil-indent-plus-i-indent-up
evil-indent-plus-a-indent-up
evil-indent-plus-i-indent-up-down
evil-indent-plus-a-indent-up-down))
(def-package! evil-textobj-anyblock
:commands (evil-textobj-anyblock-inner-block evil-textobj-anyblock-a-block))
;;
;; Multiple cursors compatibility (for the plugins that use it)
;;

View file

@ -66,8 +66,12 @@ evil is loaded and enabled)."
;;;###autoload
(defun +file-templates-get-short-path ()
"Fetches a short file path for the header in Doom module templates."
(when (string-match "/modules/\\(.+\\)$" buffer-file-truename)
(match-string 1 buffer-file-truename)))
(let ((path (file-truename (or buffer-file-name default-directory))))
(cond ((string-match "/modules/\\(.+\\)$" path)
(match-string 1 path))
((file-in-directory-p path doom-emacs-dir)
(file-relative-name path doom-emacs-dir))
((abbreviate-file-name path)))))
;;

View file

@ -6,55 +6,11 @@
(expand-file-name "templates/" (file-name-directory load-file-name))
"The path to a directory of yasnippet folders to use for file templates.")
(defvar +file-templates-alist ()
"An alist of file template rules. The CAR of each rule is either a major mode
symbol or regexp string. The CDR is a plist. See `doom--set:file-template' for
more information.")
(defvar +file-templates-default-trigger "__"
"The default yasnippet trigger key (a string) for file template rules that
don't have a :trigger property in `+file-templates-alist'.")
;;
;; Bootstrap
;;
(after! yasnippet
(add-to-list 'yas-snippet-dirs '+file-templates-dir 'append #'eq))
(defun +file-template-p (rule)
"Return t if RULE applies to the current buffer."
(let ((pred (car rule))
(plist (cdr rule)))
(and (cond ((stringp pred) (string-match-p pred))
((symbolp pred) (eq major-mode pred)))
(or (not (plist-member plist :when))
(funcall (plist-get plist :when) buffer-file-name))
rule)))
(defun +file-templates|init ()
"Check if the current buffer is a candidate for file template expansion. It
must be non-read-only, empty, and there must be a rule in
`+file-templates-alist' that applies to it."
(when (and (not buffer-read-only)
(bobp) (eobp))
(when-let* ((rule (cl-find-if #'+file-template-p +file-templates-alist)))
(apply #'+file-templates--expand rule))))
(add-hook 'find-file-hook #'+file-templates|init)
;;
;; File templates
;;
(defun +file-templates-in-emacs-dirs-p (file)
"Returns t if FILE is in Doom or your private directory."
(or (file-in-directory-p file doom-private-dir)
(file-in-directory-p file doom-emacs-dir)))
(setq +file-templates-alist
(defvar +file-templates-alist
`(;; General
(gitignore-mode)
(dockerfile-mode)
@ -137,11 +93,50 @@ must be non-read-only, empty, and there must be a rule in
;; Shell scripts
("\\.zunit$" :trigger "__zunit" :mode sh-mode)
(fish-mode)
(sh-mode)
))
(sh-mode))
"An alist of file template rules. The CAR of each rule is either a major mode
symbol or regexp string. The CDR is a plist. See `doom--set:file-template' for
more information.")
;;
;; Plugins
;; Library
;;
(defun +file-template-p (rule)
"Return t if RULE applies to the current buffer."
(let ((pred (car rule))
(plist (cdr rule)))
(and (cond ((and (stringp pred) buffer-file-name) (string-match-p pred buffer-file-name))
((symbolp pred) (eq major-mode pred)))
(or (not (plist-member plist :when))
(funcall (plist-get plist :when) buffer-file-name))
rule)))
(defun +file-templates-in-emacs-dirs-p (file)
"Returns t if FILE is in Doom or your private directory."
(or (file-in-directory-p file doom-private-dir)
(file-in-directory-p file doom-emacs-dir)))
(defun +file-templates|check ()
"Check if the current buffer is a candidate for file template expansion. It
must be non-read-only, empty, and there must be a rule in
`+file-templates-alist' that applies to it."
(when (and (not buffer-read-only)
(bobp) (eobp)
(not (string-match-p "^ *\\*" (buffer-name))))
(when-let* ((rule (cl-find-if #'+file-template-p +file-templates-alist)))
(apply #'+file-templates--expand rule))))
;;
;; Bootstrap
;;
(defun +file-templates|init ()
(after! yasnippet
(add-to-list 'yas-snippet-dirs '+file-templates-dir 'append #'eq))
(add-hook 'find-file-hook #'+file-templates|check))
(add-hook 'doom-post-init-hook #'+file-templates|init)

View file

@ -11,10 +11,9 @@ ${2:A short summary about what this module does.}
${3:If necessary, include a longer description below it that goes into more detail. This may be as long as you like.
+ If possible, include a list of features
+ Include links to major plugins that the module uses, if applicable
+ Use links whenever you can
+ Mention dependencies on other modules here}
+ If possible, include a brief list of feature highlights here
+ Like code completion, syntax checking or available snippets
+ Include links to packages & external things where possible
* Table of Contents :TOC:
@ -25,11 +24,15 @@ This module provides no flags.
This module has no prereqisites.
* Features
A list of features, how to use them, and their dependencies.
An in-depth list of features, how to use them, and their dependencies.
* Configuration
How to configure this module, including common problems and how to address them.
* Appendix
** Commands
+ A list or table of public commands (and their keybinds) and functions that this module exposes.
+ A brief description of how to use them
** Hacks
+ Include a list of ways this module changes default behavior
$0

View file

@ -0,0 +1,11 @@
;;; feature/lookup/autoload/devdocs.el -*- lexical-binding: t; -*-
;;;###if (featurep! +devdocs)
;;;###autoload
(def-setting! :devdocs (modes docset)
"Map major MODES (one major-mode symbol or a list of them) to a devdocs
DOCSET (a string).
See `devdocs-alist' for the defaults. "
`(dolist (mode ',modes)
(push (cons mode ,docset) devdocs-alist)))

View file

@ -0,0 +1,40 @@
;;; feature/lookup/autoload/docsets.el -*- lexical-binding: t; -*-
;;;###if (featurep! +docsets)
;;;###autoload
(def-setting! :docset (modes &rest docsets)
"Registers a list of DOCSETS (strings) for MODES (either one major mode
symbol or a list of them).
If MODES is a minor mode, you can use :add or :remove as the first element of
DOCSETS, to instruct it to append (or remove) those from the docsets already set
by a major-mode, if any.
Used by `+lookup/in-docsets' and `+lookup/documentation'."
(let* ((modes (doom-unquote modes))
(ivy-p (featurep! :completion ivy))
(hook-sym (intern (format "+lookup|%s-docsets--%s"
(cond ((eq ',(car docsets) :add) 'add)
((eq ',(car docsets) :remove) 'remove)
('set))
(string-join docsets "-"))))
(var-sym (if ivy-p 'counsel-dash-docsets 'helm-dash-docsets)))
`(progn
(defun ,hook-sym ()
(make-variable-buffer-local ',var-sym)
,(cond ((eq ',(car docsets) :add)
`(setq ,var-sym (append ,var-sym (list ,@(cdr docsets)))))
((eq ',(car docsets) :remove)
`(setq ,var-sym
(cl-loop with to-delete = (list ,@(cdr docsets))
for docset in ,var-sym
unless (member docset to-delete)
collect docset)))
(`(setq ,var-sym (list ,@docsets)))))
(add-hook! ,modes #',hook-sym))))
;;;###autoload
(autoload 'helm-dash-installed-docsets "helm-dash")
;;;###autoload
(autoload 'helm-dash-docset-installed-p "helm-dash")

View file

@ -160,6 +160,7 @@ Goes down a list of possible backends:
identifier
(+lookup--online-provider (not current-prefix-arg))))))
(defvar ffap-file-finder)
;;;###autoload
(defun +lookup/file (path)
"Figure out PATH from whatever is at point and open it.

View file

@ -122,33 +122,29 @@ ones."
;;
(def-package! dumb-jump
:commands (dumb-jump-go dumb-jump-quick-look
dumb-jump-back dumb-jump-result-follow)
:commands dumb-jump-result-follow
:config
(setq dumb-jump-default-project doom-emacs-dir
dumb-jump-aggressive nil
dumb-jump-selector
(cond ((featurep! :completion ivy) 'ivy)
((featurep! :completion helm) 'helm)
(t 'popup))))
('popup))))
;;
;; xref
;;
(def-package! xref
:commands (xref-backend-identifier-at-point xref-find-definitions xref-find-references)
:config
;; By default, `etags--xref-backend' is the default xref backend. No need.
;; We'll set these up ourselves in other modules.
;; By default, `etags--xref-backend' is the default xref backend. No need. We'll
;; set these up ourselves in other modules.
(setq-default xref-backend-functions '(t))
;; ...however, it breaks `projectile-find-tag', unless we put it back.
(defun +lookup*projectile-find-tag (orig-fn)
(let ((xref-backend-functions '(etags--xref-backend t)))
(funcall orig-fn)))
(advice-add #'projectile-find-tag :around #'+lookup*projectile-find-tag))
(advice-add #'projectile-find-tag :around #'+lookup*projectile-find-tag)
(def-package! ivy-xref
@ -168,41 +164,9 @@ ones."
;;
(when (featurep! +docsets)
(def-setting! :docset (modes &rest docsets)
"Registers a list of DOCSETS (strings) for MODES (either one major mode
symbol or a list of them).
If MODES is a minor mode, you can use :add or :remove as the first element of
DOCSETS, to instruct it to append (or remove) those from the docsets already set
by a major-mode, if any.
Used by `+lookup/in-docsets' and `+lookup/documentation'."
(let* ((modes (doom-unquote modes))
(ivy-p (featurep! :completion ivy))
(hook-sym (intern (format "+lookup|%s-docsets--%s"
(cond ((eq ',(car docsets) :add) 'add)
((eq ',(car docsets) :remove) 'remove)
('set))
(string-join docsets "-"))))
(var-sym (if ivy-p 'counsel-dash-docsets 'helm-dash-docsets)))
`(progn
(defun ,hook-sym ()
(make-variable-buffer-local ',var-sym)
,(cond ((eq ',(car docsets) :add)
`(setq ,var-sym (append ,var-sym (list ,@(cdr docsets)))))
((eq ',(car docsets) :remove)
`(setq ,var-sym
(cl-loop with to-delete = (list ,@(cdr docsets))
for docset in ,var-sym
unless (member docset to-delete)
collect docset)))
(`(setq ,var-sym (list ,@docsets)))))
(add-hook! ,modes #',hook-sym))))
;; Both packages depend on helm-dash
(def-package! helm-dash
:commands (helm-dash helm-dash-install-docset helm-dash-at-point
helm-dash-docset-installed-p helm-dash-installed-docsets)
:defer t
:init
(setq helm-dash-enable-debugging doom-debug-mode
helm-dash-browser-func #'eww)
@ -214,7 +178,7 @@ Used by `+lookup/in-docsets' and `+lookup/documentation'."
(def-package! counsel-dash
:when (featurep! :completion ivy)
:commands (counsel-dash counsel-dash-install-docset)
:commands counsel-dash-install-docset
:config (setq counsel-dash-min-length 2)))
@ -223,20 +187,11 @@ Used by `+lookup/in-docsets' and `+lookup/documentation'."
;;
(when (featurep! +devdocs)
(def-setting! :devdocs (modes docset)
"Map major MODES (one major-mode symbol or a list of them) to a devdocs
DOCSET (a string).
See `devdocs-alist' for the defaults. "
`(dolist (mode ',modes)
(push (cons mode ,docset) devdocs-alist)))
(def-package! devdocs-lookup
:commands (devdocs-setup devdocs-lookup)
:config
(after! devdocs-lookup
(unless (assoc "SCSS" devdocs-subjects)
(setq devdocs-subjects
(append '(("SCSS" "scss")
("GFM" "markdown")
("Typescript" "typescript"))
devdocs-subjects))))
devdocs-subjects)))))

View file

@ -1,9 +1,16 @@
;;; feature/snippets/config.el -*- lexical-binding: t; -*-
(defvar +snippets-dir (expand-file-name "snippets/" doom-private-dir)
"Directory where `yasnippet' will search for your private snippets.")
;;
;; Plugins
;;
(def-package! yasnippet
:commands (yas-minor-mode yas-minor-mode-on yas-expand yas-expand-snippet
yas-lookup-snippet yas-insert-snippet yas-new-snippet
yas-visit-snippet-file snippet-mode)
:commands (yas-minor-mode-on yas-expand yas-expand-snippet yas-lookup-snippet
yas-insert-snippet yas-new-snippet yas-visit-snippet-file)
:preface
(defvar yas-minor-mode-map
(let ((map (make-sparse-keymap)))
@ -23,28 +30,25 @@
(setq yas-verbosity (if doom-debug-mode 3 0)
yas-also-auto-indent-first-line t
yas-prompt-functions (delq #'yas-dropdown-prompt yas-prompt-functions)
;; Allow nested snippets
yas-triggers-in-field t)
yas-triggers-in-field t) ; Allow nested snippets
(cl-pushnew (expand-file-name "snippets/" doom-private-dir) yas-snippet-dirs
:test #'string=)
(add-to-list 'yas-snippet-dirs '+snippets-dir nil #'eq)
(defun +snippets|enable-project-modes (mode &rest _)
"Enable snippets for project modes."
"Automatically enable snippet libraries for project minor modes defined with
`def-project-mode!'."
(if (symbol-value mode)
(yas-activate-extra-mode mode)
(yas-deactivate-extra-mode mode)))
(add-hook 'doom-project-hook #'+snippets|enable-project-modes)
;; fix an error caused by smartparens interfering with yasnippet bindings
(advice-add #'yas-expand :before #'sp-remove-active-pair-overlay)
;; Exit snippets on ESC from normal mode
(add-hook 'doom-escape-hook #'yas-abort-snippet))
(add-hook 'doom-escape-hook #'yas-abort-snippet)
(after! smartparens
;; fix an error caused by smartparens interfering with yasnippet bindings
(advice-add #'yas-expand :before #'sp-remove-active-pair-overlay)))
(def-package! auto-yasnippet
:commands (aya-create aya-expand aya-open-line aya-persist-snippet)
:config
(after! auto-yasnippet
(setq aya-persist-snippets-dir (concat doom-local-dir "auto-snippets/")))

View file

@ -1,7 +0,0 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; feature/snippets/doctor.el
(require 'yasnippet)
(unless (ignore-errors (yas-reload-all)
(yas--get-snippet-tables))
(warn! "Couldn't find any snippets in any of these directories: %s" yas-snippet-dirs))

View file

@ -8,7 +8,7 @@ Since spellchecking can be slow in some buffers, this can be disabled with:
(setq-hook! 'LaTeX-mode-hook +spellcheck-immediately nil)")
(def-package! flyspell ; built-in
:commands flyspell-mode
:defer t
:init
(add-hook 'flyspell-mode-hook #'+spellcheck|immediately)
:config

View file

@ -1,11 +1,11 @@
;; -*- no-byte-compile: t; -*-
;;; feature/spellcheck/packages.el
(package! flyspell-correct)
(when (package! flyspell-correct)
(cond ((featurep! :completion ivy)
(package! flyspell-correct-ivy))
((featurep! :completion helm)
(package! flyspell-correct-helm))
(t
(package! flyspell-correct-popup)))
(package! flyspell-correct-popup))))

View file

@ -1,18 +1,11 @@
;;; feature/syntax-checker/config.el -*- lexical-binding: t; -*-
;; Since Doom doesn't use `package-initialize', pkg-info won't get autoloaded
;; when `flycheck-version' needs it, so we need this:
(autoload 'pkg-info-version-info "pkg-info")
(def-package! flycheck
:commands (flycheck-mode flycheck-list-errors flycheck-buffer)
:commands (flycheck-list-errors flycheck-buffer)
:config
;; Emacs feels snappier without checks on newline
(setq flycheck-check-syntax-automatically '(save idle-change mode-enabled))
;; Popup
(add-hook 'flycheck-mode-hook #'+syntax-checker-popup-mode)
(after! evil
(defun +syntax-checkers|flycheck-buffer ()
"Flycheck buffer on ESC in normal mode."
@ -20,21 +13,16 @@
(ignore-errors (flycheck-buffer))
nil))
(add-hook 'doom-escape-hook #'+syntax-checkers|flycheck-buffer t)
(add-hook 'evil-insert-state-exit-hook #'+syntax-checkers|flycheck-buffer)
;; With the option of flychecking the buffer on escape or leaving insert
;; mode, we don't need auto-flychecking on idle-change (which can feel slow,
;; esp on computers without SSDs).
(delq 'idle-change flycheck-check-syntax-automatically)))
(add-hook 'evil-insert-state-exit-hook #'+syntax-checkers|flycheck-buffer)))
(def-package! flycheck-popup-tip
:commands (flycheck-popup-tip-show-popup flycheck-popup-tip-delete-popup))
:commands (flycheck-popup-tip-show-popup flycheck-popup-tip-delete-popup)
:init (add-hook 'flycheck-mode-hook #'+syntax-checker-popup-mode))
(def-package! flycheck-posframe
:when EMACS26+
:when (featurep! +childframe)
:when (and EMACS26+ (featurep! +childframe))
:commands flycheck-posframe-show-posframe
:config
(setq flycheck-posframe-warning-prefix ""

View file

@ -1,10 +1,5 @@
;;; feature/version-control/+git.el -*- lexical-binding: t; -*-
;; These don't need `def-package!' blocks because they've already been set up by
;; `doom-initialize'.
(autoload 'gitconfig-mode "gitconfig-mode" nil t)
(autoload 'gitignore-mode "gitignore-mode" nil t)
(when (featurep! :feature evil)
(add-hook 'git-commit-mode-hook #'evil-insert-state))
@ -33,7 +28,7 @@
(ignore (git-gutter))))
(add-hook 'doom-escape-hook #'+version-control|update-git-gutter t))
(def-hydra! +version-control@git-gutter
(defhydra +version-control@git-gutter
(:body-pre (git-gutter-mode 1) :hint nil)
"
@ -59,7 +54,7 @@
(def-package! git-timemachine
:commands (git-timemachine git-timemachine-toggle)
:defer t
:config
;; Sometimes I forget `git-timemachine' is enabled in a buffer, so instead of
;; showing revision details in the minibuffer, show them in
@ -67,10 +62,6 @@
(setq git-timemachine-show-minibuffer-details t)
(advice-add #'git-timemachine--show-minibuffer-details :override #'+vcs*update-header-line)
(after! evil
;; Force evil to rehash keybindings for the current state
(add-hook 'git-timemachine-mode-hook #'evil-force-normal-state))
(def-package! git-link
:commands (git-link git-link-commit git-link-homepage))
(add-hook 'git-timemachine-mode-hook #'evil-force-normal-state)))

View file

@ -28,7 +28,7 @@
(defalias #'smerge-diff-upper-lower #'smerge-diff-mine-other)
(defalias #'smerge-diff-base-lower #'smerge-diff-base-other)))
(def-hydra! +hydra-smerge (:hint nil
(defhydra +hydra-smerge (:hint nil
:pre (smerge-mode 1)
;; Disable `smerge-mode' when quitting hydra if
;; no merge conflicts remain.

View file

@ -211,7 +211,7 @@ current workspace (by name) from session files."
(completing-read
"Workspace to load: "
(persp-list-persp-names-in-file
(expand-file-name +workspace-data-file persp-save-dir))))))
(expand-file-name +workspaces-data-file persp-save-dir))))))
(if (not (+workspace-load name))
(+workspace-error (format "Couldn't load workspace %s" name))
(+workspace/switch-to name)

View file

@ -27,7 +27,7 @@ new project directory.")
stored in `persp-save-dir'.")
(defun +workspaces-restore-last-session (&rest _)
(add-hook 'emacs-startup-hook #'+workspace/load-session 'append))
(add-hook 'doom-post-init-hook #'+workspace/load-session 'append))
(map-put command-switch-alist '"--restore" #'+workspaces-restore-last-session)
@ -77,7 +77,7 @@ Uses `+workspaces-main' to determine the name of the main workspace."
(display-buffer-in-side-window
warnings '((window-height . shrink-window-if-larger-than-buffer))))))))))
(add-hook 'doom-init-hook #'+workspaces|init t)
(add-hook 'doom-post-init-hook #'+workspaces|init t)
:config
(setq persp-autokill-buffer-on-remove 'kill-weak
persp-nil-hidden t

View file

@ -2,6 +2,7 @@
;;; feature/workspaces/test/autoload-workspaces.el
(require! :feature workspaces)
(doom|init-custom-hooks)
(defmacro with-workspace!! (buffer-args &rest body)
(declare (indent defun))
@ -13,7 +14,8 @@
(require 'persp-mode)
(let (noninteractive)
(persp-mode +1))
(+workspace-switch +workspaces-main t)
(let (persp-before-switch-functions persp-activated-functions)
(+workspace-switch +workspaces-main t))
(let* (,@buffers)
(cl-loop with persp = (get-current-persp)
for buf in (list ,@(mapcar #'car buffers))

View file

@ -0,0 +1,4 @@
;;; lang/assembly/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(map-put auto-mode-alist "\\.hax\\'" 'haxor-mode)

View file

@ -1,8 +0,0 @@
;;; lang/assembly/config.el -*- lexical-binding: t; -*-
(def-package! mips-mode :mode "\\.mips$")
(def-package! haxor-mode :mode "\\.hax$")
(def-package! nasm-mode :commands nasm-mode)

View file

@ -6,7 +6,7 @@
(interactive)
(unless (memq major-mode '(c-mode c++-mode objc-mode))
(user-error "Not a C/C++/ObjC buffer"))
(unless (doom-project-has! "compile_commands.json")
(unless (project-file-exists-p! "compile_commands.json")
(user-error "No compile_commands.json file"))
;; first rtag
(when (and (featurep 'rtags)
@ -89,13 +89,6 @@ compilation dbs."
nconc (list "-I" path)))
(doom-project-root)))))
;;;###autoload
(defun +cc|init-rtags ()
"Start an rtags server in c-mode and c++-mode buffers."
(when (and (memq major-mode '(c-mode c++-mode))
(rtags-executable-find "rtags"))
(rtags-start-process-unless-running)))
;;;###autoload
(defun +cc|cleanup-rtags ()
"Kill rtags server(s) if there are no C/C++ buffers open."

View file

@ -101,8 +101,8 @@ compilation database is present in the project.")
(label . 0))))
;;; Keybindings
;; Completely disable electric keys because it interferes with smartparens and
;; custom bindings. We'll do this ourselves.
;; Disable electric keys because it interferes with smartparens and custom
;; bindings. We'll do it ourselves (mostly).
(setq c-tab-always-indent nil
c-electric-flag nil)
(dolist (key '("#" "}" "/" "*" ";" "," ":" "(" ")" "\177"))
@ -129,6 +129,7 @@ compilation database is present in the project.")
(def-package! irony
:when (featurep! +irony)
:commands (irony-install-server irony-mode)
:preface
(setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
@ -172,23 +173,13 @@ compilation database is present in the project.")
;;
(def-package! cmake-mode
:mode "/CMakeLists\\.txt$"
:mode "\\.cmake\\$"
:defer t
:config
(set! :company-backend 'cmake-mode '(company-cmake company-yasnippet)))
(def-package! cuda-mode :mode "\\.cuh?$")
(def-package! opencl-mode :mode "\\.cl\\'")
(def-package! opencl-mode :mode "\\.cl$")
(def-package! demangle-mode
:hook llvm-mode)
(def-package! glsl-mode
:mode "\\.glsl$"
:mode "\\.vert$"
:mode "\\.frag$"
:mode "\\.geom$")
(def-package! demangle-mode :hook llvm-mode)
;;
@ -213,7 +204,12 @@ compilation database is present in the project.")
(def-package! rtags
:commands rtags-executable-find
:init
(add-hook! (c-mode c++-mode) #'+cc|init-rtags)
(defun +cc|init-rtags ()
"Start an rtags server in c-mode and c++-mode buffers."
(when (and (memq major-mode '(c-mode c++-mode))
(rtags-executable-find "rtags"))
(rtags-start-process-unless-running)))
(add-hook 'c-mode-common-hook #'+cc|init-rtags)
:config
(setq rtags-autostart-diagnostics t
rtags-use-bookmarks nil

View file

@ -7,9 +7,9 @@
(warn! "Couldn't find the rtag client and/or server programs %s. Disabling rtags support" bins)))
;; irony server
(require 'irony)
(when (require 'irony nil t)
(unless (file-directory-p irony-server-install-prefix)
(warn! "Irony server isn't installed. Run M-x irony-install-server"))
(warn! "Irony server isn't installed. Run M-x irony-install-server")))
(when (featurep! :completion company)
;; glslangValidator

View file

@ -1,13 +1,7 @@
;;; lang/clojure/config.el -*- lexical-binding: t; -*-
(def-package! clojure-mode
:mode "\\.clj$"
:mode "\\.edn$"
:mode "\\(?:build\\|profile\\)\\.boot$"
:mode ("\\.cljs$" . clojurescript-mode)
:mode ("\\.cljc$" . clojurec-mode)
:config
(add-hook 'clojure-mode #'rainbow-delimiters-mode))
;; `clojure-mode'
(add-hook 'clojure-mode #'rainbow-delimiters-mode)
(def-package! clj-refactor

View file

@ -1,8 +1,7 @@
;;; lang/crystal/config.el -*- lexical-binding: t; -*-
(def-package! crystal-mode
:mode "\\.cr$"
:interpreter "crystal"
:defer t
:config
(set! :lookup 'crystal-mode
:definition #'crystal-def-jump
@ -19,5 +18,4 @@
:config (add-hook 'crystal-mode-hook #'flycheck-mode))
(def-package! inf-crystal
:commands (inf-crystal crystal-switch-to-inf))
(def-package! inf-crystal :commands crystal-switch-to-inf)

View file

@ -1,17 +1,16 @@
;;; lang/csharp/config.el -*- lexical-binding: t; -*-
(def-package! csharp-mode :mode "\\.cs$")
(def-package! shader-mode :mode "\\.shader$") ; unity shaders
(add-to-list 'auto-mode-alist '("\\.shader$" . shader-mode)) ; unity shaders
(def-package! omnisharp
:after csharp-mode
:hook (csharp-mode . omnisharp-mode)
:commands omnisharp-install-server
:preface
(setq omnisharp-auto-complete-want-documentation nil
omnisharp-cache-directory (concat doom-cache-dir "omnisharp"))
:config
(add-hook! csharp-mode #'(flycheck-mode omnisharp-mode))
(add-hook 'csharp-mode-hook #'flycheck-mode)
(defun +csharp|cleanup-omnisharp-server ()
"Clean up the omnisharp server once you kill the last csharp-mode buffer."

View file

@ -1,47 +1,41 @@
;;; lang/data/config.el -*- lexical-binding: t; -*-
(push '("/sxhkdrc" . conf-mode) auto-mode-alist)
;; Built in plugins
(dolist (spec '(("/sxhkdrc\\'" . conf-mode)
("\\.\\(?:hex\\|nes\\)\\'" . hexl-mode)
("\\.plist\\'" . nxml-mode)))
(map-put auto-mode-alist (car spec) (cdr spec)))
(set! :company-backend 'nxml-mode '(company-nxml company-yasnippet))
(def-package! dockerfile-mode
:mode "/Dockerfile$")
;;
;; Third-party plugins
;;
;; `csv-mode'
(map! :after csv-mode
:map csv-mode-map
(:localleader
:desc "Align fields" :nvm "a" #'csv-align-fields
:desc "Unalign fields" :nvm "u" #'csv-unalign-fields
:desc "Sort fields" :nvm "s" #'csv-sort-fields
:desc "Sort fields (n)" :nvm "S" #'csv-sort-numeric-fields
:desc "Kill fields" :nvm "k" #'csv-kill-fields
:desc "Transpose fields" :nvm "t" #'csv-transpose))
(def-package! graphql-mode
:mode "\\.g\\(?:raph\\)?ql$")
(def-package! hexl ; For ROM hacking or debugging
:mode ("\\.hex$" . hexl-mode)
:mode ("\\.nes$" . hexl-mode))
:mode "\\.gql\\'")
(def-package! json-mode
:mode "\\.js\\(?:on\\|[hl]int\\(rc\\)?\\)$"
:mode "\\.js\\(?:on\\|[hl]int\\(rc\\)?\\)\\'"
:config
(when (featurep! :feature syntax-checker)
(add-hook 'json-mode-hook #'flycheck-mode))
(set! :electric 'json-mode :chars '(?\n ?: ?{ ?})))
(def-package! nxml-mode
:mode "\\.plist$"
:config
(set! :company-backend 'nxml-mode '(company-nxml company-yasnippet)))
(def-package! toml-mode
:mode "\\.toml$")
(def-package! vimrc-mode
:mode "/\\.?g?vimrc$"
:mode "\\.vimp?$"
:mode "\\.?vimperatorrc$")
(def-package! yaml-mode
:mode "\\.ya?ml$")
:mode "\\.?vimperatorrc\\'")
;;

View file

@ -7,4 +7,4 @@
(package! toml-mode)
(package! vimrc-mode)
(package! yaml-mode)
(package! csv-mode)

View file

@ -1,13 +1,10 @@
;;; lang/elixir/config.el -*- lexical-binding: t; -*-
(def-package! elixir-mode
:mode "\\.exs?\\'"
:mode "\\.elixir2\\'"
:init
;; sp's default elixir rules are obnoxious, so disable them
(provide 'smartparens-elixir)
:defer t
:config
;; ...and only complete the basics
(after! smartparens
(sp-with-modes 'elixir-mode
(sp-local-pair "do" "end"
:when '(("RET" "<evil-ret>"))
@ -15,7 +12,7 @@
:skip-match 'sp-elixir-skip-def-p
:post-handlers '("||\n[i]"))
(sp-local-pair "do " " end" :unless '(sp-in-comment-p sp-in-string-p))
(sp-local-pair "fn " " end" :unless '(sp-in-comment-p sp-in-string-p))))
(sp-local-pair "fn " " end" :unless '(sp-in-comment-p sp-in-string-p)))))
(def-package! alchemist
@ -30,13 +27,13 @@
(def-package! alchemist-company
:when (featurep! :completion company)
:after elixir-mode
:commands alchemist-company
:init
(set! :company-backend 'elixir-mode '(alchemist-company company-yasnippet))
:config
;; Alchemist doesn't use hook symbols to add these backends, so we have to use
;; the entire closure to get rid of it.
(let ((fn (byte-compile (lambda () (add-to-list (make-local-variable 'company-backends) 'alchemist-company)))))
(remove-hook 'alchemist-mode-hook fn)
(remove-hook 'alchemist-iex-mode-hook fn))
(set! :company-backend 'elixir-mode '(alchemist-company company-yasnippet)))
(remove-hook 'alchemist-iex-mode-hook fn)))

View file

@ -1,13 +1,12 @@
;;; lang/elm/config.el -*- lexical-binding: t; -*-
(def-package! elm-mode
:mode "\\.elm$"
:config
(load "elm-mode-autoloads" nil t)
;; `elm-mode'
(setq elm-format-on-save t)
(add-hook! 'elm-mode-hook #'(flycheck-mode rainbow-delimiters-mode))
(set! :company-backend 'elm-mode '(company-elm))
(set! :company-backend 'elm-mode 'company-elm)
(set! :repl 'elm-mode #'run-elm-interactive)
(setq elm-format-on-save t))
(def-package! flycheck-elm

View file

@ -1,5 +1,13 @@
;;; lang/emacs-lisp/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(autoload 'overseer-test "overseer" nil t)
;;
;; Library
;;
;;;###autoload
(defun +emacs-lisp/repl ()
"Open the Emacs Lisp REPL (`ielm')."

View file

@ -67,27 +67,17 @@
;; Plugins
;;
(def-package! auto-compile
:commands auto-compile-on-save-mode
:config
;; `auto-compile'
(setq auto-compile-display-buffer nil
auto-compile-use-mode-line nil))
auto-compile-use-mode-line nil)
(def-package! highlight-quoted
:commands highlight-quoted-mode)
(def-package! slime
:defer t
:config
;; `slime'
(setq inferior-lisp-program "clisp")
(require 'slime-fuzzy))
(after! slime (require 'slime-fuzzy))
(def-package! macrostep
:commands macrostep-expand
:config
(after! macrostep
(map! :map macrostep-keymap
:n "RET" #'macrostep-expand
:n "e" #'macrostep-expand
@ -104,6 +94,7 @@
:n "q" #'macrostep-collapse-all
:n "C" #'macrostep-collapse-all)
;; `evil-normalize-keymaps' seems to be required for macrostep or it won't
;; apply for the very first invocation
(add-hook 'macrostep-mode-hook #'evil-normalize-keymaps))
@ -111,18 +102,14 @@
(def-package! flycheck-cask
:when (featurep! :feature syntax-checker)
:commands flycheck-cask-setup
:defer t
:init
(add-hook! 'emacs-lisp-mode-hook
(add-hook 'flycheck-mode-hook #'flycheck-cask-setup nil t)))
(def-package! overseer
:commands overseer-test)
;;
;;
;; Project modes
;;
(def-project-mode! +emacs-lisp-ert-mode

View file

@ -1,20 +1,19 @@
;;; private/erlang/config.el -*- lexical-binding: t; -*-
(def-package! erlang
;; customizations
:mode "\\.erlang$"
(dolist (regexp '("\\.erlang$"
;; rebar files
:mode "/rebar\\.config\\(?:\\.script\\)?$"
"/rebar\\.config\\(?:\\.script\\)?$"
;; erlang configs
:mode "/\\(?:app\\|sys\\)\\.config$")
"/\\(?:app\\|sys\\)\\.config$"))
(map-put auto-mode-alist regexp 'erlang-mode))
(def-package! flycheck-rebar3
:when (featurep! :feature syntax-checker)
:after erlang
:config
(flycheck-rebar3-setup))
:after flycheck
:config (flycheck-rebar3-setup))
;; Completion via Ivy
(def-package! ivy-erlang-complete
:when (featurep! :completion ivy)
:hook (erlang-mode . ivy-erlang-complete-init)
@ -23,7 +22,6 @@
(add-hook 'after-save-hook #'ivy-erlang-complete-reparse nil t)))
;; Completion via Company
(def-package! company-erlang
:when (featurep! :completion company)
:hook (erlang-mode . company-erlang-init))

View file

@ -79,6 +79,6 @@
:n "cn" #'ess-noweb-next-chunk))))
(def-package! ess-smart-equals
:hook ((ess-mode . ess-smart-equals-mode)
(inferior-ess-mode . ess-smart-equals-mode)))
;; `ess-smart-equals-mode'
(add-hook! (ess-mode inferior-ess)
#'ess-smart-equals-mode)

View file

@ -4,10 +4,7 @@
;; Plugins
;;
(def-package! go-mode
:mode "\\.go$"
:interpreter "go"
:config
(after! go-mode
(set! :env "GOPATH" "GOROOT")
(set! :repl 'go-mode #'gorepl-run)
(set! :lookup 'go-mode
@ -15,11 +12,12 @@
:references #'go-guru-referrers
:documentation #'godoc-at-point)
(when (executable-find "goimports")
(setq gofmt-command "goimports"))
(when-let* ((goimports (executable-find "goimports")))
(setq gofmt-command goimports))
(setq gofmt-show-errors nil) ; Leave it to flycheck
(add-hook 'go-mode-hook #'flycheck-mode)
(add-hook! 'go-mode-hook #'(flycheck-mode go-eldoc-setup))
(add-hook! go-mode
(add-hook 'before-save-hook #'gofmt-before-save nil t))
@ -70,25 +68,13 @@
:v "r" #'go-play-region))
(def-package! go-eldoc
:hook (go-mode . go-eldoc-setup))
(def-package! go-guru
:commands (go-guru-describe go-guru-freevars go-guru-implements go-guru-peers
go-guru-referrers go-guru-definition go-guru-pointsto
go-guru-callstack go-guru-whicherrs go-guru-callers go-guru-callees
go-guru-expand-region))
(def-package! gorepl-mode
:commands (gorepl-run gorepl-run-load-current-file))
:commands gorepl-run-load-current-file)
(def-package! company-go
:when (featurep! :completion company)
:init (setq command-go-gocode-command "gocode")
:after go-mode
:config
(setq company-go-show-annotation t)
(set! :company-backend 'go-mode '(company-go)))
(set! :company-backend 'go-mode 'company-go)
(setq company-go-show-annotation t))

View file

@ -8,18 +8,7 @@
;; Common plugins
;;
(def-package! haskell-mode
:mode "\\.hs$"
:mode ("\\.ghci$" . ghci-script-mode)
:mode ("\\.cabal$" . haskell-cabal-mode)
:interpreter (("runghc" . haskell-mode)
("runhaskell" . haskell-mode))
:config
(load "haskell-mode-autoloads" nil t)
(after! haskell-mode
(set! :repl 'haskell-mode #'switch-to-haskell)
(push ".hi" completion-ignored-extensions)
(autoload 'switch-to-haskell "inf-haskell" nil t)
(after! inf-haskell
(map! :map inferior-haskell-mode-map "ESC ESC" #'+popup/close)))
(add-to-list 'completion-ignored-extensions ".hi"))

View file

@ -1,8 +1,8 @@
;;; lang/hy/config.el -*- lexical-binding: t; -*-
(def-package! hy-mode
:mode "\\.hy$"
:mode "\\.hy\\'"
:interpreter "hy"
:config
(set! :repl 'hy-mode #'hy-shell-start-or-switch-to-shell)
(set! :company-backend 'hy-mode '(company-hy)))
(set! :company-backend 'hy-mode 'company-hy))

View file

@ -24,7 +24,7 @@
;;;###autoload
(defun +java|android-mode-maybe ()
(when (doom-project-has! (or "local.properties"
(when (project-file-exists-p! (or "local.properties"
"AndroidManifest.xml"
"src/main/AndroidManifest.xml"))
(android-mode +1)

View file

@ -3,8 +3,8 @@
(add-hook 'java-mode-hook #'rainbow-delimiters-mode)
(cond ((featurep! +meghanada) (load! +meghanada))
;; TODO lang/java +eclim
;; ((featurep! +eclim) (load! +eclim))
;; TODO lang/java +lsp (lsp-java?)
;; ((featurep! +lsp) (load! +lsp))
)

View file

@ -22,6 +22,7 @@
(add-hook! 'js2-mode-hook #'(flycheck-mode rainbow-delimiters-mode))
(set! :electric 'js2-mode :chars '(?\} ?\) ?. ?:))
(set! :repl 'js2-mode #'+javascript/repl)
;; Conform switch-case indentation to js2 normal indent
(defvaralias 'js-switch-indent-offset 'js2-basic-offset)
@ -34,16 +35,7 @@
:n "S" #'+javascript/skewer-this-buffer))
(def-package! typescript-mode
:commands typescript-mode
:config
(add-hook! 'typescript-mode-hook #'(flycheck-mode rainbow-delimiters-mode))
(set! :electric 'typescript-mode
:chars '(?\} ?\)) :words '("||" "&&")))
(def-package! rjsx-mode
:commands rjsx-mode
:mode "components/.+\\.js$"
:init
(defun +javascript-jsx-file-p ()
@ -54,8 +46,7 @@
magic-mode-regexp-match-limit t)
(progn (goto-char (match-beginning 1))
(not (sp-point-in-string-or-comment)))))
(push '(+javascript-jsx-file-p . rjsx-mode) magic-mode-alist)
(map-put magic-mode-alist #'+javascript-jsx-file-p 'rjsx-mode)
:config
(set! :electric 'rjsx-mode :chars '(?\} ?\) ?. ?>))
(add-hook! 'rjsx-mode-hook
@ -67,14 +58,19 @@
;; However, the parser doesn't run immediately, so a fast typist can outrun
;; it, causing issues, so force it to parse.
(defun +javascript|reparse (n)
;; if n != 0, then rjsx-maybe-reparse will be run elsewhere
(if (= n 0) (rjsx-maybe-reparse)))
;; if n != 1, rjsx-electric-gt calls rjsx-maybe-reparse itself
(if (= n 1) (rjsx-maybe-reparse)))
(advice-add #'rjsx-electric-gt :before #'+javascript|reparse))
(def-package! coffee-mode
:defer t ; file extensions registered by autoloads file
:init (setq coffee-indent-like-python-mode t))
(after! typescript-mode
(add-hook! 'typescript-mode-hook #'(flycheck-mode rainbow-delimiters-mode))
(set! :electric 'typescript-mode
:chars '(?\} ?\)) :words '("||" "&&")))
;; `coffee-mode'
(setq coffee-indent-like-python-mode t)
;;
@ -86,6 +82,7 @@
:hook (typescript-mode . tide-setup)
:init
(defun +javascript|init-tide-in-web-mode ()
"Enable `tide-mode' if in a *.tsx file."
(when (string= (file-name-extension (or buffer-file-name "")) "tsx")
(tide-setup)))
(add-hook 'web-mode-hook #'+javascript|init-tide-in-web-mode)
@ -156,12 +153,6 @@
:init (set! :lookup 'js2-mode :xref-backend #'xref-js2-xref-backend))
(def-package! nodejs-repl
:commands nodejs-repl
:init
(set! :repl 'js2-mode #'+javascript/repl))
(def-package! js2-refactor
:commands
(js2r-extract-function js2r-extract-method js2r-introduce-parameter
@ -174,51 +165,38 @@
js2r-debug-this js2r-forward-slurp js2r-forward-barf))
(def-package! web-beautify
:commands web-beautify-js
:init
(map! :map* (json-mode js2-mode-map) :n "gQ" #'web-beautify-js))
(def-package! eslintd-fix
:commands (eslintd-fix-mode eslintd-fix)
:commands eslintd-fix
:config
(defun +javascript|set-flycheck-executable-to-eslint ()
(setq flycheck-javascript-eslint-executable eslintd-fix-executable))
(add-hook 'eslintd-fix-mode-hook #'+javascript|set-flycheck-executable-to-eslint))
(def-package! skewer-mode
:commands (skewer-mode run-skewer)
:config
(map! :map skewer-mode-map
;; `skewer-mode'
(map! (:after skewer-mode
:map skewer-mode-map
:localleader
:n "sE" #'skewer-eval-last-expression
:n "se" #'skewer-eval-defun
:n "sf" #'skewer-load-buffer))
:n "sf" #'skewer-load-buffer)
(def-package! skewer-css ; in skewer-mode
:commands skewer-css-mode
:config
(map! :map skewer-css-mode-map
(:after skewer-css
:map skewer-css-mode-map
:localleader
:n "se" #'skewer-css-eval-current-declaration
:n "sr" #'skewer-css-eval-current-rule
:n "sb" #'skewer-css-eval-buffer
:n "sc" #'skewer-css-clear-all))
:n "sc" #'skewer-css-clear-all)
(def-package! skewer-html ; in skewer-mode
:commands skewer-html-mode
:config
(map! :map skewer-html-mode-map
(:after skewer-html
:map skewer-html-mode-map
:localleader
:n "se" #'skewer-html-eval-tag))
(def-package! skewer-repl
:commands skewer-repl)
;; `web-beautify'
(map! :map* (json-mode-map js2-mode-map) :n "gQ" #'web-beautify-js)
;;
@ -226,7 +204,7 @@
;;
(def-project-mode! +javascript-screeps-mode
:match "/screeps\\(-ai\\)?/.+$"
:match "/screeps\\(?:-ai\\)?/.+$"
:modes (+javascript-npm-mode)
:add-hooks (+javascript|init-screeps-mode)
:on-load (load! +screeps))

View file

@ -1,7 +1,6 @@
;;; lang/julia/config.el -*- lexical-binding: t; -*-
(use-package julia-mode
:mode "\\.jl$"
:interpreter "julia"
:config
(set! :repl 'julia-mode #'+julia/repl)

View file

@ -18,21 +18,12 @@
"Sets the directory where AUCTeX will search for PDFs associated to BibTeX references."
`(setq +latex-bibtex-dir ,dir))
;; sp's default latex rules are obnoxious, so disable them
(provide 'smartparens-latex)
;;
;; Plugins
;;
(def-package! tex-site
:init
;; Manually load the AUCTEX autoloads. This is normally done by
;; package-initialize, ... which we do not use.
(load "auctex.el" nil t t)
(load "auctex-autoloads.el" nil t t)
:config
(after! tex-site
;; Set some varibles to fontify common LaTeX commands.
(load! +fontification)
(setq ;; Enable parse on load.
@ -182,7 +173,6 @@
(def-package! bibtex
:defer t
:mode ("\\.bib\\'" . bibtex-mode)
:config
(setq bibtex-dialect 'biblatex
bibtex-align-at-equal-sign t

View file

@ -1,8 +1,7 @@
;;; lang/ledger/config.el -*- lexical-binding: t; -*-
(def-package! ledger-mode
:mode "\\.ledger$"
:config (setq ledger-clear-whole-transactions 1))
;; `ledger-mode'
(setq ledger-clear-whole-transactions 1)
(def-package! evil-ledger
@ -12,4 +11,5 @@
(def-package! flycheck-ledger
:when (featurep! :feature syntax-checker)
:init (add-hook 'ledger-mode-hook #'flycheck-mode))
:after ledger-mode
:config (add-hook 'ledger-mode-hook #'flycheck-mode))

View file

@ -1,18 +1,12 @@
;;; lang/lua/config.el -*- lexical-binding: t; -*-
(def-package! lua-mode
:mode "\\.lua$"
:interpreter "lua"
:init
;; sp's default lua rules are obnoxious, so disable them. Use snippets
;; instead!
(provide 'smartparens-lua)
:config
(after! lua-mode
(add-hook 'lua-mode-hook #'flycheck-mode)
(set! :lookup 'lua-mode :documentation 'lua-search-documentation)
(set! :electric 'lua-mode :words '("else" "end"))
(set! :repl 'lua-mode #'+lua/repl)
(set! :company-backend 'lua-mode '(company-lua company-yasnippet))
(def-menu! +lua/build-menu
"Build/compilation commands for `lua-mode' buffers."
@ -24,15 +18,8 @@
:n "b" #'+lua/build-menu))
(def-package! company-lua
:after (:all company lua-mode)
:config
(set! :company-backend 'lua-mode '(company-lua company-yasnippet)))
(def-package! moonscript
:mode ("\\.moon$" . moonscript-mode)
:config (defvaralias 'moonscript-indent-offset 'tab-width))
(after! moonscript
(defvaralias 'moonscript-indent-offset 'tab-width))
;;

View file

@ -1,9 +1,7 @@
;;; lang/markdown/config.el -*- lexical-binding: t; -*-
(def-package! markdown-mode
:mode "/README$"
:mode ("/README\\.md$" . gfm-mode)
:mode "\\.m\\(?:d\\|arkdown\\)$"
:mode ("/README\\(?:\\.\\(?:markdown\\|md\\)\\)?\\'" . gfm-mode)
:init
(setq markdown-enable-wiki-links t
markdown-enable-math t

View file

@ -1,32 +1,20 @@
;;; lang/nim/config.el -*- lexical-binding: t; -*-
(def-package! nim-mode
:mode "\\.nim\\'"
:mode ("\\.nim\\(ble\\|s\\)\\'" . nimscript-mode)
:config
(load "nim-mode-autoloads" nil t)
;; NOTE nim-mode autoloads sets up xref
(after! nim-mode
(defun +nim|init-nimsuggest-mode ()
"Conditionally load `nimsuggest-mode', instead of clumsily erroring out if
nimsuggest isn't installed."
(when (executable-find "nimsuggest")
(when (file-executable-p nimsuggest-path)
(nimsuggest-mode)))
(add-hook 'nim-mode-hook #'+nim|init-nimsuggest-mode)
(map! :map nim-mode-map
:localleader
:n "b" #'+nim/build-menu)
(def-menu! +nim/build-menu
"Building commands for `nim-mode' buffers."
'(("Build & run" :exec nim-compile))
:prompt "Build"))
:n "b" #'nim-compile))
(def-package! flycheck-nim
:when (featurep! :feature syntax-checker)
:after nim-mode
:config
(add-hook 'nimsuggest-mode-hook #'flycheck-mode))
:config (add-hook 'nimsuggest-mode-hook #'flycheck-mode))

View file

@ -1,4 +0,0 @@
;;; lang/nix/config.el -*- lexical-binding: t; -*-
(def-package! nix-mode
:mode "\\.nix$")

View file

@ -1,9 +1,13 @@
;;; lang/ocaml/config.el -*- lexical-binding: t; -*-
(def-package! tuareg
:mode ("\\.ml[4ilpy]?$" . tuareg-mode))
:mode ("\\.ml[4ilpy]?\\'" . tuareg-mode))
(def-package! merlin
:after tuareg
:hook (tuareg-mode . merlin-mode))
:hook (tuareg-mode . merlin-mode)
:config
(set! :company-backend 'tuareg-mode 'merlin-compand-backend)
(after! company
(remove-hook 'company-backends 'merlin-compand-backend)))

View file

@ -16,12 +16,8 @@
;; Plugins
;;
(def-package! toc-org
:commands toc-org-enable
:config (setq toc-org-hrefify-default "org"))
(def-package! org-bullets
:commands org-bullets-mode)
;; `toc-org'
(setq toc-org-hrefify-default "org")
(def-package! evil-org
:when (featurep! :feature evil)
@ -126,7 +122,13 @@ unfold to point on startup."
org-agenda-dim-blocked-tasks nil
org-agenda-files (ignore-errors (directory-files +org-dir t "\\.org$" t))
org-agenda-inhibit-startup t
org-agenda-skip-unavailable-files t))
org-agenda-skip-unavailable-files t)
;; Move the agenda to show the previous 3 days and the next 7 days for a bit
;; better context instead of just the current week which is a bit confusing
;; on, for example, a sunday
(setq org-agenda-span 10
org-agenda-start-on-weekday nil
org-agenda-start-day "-3d"))
(defun +org|setup-ui ()
"Configures the UI for `org-mode'."
@ -278,12 +280,14 @@ between the two."
:ni [M-return] (λ! (+org/insert-item 'below))
:ni [S-M-return] (λ! (+org/insert-item 'above))
;; more org-ish vim motion keys
:n "]]" (λ! (org-forward-heading-same-level nil) (org-beginning-of-line))
:n "[[" (λ! (org-backward-heading-same-level nil) (org-beginning-of-line))
:n "]l" #'org-next-link
:n "[l" #'org-previous-link
:n "]s" #'org-babel-next-src-block
:n "[s" #'org-babel-previous-src-block
:m "]]" (λ! (org-forward-heading-same-level nil) (org-beginning-of-line))
:m "[[" (λ! (org-backward-heading-same-level nil) (org-beginning-of-line))
:m "]h" #'org-next-visible-heading
:m "[h" #'org-previous-visible-heading
:m "]l" #'org-next-link
:m "[l" #'org-previous-link
:m "]s" #'org-babel-next-src-block
:m "[s" #'org-babel-previous-src-block
:m "^" #'evil-org-beginning-of-line
:m "0" (λ! (let ((visual-line-mode)) (org-beginning-of-line)))
:n "gQ" #'org-fill-paragraph
@ -348,10 +352,11 @@ between the two."
(def-package! org-clock
:commands org-clock-save
:hook (org-mode . org-clock-load)
:config
:init
(setq org-clock-persist 'history
org-clock-persist-file (concat doom-etc-dir "org-clock-save.el"))
(add-hook 'kill-emacs-hook 'org-clock-save))
:config
(add-hook 'kill-emacs-hook #'org-clock-save))
;;
(when (featurep 'org)

View file

@ -1,7 +1,7 @@
;;; lang/plantuml/config.el -*- lexical-binding: t; -*-
(def-package! plantuml-mode
:mode "\\.p\\(?:lant\\)?uml$"
:defer t
:init
(setq plantuml-jar-path (concat doom-etc-dir "plantuml.jar")
org-plantuml-jar-path plantuml-jar-path)

View file

@ -1,16 +1,18 @@
;;; lang/purescript/config.el -*- lexical-binding: t; -*-
(def-package! purescript-mode
:mode "\\.purs$"
:config
(after! purescript-mode
(add-hook! 'purescript-mode-hook
#'(flycheck-mode purescript-indentation-mode rainbow-delimiters-mode)))
#'(flycheck-mode
purescript-indentation-mode
rainbow-delimiters-mode)))
;; (def-package! flycheck-purescript
;; :after purescript-mode
;; :config
;; (add-hook 'flycheck-mode-hook #'flycheck-purescript-setup))
(def-package! psc-ide
:hook (purescript-mode . psc-ide-mode))

Some files were not shown because too many files have changed in this diff Show more