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 DOOM = bin/doom
EMACS = emacs -q --eval "(setq user-emacs-directory default-directory load-prefer-newer t)"
DOOM = $(EMACS) --batch -l init.el
DOOMI = $(subst --batch,,$(DOOM))
MODULES = $(patsubst modules/%/, %, $(sort $(dir $(wildcard modules/*/ modules/*/*/)))) MODULES = $(patsubst modules/%/, %, $(sort $(dir $(wildcard modules/*/ modules/*/*/))))
all: all:
@$(DOOM) -f doom//reload-packages @$(DOOM) refresh
## Shortcuts ## Shortcuts
a: autoloads a: autoloads
@ -16,88 +12,66 @@ U: upgrade
r: autoremove r: autoremove
c: compile c: compile
cc: compile-core cc: compile-core
ce: compile-elpa cp: compile-plugins
re: recompile re: recompile
d: doctor d: doctor
quickstart: | ~/.doom.d/init.el all recompile quickstart:
~/.doom.d/init.el: @$(DOOM) quickstart
@echo "Creating ~/.doom.d directory"
@mkdir ~/.doom.d && cp init.example.el ~/.doom.d/init.el
@touch ~/.doom.d/config.el
## Package management ## Package management
install: | .local/autoloads.el install:
@$(DOOM) -f doom//packages-install @$(DOOM) install
update:
update: | .local/autoloads.el @$(DOOM) update
@$(DOOM) -f doom//packages-update autoremove:
@$(DOOM) autoremove
autoremove: | .local/autoloads.el
@$(DOOM) -f doom//packages-autoremove
autoloads: autoloads:
@$(DOOM) -f doom//reload-autoloads @$(DOOM) autoloads
upgrade:
upgrade: | _upgrade recompile all @$(DOOM) upgrade
_upgrade:
@git pull origin $(shell git rev-parse --abbrev-ref HEAD)
## Byte compilation ## Byte compilation
# compile compile:
# compile-core @$(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
# compile-module/submodule # 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 $(patsubst %, compile-%, $(MODULES)): | .local/autoloads.el
@$(DOOM) -f doom//byte-compile -- $(patsubst compile-%, %, $@) @$(DOOM) $@ $(subst compile-, , $@)
recompile:
@$(DOOM) -f doom//byte-compile -- -r
clean:
@$(DOOM) -f doom//clean-byte-compiled-files
## Unit tests ## Unit tests
# test test:
# test-core @$(DOOM) test
test-core:
@$(DOOM) test :core
# test-module # test-module
# test-module/submodule # test-module/submodule
test: | .local/autoloads.el $(patsubst %, test-%, $(MODULES)):
@$(DOOM) -f doom//run-tests @$(DOOM) test $(subst test-, , $@)
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
## Utility tasks ## Utility tasks
# Runs Emacs from a different folder than ~/.emacs.d; only use this for testing! # Runs Emacs from a different folder than ~/.emacs.d; only use this for testing!
run: 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 # Diagnoses potential OS/environment issues
doctor: doctor:
@$(EMACS) --script bin/doom-doctor @$(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
.PHONY: all compile test testi clean .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 #!/usr/bin/env bash
":"; command -v emacs >/dev/null || { >&2 echo "Emacs isn't installed"; exit 1; } # -*-emacs-lisp-*- ":"; 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 ;; Uses a couple simple heuristics to locate issues with your environment that
;; could interfere with running or setting up DOOM Emacs. ;; could interfere with running or setting up DOOM Emacs.
@ -18,6 +20,7 @@
;; ;;
(defvar doom-init-p nil) (defvar doom-init-p nil)
(defvar doom-warnings 0)
(defvar doom-errors 0) (defvar doom-errors 0)
(defmacro when! (cond &rest body) (defmacro when! (cond &rest body)
(declare (indent defun)) (declare (indent defun))
@ -62,7 +65,7 @@
(format (concat prefix ,msg) (format (concat prefix ,msg)
,@args)))) ,@args))))
(defmacro error! (&rest args) `(progn (msg! (color 31 ,@args)) (setq doom-errors (+ doom-errors 1)))) (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 success! (&rest args) `(msg! (color 32 ,@args)))
(defmacro section! (&rest args) (defmacro section! (&rest args)
`(msg! (color 1 (color 34 ,@args)))) `(msg! (color 1 (color 34 ,@args))))
@ -112,11 +115,8 @@
(message "Compiled with:\n%s" (indented 2 system-configuration-features))) (message "Compiled with:\n%s" (indented 2 system-configuration-features)))
(message "uname -a:\n%s\n" (indented 2 (sh "uname -a"))) (message "uname -a:\n%s\n" (indented 2 (sh "uname -a")))
(msg! "----\n")
;; --- is emacs set up properly? ------------------------------ ;; --- is emacs set up properly? ------------------------------
(section! "test-emacs")
(when (version< emacs-version "25.1") (when (version< emacs-version "25.1")
(error! "Important: Emacs %s detected [%s]" emacs-version (executable-find "emacs")) (error! "Important: Emacs %s detected [%s]" emacs-version (executable-find "emacs"))
(explain! (explain!
@ -125,7 +125,6 @@
(concat "\nMacOS users should use homebrew (https://brew.sh) to install Emacs\n" (concat "\nMacOS users should use homebrew (https://brew.sh) to install Emacs\n"
" brew install emacs --with-modules --with-imagemagick --with-cocoa")))) " brew install emacs --with-modules --with-imagemagick --with-cocoa"))))
(section! "test-private-config")
(let ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME") (let ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME")
"~/.config") "~/.config")
"/doom/")) "/doom/"))
@ -140,14 +139,14 @@
;; --- is the environment set up properly? -------------------- ;; --- is the environment set up properly? --------------------
;; windows? windows ;; on windows?
(section! "test-windows") (section! "Checking your OS...")
(when (memq system-type '(windows-nt ms-dos cygwin)) (when (memq system-type '(windows-nt ms-dos cygwin))
(warn! "Warning: Windows detected") (warn! "Warning: Windows detected")
(explain! "DOOM was designed for MacOS and Linux. Expect a bumpy ride!")) (explain! "DOOM was designed for MacOS and Linux. Expect a bumpy ride!"))
;; are all default fonts present ;; are all default fonts present?
(section! "test-fonts") (section! "Checking your fonts...")
(if (not (fboundp 'find-font)) (if (not (fboundp 'find-font))
(progn (progn
(warn! "Warning: unable to detect font") (warn! "Warning: unable to detect font")
@ -170,7 +169,7 @@
"case, ignore this warning.")))))) "case, ignore this warning."))))))
;; gnutls-cli & openssl ;; gnutls-cli & openssl
(section! "test-gnutls") (section! "Checking gnutls/openssl...")
(cond ((executable-find "gnutls-cli")) (cond ((executable-find "gnutls-cli"))
((executable-find "openssl") ((executable-find "openssl")
(let* ((output (sh "openssl ciphers -v")) (let* ((output (sh "openssl ciphers -v"))
@ -205,7 +204,8 @@
"network, provider, government, neckbearded mother-in-laws, geeky roommates, " "network, provider, government, neckbearded mother-in-laws, geeky roommates, "
"or just about anyone who knows more about computers than you do!"))) "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)) (cond ((not (string-match-p "\\_<GNUTLS\\_>" system-configuration-features))
(warn! "Warning: You didn't install Emacs with gnutls support") (warn! "Warning: You didn't install Emacs with gnutls support")
(explain! (explain!
@ -227,8 +227,7 @@
(gnutls-verify-error t)) (gnutls-verify-error t))
(dolist (url '("https://elpa.gnu.org" "https://melpa.org")) (dolist (url '("https://elpa.gnu.org" "https://melpa.org"))
(when! (condition-case-unless-debug e (when! (condition-case-unless-debug e
(if (let ((inhibit-message t)) (url-retrieve-synchronously url)) (unless (let ((inhibit-message t)) (url-retrieve-synchronously url))
(ignore (success! "Validated %s" url))
'empty) 'empty)
('timed-out 'timeout) ('timed-out 'timeout)
('error e)) ('error e))
@ -245,7 +244,7 @@
t t
'empty) 'empty)
('timed-out 'timeout) ('timed-out 'timeout)
('error (ignore (success! "Successfully rejected %s" url)))) ('error))
(pcase it (pcase it
(`empty (error! "Couldn't reach %s" url)) (`empty (error! "Couldn't reach %s" url))
(`timeout (error! "Timed out trying to contact %s" ex)) (`timeout (error! "Timed out trying to contact %s" ex))
@ -254,8 +253,8 @@
((error! "Nope!"))) ((error! "Nope!")))
;; bsd vs gnu tar ;; which variant of tar is on your system? bsd or gnu tar?
(section! "test-tar") (section! "Checking for GNU/BSD tar...")
(let ((tar-bin (or (executable-find "gtar") (let ((tar-bin (or (executable-find "gtar")
(executable-find "tar")))) (executable-find "tar"))))
(if tar-bin (if tar-bin
@ -276,14 +275,11 @@
;; --- are your modules set up properly? ---------------------- ;; --- are your modules set up properly? ----------------------
(message "\n----")
(let (doom-core-packages doom-debug-mode) (let (doom-core-packages doom-debug-mode)
(condition-case ex (condition-case ex
(let ((inhibit-message t)) (let ((inhibit-message t))
(load "~/.emacs.d/core/core.el" nil t) (load (concat user-emacs-directory "init.el") nil t)
(let (noninteractive) (doom-initialize-modules)
(doom-initialize t)
(doom|finalize))
(success! "Attempt to load DOOM: success! Loaded v%s" doom-version)) (success! "Attempt to load DOOM: success! Loaded v%s" doom-version))
('error ('error
(warn! "Attempt to load DOOM: failed\n %s\n" (warn! "Attempt to load DOOM: failed\n %s\n"
@ -291,14 +287,14 @@
(setq doom-modules nil)))) (setq doom-modules nil))))
(when (bound-and-true-p doom-modules) (when (bound-and-true-p doom-modules)
(section! "test-modules") (section! "Checking your enabled modules...")
(let ((indent 4)) (let ((indent 4))
(advice-add #'require :around #'doom*shut-up) (advice-add #'require :around #'doom*shut-up)
(maphash (maphash
(lambda (key plist) (lambda (key plist)
(condition-case ex (condition-case ex
(let ((doctor-file (doom-module-expand-file (car key) (cdr key) "doctor.el")) (let ((doctor-file (doom-module-path (car key) (cdr key) "doctor.el"))
(packages-file (doom-module-expand-file (car key) (cdr key) "packages.el")) (packages-file (doom-module-path (car key) (cdr key) "packages.el"))
doom-packages) doom-packages)
(when (or (file-exists-p doctor-file) (when (or (file-exists-p doctor-file)
(file-exists-p packages-file)) (file-exists-p packages-file))
@ -306,7 +302,8 @@
(doom--stage 'packages)) (doom--stage 'packages))
(when (load packages-file t t) (when (load packages-file t t)
(dolist (package (cl-remove-if #'package-installed-p doom-packages :key #'car)) (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)) (let ((doom--stage 'doctor))
(load doctor-file t t))))) (load doctor-file t t)))))
('error ('error
@ -314,7 +311,13 @@
doom-modules))) doom-modules)))
;; ;;
(message "\n----") (message "\n")
(if (> doom-errors 0) (dolist (msg (list (list doom-errors "error" 31)
(warn! "There were %s issues!" doom-errors) (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!")) (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 ;; Like persistent-soft, caches assume a 2-tier structure, where all caches are
;; namespaced by location. ;; namespaced by location.
(require 'persistent-soft)
(defvar doom-cache-alists () (defvar doom-cache-alists ()
"An alist of alists, containing lists of variables for the doom cache library "An alist of alists, containing lists of variables for the doom cache library
to persist across Emacs sessions.") 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)))) (t (delete-char (- n) killflag))))
;;;###autoload ;;;###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 "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 buffer start and end, to make indentation consistent. Which it does depends on
the value of `indent-tab-mode'." the value of `indent-tab-mode'.
(interactive "r")
If ARG (universal argument) is non-nil, retab the current buffer using the
opposite indentation style."
(interactive "Pr")
(unless (and beg end) (unless (and beg end)
(setq beg (point-min) (setq beg (point-min)
end (point-max))) end (point-max)))
(if indent-tabs-mode (let ((indent-tabs-mode (if arg (not indent-tabs-mode) indent-tabs-mode)))
(tabify beg end) (if indent-tabs-mode
(untabify beg end))) (tabify beg end)
(untabify beg end))))
(defvar-local doom--buffer-narrowed-origin nil) (defvar-local doom--buffer-narrowed-origin nil)
;;;###autoload ;;;###autoload

View file

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

View file

@ -1,22 +1,5 @@
;;; core/autoload/help.el -*- lexical-binding: t; -*- ;;; 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 (defvar doom--module-mode-alist
'((c-mode :lang cc) '((c-mode :lang cc)
(c++-mode :lang cc) (c++-mode :lang cc)
@ -58,6 +41,42 @@ Defaults to the "
(stylus-mode :lang web)) (stylus-mode :lang web))
"TODO") "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 ;;;###autoload
(defun doom/describe-module (module) (defun doom/describe-module (module)
"Open the documentation of MODULE (a string that represents the category and "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") "init.el")
(thing-at-point 'sexp t))) (thing-at-point 'sexp t)))
((save-excursion ((save-excursion
(require 'smartparens)
(ignore-errors (ignore-errors
(sp-beginning-of-sexp) (sp-beginning-of-sexp)
(unless (eq (char-after) ?\() (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 " ")) (mapcar #'intern (split-string module " "))
(unless (doom-module-p category submodule) (unless (doom-module-p category submodule)
(error "'%s' isn't a valid module" module)) (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) (unless (file-exists-p doc-path)
(error "There is no documentation for this module")) (error "There is no documentation for this module"))
(find-file doc-path)))) (find-file doc-path))))
;;;###autoload ;;;###autoload
(defun doom/version () (defun doom/describe-active-minor-mode (mode)
"Display the current version of Doom & Emacs, including the current Doom "Get information on an active minor mode. Use `describe-minor-mode' for a
branch and commit." 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) (interactive)
(message "Doom v%s (Emacs v%s). Branch: %s. Commit: %s." (let* ((pos (or pos (point)))
doom-version (faces (let ((face (get-text-property pos 'face)))
emacs-version (if (keywordp (car-safe face))
(if-let* ((branch (vc-git--symbolic-ref "core/core.el"))) (list face)
branch (cl-loop for f in (doom-enlist face) collect f))))
"n/a") (overlays (cl-loop for ov in (overlays-at pos (1+ pos))
(if-let* ((rev (vc-git-working-revision "core/core.el"))) nconc (doom-enlist (overlay-get ov 'face)))))
rev (cond ((called-interactively-p 'any)
"n/a"))) (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//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; -*- ;;; core/autoload/message.el -*- lexical-binding: t; -*-
(defconst doom-message-fg (defconst doom-message-fg
'((reset . 0) '((black 30 term-color-black)
(black . 30) (red 31 term-color-red)
(red . 31) (green 32 term-color-green)
(green . 32) (yellow 33 term-color-yellow)
(yellow . 33) (blue 34 term-color-blue)
(blue . 34) (magenta 35 term-color-magenta)
(magenta . 35) (cyan 36 term-color-cyan)
(cyan . 36) (white 37 term-color-white))
(white . 37))
"List of text colors.") "List of text colors.")
(defconst doom-message-bg (defconst doom-message-bg
'((on-black . 40) '((on-black 40 term-color-black)
(on-red . 41) (on-red 41 term-color-red)
(on-green . 42) (on-green 42 term-color-green)
(on-yellow . 43) (on-yellow 43 term-color-yellow)
(on-blue . 44) (on-blue 44 term-color-blue)
(on-magenta . 45) (on-magenta 45 term-color-magenta)
(on-cyan . 46) (on-cyan 46 term-color-cyan)
(on-white . 47)) (on-white 47 term-color-white))
"List of colors to draw text on.") "List of colors to draw text on.")
(defconst doom-message-fx (defconst doom-message-fx
'((bold . 1) '((bold 1 :weight bold)
(dark . 2) (dark 2)
(italic . 3) (italic 3 :slant italic)
(underscore . 4) (underscore 4 :underline t)
(blink . 5) (blink 5)
(rapid . 6) (rapid 6)
(contrary . 7) (contrary 7)
(concealed . 8) (concealed 8)
(strike . 9)) (strike 9 :strike-through t))
"List of styles.") "List of styles.")
;;;###autoload ;;;###autoload
(defun doom-ansi-apply (code message &rest args) (defun doom-ansi-apply (code message &rest args)
"Apply the ansi CODE to formatted MESSAGE with ARGS." "Apply CODE to formatted MESSAGE with ARGS. CODE is derived from any of
(let ((rule (or (assq code doom-message-fg) `doom-message-fg', `doom-message-bg' or `doom-message-fx'.
(assq code doom-message-bg)
(assq code doom-message-fx)))) In a noninteractive session, this wraps the result in ansi color codes.
(format "\e[%dm%s\e[%dm" Otherwise, it maps colors to a term-color-* face."
(cdr rule) (let ((text (apply #'format message args)))
(apply #'format message args) (if noninteractive
0))) (format "\e[%dm%s\e[%dm"
(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 ;;;###autoload
(defmacro format! (message &rest args) (defmacro format! (message &rest args)
"An alternative to `format' that strips out ANSI codes if used in an "An alternative to `format' that understands (color ...) and converts them
interactive session." into faces or ANSI codes depending on the type of sesssion we're in."
`(cl-flet* `(cl-flet*
(,@(cl-loop for rule (,@(cl-loop for rule
in (append doom-message-fg doom-message-bg doom-message-fx) in (append doom-message-fg doom-message-bg doom-message-fx)
@ -63,19 +76,19 @@ interactive session."
(format ,message ,@args))) (format ,message ,@args)))
;;;###autoload ;;;###autoload
(defmacro message! (message &rest args) (defmacro print! (message &rest args)
"An alternative to `message' that strips out ANSI codes if used in an "Uses `message' in interactive sessions and `princ' otherwise (prints to
interactive session." standard out).
`(if noninteractive
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)) (message (format! ,message ,@args))
(let ((buf (get-buffer-create " *doom messages*"))) ;; princ prints to stdout, message to stderr
(with-current-buffer buf (princ (format! ,message ,@args))
(goto-char (point-max)) (terpri)))
(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)))))

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; -*- ;;; core/autoload/packages.el -*- lexical-binding: t; -*-
(load! cache) (load! cache)
(require 'use-package)
(require 'quelpa)
(require 'package)
(require 'async)
;;; Private functions ;;; Private functions
(defsubst doom--sort-alpha (it other)
(string-lessp (symbol-name (car it))
(symbol-name (car other))))
(defun doom--packages-choose (prompt) (defun doom--packages-choose (prompt)
(let ((table (cl-loop for pkg in package-alist (let ((table (cl-loop for pkg in package-alist
@ -26,15 +19,15 @@
(condition-case ex2 (condition-case ex2
(progn ,@body) (progn ,@body)
('file-error ('file-error
(message! (bold (red " FILE ERROR: %s" (error-message-string ex2)))) (print! (bold (red " FILE ERROR: %s" (error-message-string ex2))))
(message! " Trying again...") (print! " Trying again...")
(quiet! (doom-refresh-packages-maybe t)) (quiet! (doom-refresh-packages-maybe t))
,@body)) ,@body))
('user-error ('user-error
(message! (bold (red " ERROR: %s" ex)))) (print! (bold (red " ERROR: %s" ex))))
('error ('error
(doom--refresh-pkg-cache) (doom--refresh-pkg-cache)
(message! (bold (red " FATAL ERROR: %s" ex)))))) (print! (bold (red " FATAL ERROR: %s" ex))))))
(defun doom--refresh-pkg-cache () (defun doom--refresh-pkg-cache ()
"Clear the cache for `doom-refresh-packages-maybe'." "Clear the cache for `doom-refresh-packages-maybe'."
@ -57,7 +50,7 @@
(progn (progn
(message "Refreshing package archives") (message "Refreshing package archives")
(package-refresh-contents) (package-refresh-contents)
(doom-cache-set 'last-pkg-refresh t 900)) (doom-cache-set 'last-pkg-refresh t 1200))
('error ('error
(doom--refresh-pkg-cache) (doom--refresh-pkg-cache)
(message "Failed to refresh packages: (%s) %s" (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. Be careful not to use it in a loop.
If INSTALLED-ONLY-P, only return packages that are installed." 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)) (cl-loop with packages = (append doom-core-packages (mapcar #'car doom-packages))
for sym in (cl-delete-duplicates packages) for sym in (cl-delete-duplicates packages)
if (and (or (not installed-only-p) 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. If INCLUDE-FROZEN-P is non-nil, check frozen packages as well.
Used by `doom//packages-update'." Used by `doom//packages-update'."
(doom-initialize-packages (not noninteractive)) (doom-initialize-packages t)
(doom-refresh-packages-maybe doom-debug-mode)
(require 'async) (require 'async)
(let (quelpa-pkgs elpa-pkgs) (let (quelpa-pkgs elpa-pkgs)
;; Separate quelpa from elpa packages ;; Separate quelpa from elpa packages
@ -201,9 +195,12 @@ Used by `doom//packages-update'."
(message "New thread for: %s" pkg)) (message "New thread for: %s" pkg))
(push (async-start (push (async-start
`(lambda () `(lambda ()
(let ((doom-init-p 'internal) (let ((doom-init-p t)
(noninteractive t) (noninteractive t)
(load-path ',load-path) (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-packages ',doom-packages)
(doom-modules ',doom-modules) (doom-modules ',doom-modules)
(quelpa-cache ',quelpa-cache) (quelpa-cache ',quelpa-cache)
@ -211,6 +208,8 @@ Used by `doom//packages-update'."
doom-private-dir) doom-private-dir)
(load ,(expand-file-name "core.el" doom-core-dir)) (load ,(expand-file-name "core.el" doom-core-dir))
(load ,(expand-file-name "autoload/packages.el" doom-core-dir)) (load ,(expand-file-name "autoload/packages.el" doom-core-dir))
(require 'package)
(require 'quelpa)
(doom-package-outdated-p ',pkg)))) (doom-package-outdated-p ',pkg))))
futures)) futures))
(delq nil (delq nil
@ -223,7 +222,7 @@ Used by `doom//packages-update'."
depended on. depended on.
Used by `doom//packages-autoremove'." Used by `doom//packages-autoremove'."
(doom-initialize-packages (not noninteractive)) (doom-initialize-packages t)
(let ((package-selected-packages (let ((package-selected-packages
(append (mapcar #'car doom-packages) doom-core-packages))) (append (mapcar #'car doom-packages) doom-core-packages)))
(append (package--removable-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. i.e. they have an :ignore property.
Used by `doom//packages-install'." Used by `doom//packages-install'."
(doom-initialize-packages (not noninteractive))
(cl-loop for desc in (doom-get-packages) (cl-loop for desc in (doom-get-packages)
for (name . plist) = desc for (name . plist) = desc
if (and (or include-ignored-p if (and (or include-ignored-p
@ -260,6 +258,7 @@ Used by `doom//packages-install'."
;; Main functions ;; Main functions
;; ;;
;;;###autoload
(defun doom-install-package (name &optional plist) (defun doom-install-package (name &optional plist)
"Installs package NAME with optional quelpa RECIPE (see `quelpa-recipe' for an "Installs package NAME with optional quelpa RECIPE (see `quelpa-recipe' for an
example; the package name can be omitted)." example; the package name can be omitted)."
@ -283,6 +282,7 @@ example; the package name can be omitted)."
(map-put doom-packages name plist) (map-put doom-packages name plist)
name))) name)))
;;;###autoload
(defun doom-update-package (name &optional force-p) (defun doom-update-package (name &optional force-p)
"Updates package NAME (a symbol) if it is out of date, using quelpa or "Updates package NAME (a symbol) if it is out of date, using quelpa or
package.el as appropriate." package.el as appropriate."
@ -310,6 +310,7 @@ package.el as appropriate."
(delete-directory old-dir t))) (delete-directory old-dir t)))
t)))) t))))
;;;###autoload
(defun doom-delete-package (name &optional force-p) (defun doom-delete-package (name &optional force-p)
"Uninstalls package NAME if it exists, and clears it from `quelpa-cache'." "Uninstalls package NAME if it exists, and clears it from `quelpa-cache'."
(unless (package-installed-p name) (unless (package-installed-p name)
@ -328,162 +329,6 @@ package.el as appropriate."
t))) 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 ;; Interactive commands
;; ;;
@ -533,3 +378,148 @@ calls."
(when (file-exists-p path) (when (file-exists-p path)
(delete-directory path t)))))) (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; -*- ;;; core/autoload/test.el -*- lexical-binding: t; no-byte-compile: t; -*-
;;;###autoload
(defun doom//run-tests (&optional modules) (defun doom//run-tests (&optional modules)
"Run all loaded tests, specified by MODULES (a list of module cons cells) or "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 command line args following a double dash (each arg should be in the
@ -8,56 +7,56 @@ command line args following a double dash (each arg should be in the
If neither is available, run all tests in all enabled modules." If neither is available, run all tests in all enabled modules."
(interactive) (interactive)
(let ((doom-modules (make-hash-table :test #'equal))) (doom//reload-autoloads)
;; ensure DOOM is initialized (let (noninteractive)
(let (noninteractive) ;; Core libraries aren't fully loaded in a noninteractive session, so we
;; Core libraries aren't fully loaded in a noninteractive session, so we ;; reload it with `noninteractive' set to nil to force them to.
;; reload it with `noninteractive' set to nil to force them to. (doom-initialize t)
(doom-initialize t) (doom-initialize-modules t))
(run-hooks 'doom-init-hook 'pre-command-hook 'doom-after-switch-buffer-hook)) (condition-case-unless-debug ex
(condition-case-unless-debug ex (let* ((doom-modules (doom-module-table))
(let ((target-paths (target-paths
;; Convert targets (either from MODULES or `argv') into a list of ;; Convert targets (either from MODULES or `argv') into a list of
;; string paths, pointing to the root directory of modules ;; string paths, pointing to the root directory of modules
(cond ((string= (car argv) "--") ; command line (cond ((stringp (car modules)) ; command line
(save-match-data (save-match-data
(cl-loop for arg in (cdr argv) (cl-loop for arg in modules
if (string= arg "core") collect doom-core-dir if (string= arg ":core") collect doom-core-dir
else if (string-match-p "/" arg) else if (string-match-p "/" arg)
nconc (cl-loop for dir in doom-modules-dirs nconc (cl-loop for dir in doom-modules-dirs
collect (expand-file-name arg dir)) collect (expand-file-name arg dir))
else else
nconc (cl-loop for dir in doom-modules-dirs nconc (cl-loop for dir in doom-modules-dirs
for path = (expand-file-name arg dir) for path = (expand-file-name arg dir)
if (file-directory-p path) if (file-directory-p path)
nconc nconc
(cl-remove-if-not (cl-remove-if-not
#'file-directory-p #'file-directory-p
(directory-files path t "^[^.]" t))) (directory-files path t "^[^.]" t)))
finally do (setq argv nil)))) finally do (setq argv nil))))
(modules ; cons-cells given to MODULES (modules ; cons-cells given to MODULES
(cl-loop for (module . submodule) in modules (cl-loop for (module . submodule) in modules
if (doom-module-find-path module submodule) if (doom-module-locate-path module submodule)
collect it)) collect it))
((let (noninteractive) ((append (list doom-core-dir)
(load (expand-file-name "init.test.el" user-emacs-directory) nil t) (doom-module-load-path))))))
(append (list doom-core-dir) (doom-module-load-path))))))) ;; Load all the unit test files...
;; Load all the unit test files... (dolist (path target-paths)
(dolist (path target-paths) (let ((test-path (expand-file-name "test/" path)))
(let ((test-path (expand-file-name "test/" path))) (when (file-directory-p test-path)
(when (file-directory-p test-path) (dolist (test-file (reverse (doom-files-in test-path :match "\\.el$" :full t)))
(dolist (test-file (reverse (doom-packages--files test-path "\\.el$"))) (load test-file nil :noerror)))))
(load test-file nil :noerror))))) ;; ... then run them
;; ... then run them (switch-to-buffer (get-buffer-create "*blank*"))
(if noninteractive (if noninteractive
(ert-run-tests-batch-and-exit) (ert-run-tests-batch-and-exit)
(call-interactively #'ert-run-tests-interactively))) (call-interactively #'ert-run-tests-interactively)))
('error ('error
(lwarn 'doom-test :error (lwarn 'doom-test :error
"%s -> %s" "%s -> %s"
(car ex) (error-message-string ex)))))) (car ex) (error-message-string ex)))))
;; --- Test helpers ----------------------- ;; --- 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 ;; 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. (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 ;; revert buffers for changed files
(def-package! autorevert (def-package! autorevert
:defer doom-before-switch-buffer-hook :after-call doom-before-switch-buffer-hook
:config :config
(setq auto-revert-verbose nil) (setq auto-revert-verbose nil)
(global-auto-revert-mode +1)) (global-auto-revert-mode +1))
;; persist variables across sessions ;; persist variables across sessions
(def-package! savehist (def-package! savehist
:defer (pre-command-hook . 1) :defer 1
:after-call post-command-hook
:config :config
(setq savehist-file (concat doom-cache-dir "savehist") (setq savehist-file (concat doom-cache-dir "savehist")
savehist-save-minibuffer-history t savehist-save-minibuffer-history t
@ -100,7 +101,7 @@ fundamental-mode) for performance sake."
;; persistent point location in buffers ;; persistent point location in buffers
(def-package! saveplace (def-package! saveplace
:defer doom-before-switch-buffer-hook :after-call doom-before-switch-buffer-hook
:config :config
(setq save-place-file (concat doom-cache-dir "saveplace")) (setq save-place-file (concat doom-cache-dir "saveplace"))
(defun doom*recenter-on-load-saveplace (&rest _) (defun doom*recenter-on-load-saveplace (&rest _)
@ -112,20 +113,21 @@ fundamental-mode) for performance sake."
;; Keep track of recently opened files ;; Keep track of recently opened files
(def-package! recentf (def-package! recentf
:defer (pre-command-hook . 1) :defer 1
:after-call find-file-hook
:commands recentf-open-files :commands recentf-open-files
:config :config
(setq recentf-save-file (concat doom-cache-dir "recentf") (setq recentf-save-file (concat doom-cache-dir "recentf")
recentf-auto-cleanup 60 recentf-auto-cleanup 120
recentf-max-menu-items 0 recentf-max-menu-items 0
recentf-max-saved-items 300 recentf-max-saved-items 300
recentf-filename-handlers '(file-truename) recentf-filename-handlers '(file-truename)
recentf-exclude 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$" "^/tmp/" "^/ssh:" "\\.?ido\\.last$" "\\.revive$" "/TAGS$"
"^/var/folders/.+$" "^/var/folders/.+$"
;; ignore private DOOM temp files (but not all of them) ;; 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)) (recentf-mode +1))
@ -135,7 +137,7 @@ fundamental-mode) for performance sake."
;; Auto-close delimiters and blocks as you type ;; Auto-close delimiters and blocks as you type
(def-package! smartparens (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) :commands (sp-pair sp-local-pair sp-with-modes)
:config :config
(require 'smartparens-config) (require 'smartparens-config)
@ -155,7 +157,7 @@ fundamental-mode) for performance sake."
;; Branching undo ;; Branching undo
(def-package! undo-tree (def-package! undo-tree
:defer doom-before-switch-buffer-hook :after-call doom-before-switch-buffer-hook
:config :config
;; persistent undo history is known to cause undo history corruption, which ;; persistent undo history is known to cause undo history corruption, which
;; can be very destructive! So disable it! ;; 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)) command-log-mode-open-log-turns-on-mode t))
(def-package! dtrt-indent (def-package! dtrt-indent
:after-call doom-before-switch-buffer-hook
:config :config
(setq dtrt-indent-verbosity (if doom-debug-mode 2 0)) (setq dtrt-indent-verbosity (if doom-debug-mode 2 0))
(defun doom|detect-indentation () (defun doom|detect-indentation ()
(unless (or doom-inhibit-indent-detection (eq major-mode 'fundamental-mode)) (unless (or doom-inhibit-indent-detection (eq major-mode 'fundamental-mode))
(dtrt-indent-mode +1))) (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 (def-package! expand-region
:commands (er/expand-region er/contract-region er/mark-symbol er/mark-word) :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 ;; embolden local bindings
(set-face-attribute 'which-key-local-map-description-face nil :weight 'bold) (set-face-attribute 'which-key-local-map-description-face nil :weight 'bold)
(which-key-setup-side-window-bottom) (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 (def-package! hydra
:commands (defhydra defhydradio) :defer t
:init
;; In case I later need to wrap defhydra in any special functionality.
(defalias 'def-hydra! 'defhydra)
(defalias 'def-hydra-radio! 'defhydradio)
:config :config
(setq lv-use-seperator t) (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 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") ("k" text-scale-decrease "out")
("0" (text-scale-set 0) "reset")) ("0" (text-scale-set 0) "reset"))
(def-hydra! doom@window-nav (:hint nil) (defhydra doom@window-nav (:hint nil)
" "
Split: _v_ert _s_:horz Split: _v_ert _s_:horz
Delete: _c_lose _o_nly Delete: _c_lose _o_nly

View file

@ -1,8 +1,15 @@
;;; core-lib.el -*- lexical-binding: t; -*- ;;; 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 (eval-and-compile
(unless EMACS26+ (unless EMACS26+
(with-no-warnings (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 'if-let* #'if-let)
(defalias 'when-let* #'when-let)))) (defalias 'when-let* #'when-let))))
@ -11,18 +18,40 @@
;; Helpers ;; Helpers
;; ;;
(defun doom--resolve-path-forms (paths &optional root) (defun doom--resolve-path-forms (spec &optional directory)
(cond ((stringp paths) "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 `(file-exists-p
(expand-file-name ,(if (file-name-absolute-p spec)
,paths ,(if (or (string-prefix-p "./" paths) spec
(string-prefix-p "../" paths)) `(expand-file-name ,spec ,directory))))
'default-directory ((symbolp spec)
(or root `(doom-project-root)))))) `(file-exists-p ,(if directory
((listp paths) `(expand-file-name ,spec ,directory)
(cl-loop for i in paths path)))
collect (doom--resolve-path-forms i root))) ((and (listp spec)
(t paths))) (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) (defun doom--resolve-hook-forms (hooks)
(cl-loop with quoted-p = (eq (car-safe hooks) 'quote) (cl-loop with quoted-p = (eq (car-safe hooks) 'quote)
@ -33,6 +62,11 @@
collect hook collect hook
else collect (intern (format "%s-hook" (symbol-name hook))))) else collect (intern (format "%s-hook" (symbol-name hook)))))
;;
;; Functions
;;
(defun doom-unquote (exp) (defun doom-unquote (exp)
"Return EXP unquoted." "Return EXP unquoted."
(while (memq (car-safe exp) '(quote function)) (while (memq (car-safe exp) '(quote function))
@ -43,6 +77,94 @@
"Return EXP wrapped in a list, or as-is if already a list." "Return EXP wrapped in a list, or as-is if already a list."
(if (listp exp) exp (list exp))) (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) (defun doom*shut-up (orig-fn &rest args)
"Generic advisor for silencing noisy functions." "Generic advisor for silencing noisy functions."
(quiet! (apply orig-fn args))) (quiet! (apply orig-fn args)))
@ -61,29 +183,31 @@
(defmacro after! (targets &rest body) (defmacro after! (targets &rest body)
"A smart wrapper around `with-eval-after-load'. Supresses warnings during "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)) (declare (indent defun) (debug t))
(list (if (or (not (bound-and-true-p byte-compile-current-file)) (unless (and (symbolp targets)
(dolist (next (doom-enlist targets)) (memq targets doom-disabled-packages))
(if (symbolp next) (list (if (or (not (bound-and-true-p byte-compile-current-file))
(require next nil :no-error) (dolist (next (doom-enlist targets))
(load next :no-message :no-error)))) (if (symbolp next)
#'progn (require next nil :no-error)
#'with-no-warnings) (load next :no-message :no-error))))
(cond ((symbolp targets) #'progn
`(eval-after-load ',targets '(progn ,@body))) #'with-no-warnings)
((and (consp targets) (cond ((symbolp targets)
(memq (car targets) '(:or :any))) `(eval-after-load ',targets '(progn ,@body)))
`(progn ((and (consp targets)
,@(cl-loop for next in (cdr targets) (memq (car targets) '(:or :any)))
collect `(after! ,next ,@body)))) `(progn
((and (consp targets) ,@(cl-loop for next in (cdr targets)
(memq (car targets) '(:and :all))) collect `(after! ,next ,@body))))
(dolist (next (cdr targets)) ((and (consp targets)
(setq body `(after! ,next ,@body))) (memq (car targets) '(:and :all)))
body) (dolist (next (cdr targets))
((listp targets) (setq body `(after! ,next ,@body)))
`(after! (:all ,@targets) ,@body))))) body)
((listp targets)
`(after! (:all ,@targets) ,@body))))))
(defmacro quiet! (&rest forms) (defmacro quiet! (&rest forms)
"Run FORMS without making any output." "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 ,@forms
(cond ((functionp ,hook) (advice-remove ,hook #',fn)) (cond ((functionp ,hook) (advice-remove ,hook #',fn))
((symbolp ,hook) (remove-hook ,hook #',fn))) ((symbolp ,hook) (remove-hook ,hook #',fn)))
(unintern ',fn nil))) (fmakunbound ',fn)))
(cond ((functionp ,hook) (cond ((functionp ,hook)
(advice-add ,hook ,(if append :after :before) #',fn)) (advice-add ,hook ,(if append :after :before) #',fn))
((symbolp ,hook) ((symbolp ,hook)
(put ',fn 'permanent-local-hook t)
(add-hook ,hook #',fn ,append)))))) (add-hook ,hook #',fn ,append))))))
(defmacro add-hook! (&rest args) (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. 3. A function, list of functions, or body forms to be wrapped in a lambda.
Examples: 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! some-mode '(enable-something and-another))
(add-hook! '(one-mode-hook second-mode-hook) 'enable-something) (add-hook! '(one-mode-hook second-mode-hook) 'enable-something)
(add-hook! (one-mode second-mode) '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)))) (nreverse forms))))
(defmacro associate! (mode &rest plist) (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)) (declare (indent 1))
(unless noninteractive (unless noninteractive
(let ((modes (plist-get plist :modes)) (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) (not ,mode)
(and buffer-file-name (not (file-remote-p buffer-file-name))) (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 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)) ,(or pred-form t))
(,mode 1))) (,mode 1)))
,@(if (and modes (listp modes)) ,@(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)" (t (user-error "associate! invalid rules for mode [%s] (modes %s) (match %s) (files %s)"
mode modes match files)))))) 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) (provide 'core-lib)
;;; core-lib.el ends here ;;; core-lib.el ends here

View file

@ -30,20 +30,21 @@
;; Don't open files from the workspace in a new frame ;; Don't open files from the workspace in a new frame
ns-pop-up-frames nil) ns-pop-up-frames nil)
(cond ((display-graphic-p) (if (not (display-graphic-p))
;; A known problem with GUI Emacs on MacOS: it runs in an isolated (add-hook 'doom-post-init-hook #'osx-clipboard-mode)
;; environment, so envvars will be wrong. That includes the PATH ;; A known problem with GUI Emacs on MacOS: it runs in an isolated
;; Emacs picks up. `exec-path-from-shell' fixes this. ;; environment, so envvars will be wrong. That includes the PATH Emacs
(when (require 'exec-path-from-shell nil t) ;; picks up. `exec-path-from-shell' fixes this.
(def-setting! :env (&rest vars) (defun doom|init-exec-path ()
"Inject VARS from your shell environment into Emacs." (when (require 'exec-path-from-shell nil t)
`(exec-path-from-shell-copy-envs (list ,@vars))) (def-setting! :env (&rest vars)
(setq exec-path-from-shell-check-startup-files nil "Inject VARS from your shell environment into Emacs."
exec-path-from-shell-arguments (delete "-i" exec-path-from-shell-arguments)) `(exec-path-from-shell-copy-envs (list ,@vars)))
(defvaralias 'exec-path-from-shell-debug 'doom-debug-mode) (setq exec-path-from-shell-check-startup-files nil
(exec-path-from-shell-initialize))) exec-path-from-shell-arguments (delete "-i" exec-path-from-shell-arguments))
((require 'osx-clipboard nil t) (defvaralias 'exec-path-from-shell-debug 'doom-debug-mode)
(osx-clipboard-mode +1)))) (exec-path-from-shell-initialize)))
(add-hook 'doom-pre-init-hook #'doom|init-exec-path)))
(IS-LINUX (IS-LINUX
(setq x-gtk-use-system-tooltips nil ; native tooltips are ugly! (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 :config
(add-hook 'dired-before-readin-hook #'projectile-track-known-projects-find-file-hook) (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) (projectile-mode +1)
;; a more generic project root file ;; 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) (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. "Checks if the project has the specified FILES.
Paths are relative to the project root, unless they start with ./ or ../ (in 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, which case they're relative to `default-directory'). If they start with a slash,
they are absolute." 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) (defun doom-project-find-file (dir)
"Fuzzy-find a file under 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 "Hook run when a project is enabled. The name of the project's mode and its
state are passed in.") state are passed in.")
(defun doom|autoload-project-mode () (defun doom|init-project-mode ()
"Auto-enable the project(s) listed in `doom-project'." "Auto-enable the project(s) listed in `doom-project'."
(when doom-project (when doom-project
(if (symbolp 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 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'.") shorter major mode name in the mode-line. See `doom|set-mode-name'.")
;;
(defvar doom-init-ui-hook nil (defvar doom-init-ui-hook nil
"List of hooks to run when the UI has been initialized.") "List of hooks to run when the UI has been initialized.")
@ -57,7 +58,7 @@ with `doom//reload-theme').")
compilation-scroll-output 'first-error compilation-scroll-output 'first-error
confirm-nonexistent-file-or-buffer t confirm-nonexistent-file-or-buffer t
cursor-in-non-selected-windows nil ; hide cursors in other windows 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 display-line-numbers-width 3
enable-recursive-minibuffers nil enable-recursive-minibuffers nil
frame-inhibit-implied-resize t frame-inhibit-implied-resize t
@ -177,15 +178,11 @@ DEFAULT is non-nil, set the default mode-line for all buffers."
;; Plugins ;; Plugins
;; ;;
(def-package! ace-link ;; `avy'
:commands (ace-link-help ace-link-org ace-link-addr ace-link-mu4e)) (setq avy-all-windows nil
avy-background t)
(def-package! avy
:commands (avy-goto-char-2 avy-goto-line)
:config
(setq avy-all-windows nil
avy-background t))
;; `all-the-icons'
(def-package! all-the-icons (def-package! all-the-icons
:commands (all-the-icons-octicon all-the-icons-faicon all-the-icons-fileicon :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 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)) all-the-icons-wicon all-the-icons-alltheicon))
(advice-add fn :around #'doom*disable-all-the-icons-in-tty))) (advice-add fn :around #'doom*disable-all-the-icons-in-tty)))
(def-package! hideshow ; built-in ;; `hide-mode-line-mode'
:commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p) (add-hook 'completion-list-mode-hook #'hide-mode-line-mode)
:config (setq hs-hide-comments-when-hiding-all nil))
(def-package! hide-mode-line ;; `rainbow-delimiters' Helps us distinguish stacked delimiter pairs. Especially
:commands hide-mode-line-mode ;; in parentheses-drunk languages like Lisp.
:init (add-hook 'completion-list-mode-hook #'hide-mode-line-mode)) (def-package! rainbow-delimiters
:hook (lisp-mode . rainbow-delimiters-mode)
:config (setq rainbow-delimiters-max-face-count 3))
(def-package! highlight-indentation ;; `restart-emacs'
:commands (highlight-indentation-mode highlight-indentation-current-column-mode)) (setq restart-emacs--args (list "--restore"))
;; For modes with sub-par number fontification ;; `visual-fill-column' For a distractions-free-like UI, that dynamically
(def-package! highlight-numbers :commands highlight-numbers-mode) ;; 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 ;; Highlights the current line
(def-package! hl-line ; built-in (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-entry-hook #'doom|disable-hl-line)
(add-hook 'evil-visual-state-exit-hook #'doom|enable-hl-line-maybe))) (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 ;; undo/redo changes to Emacs' window layout
(def-package! winner (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 :preface (defvar winner-dont-bind-my-keys t) ; I'll bind keys myself
:config (winner-mode +1)) :config (winner-mode +1))
;; highlight matching delimiters ;; highlight matching delimiters
(def-package! paren (def-package! paren
:defer doom-before-switch-buffer-hook :after-call doom-before-switch-buffer-hook
:config :config
(setq show-paren-delay 0.1 (setq show-paren-delay 0.1
show-paren-highlight-openparen t 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)) (remove-hook 'kill-buffer-query-functions #'server-kill-buffer-query-function))
(add-hook 'server-visit-hook #'server-remove-kill-buffer-hook) (add-hook 'server-visit-hook #'server-remove-kill-buffer-hook)
;; whitespace-mode settings ;; `whitespace-mode'
(setq whitespace-line-column nil (setq whitespace-line-column nil
whitespace-style whitespace-style
'(face indentation tabs tab-mark spaces space-mark newline newline-mark '(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 #'switch-to-buffer :around #'doom*switch-buffer-hooks)
(advice-add #'display-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)) (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 _) (defun doom*load-theme-hooks (theme &rest _)
(setq doom-theme theme) (setq doom-theme theme)
@ -704,7 +688,7 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
;; ;;
(run-hooks 'doom-init-ui-hook)) (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) (provide 'core-ui)
;;; core-ui.el ends here ;;; core-ui.el ends here

View file

@ -1,5 +1,10 @@
;;; core.el --- the heart of the beast -*- lexical-binding: t; -*- ;;; 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" (defvar doom-version "2.0.9"
"Current version of DOOM emacs.") "Current version of DOOM emacs.")
@ -15,7 +20,7 @@ line or use --debug-init to enable this.")
;; ;;
(defvar doom-emacs-dir (defvar doom-emacs-dir
(eval-when-compile (file-truename user-emacs-directory)) (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/") (defvar doom-core-dir (concat doom-emacs-dir "core/")
"Where essential files are stored.") "Where essential files are stored.")
@ -44,14 +49,29 @@ Use this for files that change often, like cache files.")
(defvar doom-private-dir (defvar doom-private-dir
(eval-when-compile (eval-when-compile
(or (let ((xdg-path (concat (or (getenv "XDG_CONFIG_HOME") (or (let ((xdg-path
"~/.config") (expand-file-name "doom/"
"/doom/"))) (or (getenv "XDG_CONFIG_HOME")
"~/.config"))))
(if (file-directory-p xdg-path) xdg-path)) (if (file-directory-p xdg-path) xdg-path))
"~/.doom.d/")) "~/.doom.d/"))
"Where your private customizations are placed. Must end in a slash. Respects "Where your private customizations are placed. Must end in a slash. Respects
XDG directory conventions if ~/.config/doom exists.") 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 ;; UTF-8 as the default coding system
@ -70,6 +90,13 @@ XDG directory conventions if ~/.config/doom exists.")
debug-on-error doom-debug-mode debug-on-error doom-debug-mode
ffap-machine-p-known 'reject ; don't ping things that look like domain names ffap-machine-p-known 'reject ; don't ping things that look like domain names
idle-update-delay 2 ; update ui less often 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 ;; keep the point out of the minibuffer
minibuffer-prompt-properties '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt) 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) ;; 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-cache-directory (concat doom-cache-dir "url/")
url-configuration-directory (concat doom-etc-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 ;; Emacs fixes/hacks
@ -148,9 +161,12 @@ with functions that require it (like modeline segments)."
buffer)) buffer))
(advice-add #'make-indirect-buffer :around #'doom*set-indirect-buffer-filename) (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) (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 "Resets garbage collection settings to reasonable defaults (if you don't do
this, you'll get stuttering and random freezes) and resets this, you'll get stuttering and random freezes) and resets
`file-name-handler-alist'." `file-name-handler-alist'."
(unless noninteractive
(run-hooks 'doom-init-hook))
(setq file-name-handler-alist doom--file-name-handler-alist (setq file-name-handler-alist doom--file-name-handler-alist
gc-cons-threshold 16777216 gc-cons-threshold 8388608
gc-cons-percentage 0.15)) 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")) ;; Bootstrap Doom
(doom-initialize noninteractive) ;;
(add-hook! '(emacs-startup-hook doom-reload-hook) (add-to-list 'load-path doom-core-dir)
#'doom|finalize)
(when doom-private-dir (require 'core-lib)
(load (concat doom-private-dir "init") t t)) (require 'core-packages)
(require 'core-os)
(doom-initialize noninteractive)
(if noninteractive
(require 'core-dispatcher)
(doom-initialize-modules))
(provide 'core) (provide 'core)
;;; core.el ends here ;;; core.el ends here

View file

@ -36,3 +36,6 @@
;; core-keybinds.el ;; core-keybinds.el
(package! which-key) (package! which-key)
(package! hydra) (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,17 +7,18 @@
(dolist (bsym buffer-args) (dolist (bsym buffer-args)
(push `(,bsym (get-buffer-create ,(symbol-name bsym))) (push `(,bsym (get-buffer-create ,(symbol-name bsym)))
buffers)) buffers))
`(cl-flet ((buffer-list `(save-window-excursion
(lambda () (cl-flet ((buffer-list
(cl-remove-if-not #'buffer-live-p (list ,@(reverse (mapcar #'car buffers))))))) (lambda ()
(let* ((split-width-threshold 0) (cl-remove-if-not #'buffer-live-p (list ,@(reverse (mapcar #'car buffers)))))))
(window-min-width 0) (let* ((split-width-threshold 0)
persp-mode (window-min-width 0)
,@buffers) persp-mode
(delete-other-windows) ,@buffers)
,@body (delete-other-windows)
(let (kill-buffer-query-functions kill-buffer-hook) ,@body
(mapc #'kill-buffer (buffer-list))))))) (let (kill-buffer-query-functions kill-buffer-hook)
(mapc #'kill-buffer (buffer-list))))))))
;; ;;
(def-test! get-buffers (def-test! get-buffers
@ -93,7 +94,7 @@
(with-temp-buffers!! (a b c d e) (with-temp-buffers!! (a b c d e)
(dolist (buf (list a b)) (dolist (buf (list a b))
(with-current-buffer buf (with-current-buffer buf
(emacs-lisp-mode))) (delay-mode-hooks (emacs-lisp-mode))))
(dolist (buf (list c d e)) (dolist (buf (list c d e))
(with-current-buffer buf (with-current-buffer buf
(text-mode))) (text-mode)))

View file

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

View file

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

View file

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

View file

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

View file

@ -33,15 +33,15 @@
(should (equal (doom-project-expand "init.el") (should (equal (doom-project-expand "init.el")
(expand-file-name "init.el" (doom-project-root)))))) (expand-file-name "init.el" (doom-project-root))))))
;; `doom-project-has!' ;; `project-file-exists-p!'
(def-test! project-has! (def-test! project-has!
:minor-mode projectile-mode :minor-mode projectile-mode
(let ((default-directory doom-core-dir)) (let ((default-directory doom-core-dir))
;; Resolve from project root ;; Resolve from project root
(should (doom-project-has! "init.el")) (should (project-file-exists-p! "init.el"))
;; Chained file checks ;; Chained file checks
(should (doom-project-has! (and "init.el" "LICENSE"))) (should (project-file-exists-p! (and "init.el" "LICENSE")))
(should (doom-project-has! (or "init.el" "does-not-exist"))) (should (project-file-exists-p! (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" (or "LICENSE" "does-not-exist"))))
;; Should resolve relative paths from `default-directory' ;; 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) ;; Faster to disable these here (before they've been initialized)
(setq tool-bar-mode nil (setq tool-bar-mode nil
menu-bar-mode nil) menu-bar-mode nil
(set-scroll-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 ;; TODO Once Emacs 27 hits stable, perhaps replace init.el with early-init.el

View file

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

View file

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

View file

@ -2,9 +2,8 @@
;;;###autoload ;;;###autoload
(defun +impatient-mode/toggle () (defun +impatient-mode/toggle ()
"TODO" "Toggle `impatient-mode' in the current buffer."
(interactive) (interactive)
(require 'simple-httpd)
(unless (process-status "httpd") (unless (process-status "httpd")
(httpd-start)) (httpd-start))
(impatient-mode) (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 (def-package! company
:commands (company-mode global-company-mode company-complete :commands (company-complete-common company-manual-begin company-grab-line)
company-complete-common company-manual-begin company-grab-line)
:init :init
(setq company-idle-delay nil (setq company-idle-delay nil
company-tooltip-limit 14 company-tooltip-limit 14
@ -48,7 +47,8 @@ MODES should be one major-mode symbol or a list of them."
(def-package! company (def-package! company
:when (featurep! +auto) :when (featurep! +auto)
:defer pre-command-hook :defer 2
:after-call pre-command-hook
:config (setq company-idle-delay 0.2)) :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 (def-package! company-dict
:commands company-dict :defer t
:config :config
(defun +company|enable-project-dicts (mode &rest _) (defun +company|enable-project-dicts (mode &rest _)
"Enable per-project dictionaries." "Enable per-project dictionaries."
(if (symbol-value mode) (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)))) (setq company-dict-minor-mode-list (delq mode company-dict-minor-mode-list))))
(add-hook 'doom-project-hook #'+company|enable-project-dicts)) (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 (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 :config
(helm-mode +1) (helm-mode +1)
;; helm is too heavy for find-file-at-point ;; helm is too heavy for find-file-at-point
@ -40,7 +57,6 @@
helm-move-to-line-cycle-in-source t) helm-move-to-line-cycle-in-source t)
:config :config
(load "helm-autoloads" nil t)
(setq projectile-completion-system 'helm) (setq projectile-completion-system 'helm)
(defvar helm-projectile-find-file-map (make-sparse-keymap)) (defvar helm-projectile-find-file-map (make-sparse-keymap))
@ -72,20 +88,7 @@
(setq-local cursor-type nil)))) (setq-local cursor-type nil))))
(add-hook 'helm-minibuffer-set-up-hook #'+helm*hide-minibuffer-maybe) (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 (def-package! helm-locate
@ -94,40 +97,28 @@
:config (set-keymap-parent helm-generic-files-map helm-map)) :config (set-keymap-parent helm-generic-files-map helm-map))
(def-package! helm-bookmark (after! helm-bookmark
:commands helm-bookmark (setq-default helm-bookmark-show-location t))
:config (setq-default helm-bookmark-show-location t))
(def-package! helm-files (after! helm-files
:defer t
:config
(setq helm-boring-file-regexp-list (setq helm-boring-file-regexp-list
(append (list "\\.projects$" "\\.DS_Store$") (append (list "\\.projects$" "\\.DS_Store$")
helm-boring-file-regexp-list))) helm-boring-file-regexp-list)))
(def-package! helm-ag ;; `helm-ag'
:defer t (map! :after helm-ag
:config :map helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort)
(map! :map helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort))
(def-package! helm-css-scss ; https://github.com/ShingoFukuyama/helm-css-scss (after! 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
(setq helm-css-scss-split-direction #'split-window-vertically (setq helm-css-scss-split-direction #'split-window-vertically
helm-css-scss-split-with-multiple-windows t)) 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 (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 :config
(setq helm-swoop-use-line-number-face t (setq helm-swoop-use-line-number-face t
helm-swoop-candidate-number-limit 200 helm-swoop-candidate-number-limit 200
@ -135,9 +126,6 @@
helm-swoop-pre-input-function (lambda () ""))) helm-swoop-pre-input-function (lambda () "")))
(def-package! helm-describe-modes :commands helm-describe-modes)
(def-package! wgrep (def-package! wgrep
:commands (wgrep-setup wgrep-change-to-wgrep-mode) :commands wgrep-change-to-wgrep-mode
:config (setq wgrep-auto-save-buffer t)) :config (setq wgrep-auto-save-buffer t))

View file

@ -116,9 +116,9 @@ If ARG (universal argument), open selection in other-window."
"\\):?\\s-*\\(.+\\)") "\\):?\\s-*\\(.+\\)")
x) x)
(error (error
(message! (red "Error matching task in file: (%s) %s" (print! (red "Error matching task in file: (%s) %s"
(error-message-string ex) (error-message-string ex)
(car (split-string x ":")))) (car (split-string x ":"))))
nil)) nil))
collect `((type . ,(match-string 3 x)) collect `((type . ,(match-string 3 x))
(desc . ,(match-string 4 x)) (desc . ,(match-string 4 x))
@ -202,7 +202,6 @@ search current file. See `+ivy-task-tags' to customize what this searches for."
;; File searching ;; File searching
;; ;;
(defvar +ivy--file-last-search nil)
(defvar +ivy--file-search-recursion-p t) (defvar +ivy--file-search-recursion-p t)
(defvar +ivy--file-search-all-files-p nil) (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))) (let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning)))
(end (or (bound-and-true-p evil-visual-end) (region-end)))) (end (or (bound-and-true-p evil-visual-end) (region-end))))
(when (> (abs (- end beg)) 1) (when (> (abs (- end beg)) 1)
(rxt-quote-pcre (buffer-substring-no-properties beg end))))) (rxt-quote-pcre (buffer-substring-no-properties beg end)))))))
+ivy--file-last-search))
(prompt (prompt
(format "%s%%s %s" (format "%s%%s %s"
(symbol-name engine) (symbol-name engine)
@ -232,7 +230,6 @@ search current file. See `+ivy-task-tags' to customize what this searches for."
(t (t
(file-relative-name directory project-root))))) (file-relative-name directory project-root)))))
(default-directory directory)) (default-directory directory))
(setq +ivy--file-last-search query)
(require 'counsel) (require 'counsel)
(cl-letf (((symbol-function 'counsel-ag-function) (cl-letf (((symbol-function 'counsel-ag-function)
(symbol-function '+ivy*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 (def-package! ivy
:defer (pre-command-hook . 1) :defer 1
:after-call pre-command-hook
:config :config
(setq ivy-height 12 (setq ivy-height 15
ivy-do-completion-in-region nil ivy-do-completion-in-region nil
ivy-wrap t ivy-wrap t
ivy-fixed-height-minibuffer 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 "C-o" #'+ivy@coo/body
"M-o" #'ivy-dispatching-done-hydra) "M-o" #'ivy-dispatching-done-hydra)
:config :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) 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 (def-package! wgrep
:commands (wgrep-setup wgrep-change-to-wgrep-mode) :commands wgrep-change-to-wgrep-mode
:config (setq wgrep-auto-save-buffer t)) :config (setq wgrep-auto-save-buffer t))

View file

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

View file

@ -35,6 +35,15 @@
(sp-pair "'" nil :unless unless-list) (sp-pair "'" nil :unless unless-list)
(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 {|} => { | }
;; Expand {|} => { ;; Expand {|} => {
;; | ;; |

View file

@ -3,7 +3,8 @@
(def-package! realgud (def-package! realgud
:commands (realgud:gdb realgud:trepanjs realgud:bashdb realgud:zshdb) :commands (realgud:gdb realgud:trepanjs realgud:bashdb realgud:zshdb)
:config :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 ;; TODO Temporary Ex commands for the debugger
;; (def-tmp-excmd! doom:def-debug-on doom:def-debug-off ;; (def-tmp-excmd! doom:def-debug-on doom:def-debug-off

View file

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

View file

@ -1,6 +1,21 @@
;; feature/evil/autoload/evil.el -*- lexical-binding: t; -*- ;; feature/evil/autoload/evil.el -*- lexical-binding: t; -*-
;;;###if (featurep! :feature evil) ;;;###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 ;;;###autoload
(defun +evil/visual-indent () (defun +evil/visual-indent ()
"vnoremap < <gv" "vnoremap < <gv"
@ -80,6 +95,11 @@ evil-window-move-* (e.g. `evil-window-move-far-left')"
;;;###autoload ;;;###autoload
(defun +evil/window-move-down () "See `+evil--window-swap'" (interactive) (+evil--window-swap 'down)) (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) ;;;###autoload (autoload '+evil:apply-macro "feature/evil/autoload/evil" nil t)
(evil-define-operator +evil:apply-macro (beg end) (evil-define-operator +evil:apply-macro (beg end)
"Apply macro to each line." "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 ;; 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. ;; 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 (def-package! evil-collection
:when (featurep! +everywhere) :when (featurep! +everywhere)
:defer pre-command-hook :defer 1
:after-call post-command-hook
:preface :preface
;; must be set before evil/evil-collcetion is loaded ;; must be set before evil/evil-collcetion is loaded
(setq evil-want-integration nil (setq evil-want-integration nil
@ -61,7 +44,7 @@
evil-visual-state-cursor 'hollow) evil-visual-state-cursor 'hollow)
:config :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) (evil-select-search-module 'evil-search-module 'evil-search)
(set! :popup "^\\*evil-registers" '((size . 0.3))) (set! :popup "^\\*evil-registers" '((size . 0.3)))
@ -235,7 +218,7 @@
evil-escape-excluded-major-modes '(neotree-mode) evil-escape-excluded-major-modes '(neotree-mode)
evil-escape-key-sequence "jk" evil-escape-key-sequence "jk"
evil-escape-delay 0.25) 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) (map! :irvo "C-g" #'evil-escape)
:config :config
;; no `evil-escape' in minibuffer ;; no `evil-escape' in minibuffer
@ -325,7 +308,7 @@ the new algorithm is confusing, like in python or ruby."
(def-package! evil-snipe (def-package! evil-snipe
:commands (evil-snipe-mode evil-snipe-override-mode :commands (evil-snipe-mode evil-snipe-override-mode
evil-snipe-local-mode evil-snipe-override-local-mode) evil-snipe-local-mode evil-snipe-override-local-mode)
:defer pre-command-hook :after-call pre-command-hook
:init :init
(setq evil-snipe-smart-case t (setq evil-snipe-smart-case t
evil-snipe-scope 'line evil-snipe-scope 'line
@ -385,19 +368,6 @@ the new algorithm is confusing, like in python or ruby."
(push ">" evil-args-closers))) (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) ;; Multiple cursors compatibility (for the plugins that use it)
;; ;;

View file

@ -66,8 +66,12 @@ evil is loaded and enabled)."
;;;###autoload ;;;###autoload
(defun +file-templates-get-short-path () (defun +file-templates-get-short-path ()
"Fetches a short file path for the header in Doom module templates." "Fetches a short file path for the header in Doom module templates."
(when (string-match "/modules/\\(.+\\)$" buffer-file-truename) (let ((path (file-truename (or buffer-file-name default-directory))))
(match-string 1 buffer-file-truename))) (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,142 +6,137 @@
(expand-file-name "templates/" (file-name-directory load-file-name)) (expand-file-name "templates/" (file-name-directory load-file-name))
"The path to a directory of yasnippet folders to use for file templates.") "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 "__" (defvar +file-templates-default-trigger "__"
"The default yasnippet trigger key (a string) for file template rules that "The default yasnippet trigger key (a string) for file template rules that
don't have a :trigger property in `+file-templates-alist'.") don't have a :trigger property in `+file-templates-alist'.")
(defvar +file-templates-alist
`(;; General
(gitignore-mode)
(dockerfile-mode)
("/docker-compose\\.yml$" :mode yaml-mode)
("/Makefile$" :mode makefile-gmake-mode)
;; elisp
("/.dir-locals.el$")
("/packages\\.el$" :when +file-templates-in-emacs-dirs-p
:trigger "__doom-packages"
:mode emacs-lisp-mode)
("/doctor\\.el$" :when +file-templates-in-emacs-dirs-p
:trigger "__doom-doctor"
:mode emacs-lisp-mode)
("/test/.+\\.el$" :when +file-templates-in-emacs-dirs-p
:trigger "__doom-test"
:mode emacs-lisp-mode)
("\\.el$" :when +file-templates-in-emacs-dirs-p
:trigger "__doom-module"
:mode emacs-lisp-mode)
("-test\\.el$" :mode emacs-ert-mode)
(emacs-lisp-mode :trigger "__initfile")
(snippet-mode)
;; C/C++
("/main\\.c\\(?:c\\|pp\\)$" :trigger "__main.cpp" :mode c++-mode)
("/win32_\\.c\\(?:c\\|pp\\)$" :trigger "__winmain.cpp" :mode c++-mode)
("\\.c\\(?:c\\|pp\\)$" :trigger "__cpp" :mode c++-mode)
("\\.h\\(?:h\\|pp\\|xx\\)$" :trigger "__hpp" :mode c++-mode)
("\\.h$" :trigger "__h" :mode c-mode)
(c-mode :trigger "__c" :mode c-mode)
;; go
("/main\\.go$" :trigger "__main.go" :mode go-mode :project t)
(go-mode :trigger "__.go")
;; web-mode
("/normalize\\.scss$" :trigger "__normalize.scss" :mode scss-mode)
("/master\\.scss$" :trigger "__master.scss" :mode scss-mode)
("\\.html$" :trigger "__.html" :mode web-mode)
(scss-mode)
;; java
("/main\\.java$" :trigger "__main" :mode java-mode)
("/build\\.gradle$" :trigger "__build.gradle" :mode android-mode)
("/src/.+\\.java$" :mode java-mode)
;; javascript
("/package\\.json$" :trigger "__package.json" :mode json-mode)
("/bower\\.json$" :trigger "__bower.json" :mode json-mode)
("/gulpfile\\.js$" :trigger "__gulpfile.js" :mode js-mode)
("/webpack\\.config\\.js$" :trigger "__webpack.config.js" :mode js-mode)
("\\.js\\(?:on\\|hintrc\\)$" :mode json-mode)
;; Lua
("/main\\.lua$" :trigger "__main.lua" :mode love-mode)
("/conf\\.lua$" :trigger "__conf.lua" :mode love-mode)
;; Markdown
(markdown-mode)
;; Org
("\\.org$" :trigger "__" :mode org-mode)
("/README\\.org$"
:when +file-templates-in-emacs-dirs-p
:trigger "__doom-readme"
:mode org-mode)
;; PHP
("\\.class\\.php$" :trigger "__.class.php" :mode php-mode)
(php-mode)
;; Python
;; TODO ("tests?/test_.+\\.py$" :trigger "__" :mode nose-mode)
;; TODO ("/setup\\.py$" :trigger "__setup.py" :mode python-mode)
(python-mode)
;; Ruby
("/lib/.+\\.rb$" :trigger "__module" :mode ruby-mode :project t)
("/spec_helper\\.rb$" :trigger "__helper" :mode rspec-mode :project t)
("_spec\\.rb$" :mode rspec-mode :project t)
("/\\.rspec$" :trigger "__.rspec" :mode rspec-mode :project t)
("\\.gemspec$" :trigger "__.gemspec" :mode ruby-mode :project t)
("/Gemfile$" :trigger "__Gemfile" :mode ruby-mode :project t)
("/Rakefile$" :trigger "__Rakefile" :mode ruby-mode :project t)
(ruby-mode)
;; Rust
("/Cargo.toml$" :trigger "__Cargo.toml" :mode rust-mode)
("/main\\.rs$" :trigger "__main.rs" :mode rust-mode)
;; Slim
("/\\(?:index\\|main\\)\\.slim$" :mode slim-mode)
;; Shell scripts
("\\.zunit$" :trigger "__zunit" :mode sh-mode)
(fish-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.")
;; ;;
;; Bootstrap ;; Library
;; ;;
(after! yasnippet
(add-to-list 'yas-snippet-dirs '+file-templates-dir 'append #'eq))
(defun +file-template-p (rule) (defun +file-template-p (rule)
"Return t if RULE applies to the current buffer." "Return t if RULE applies to the current buffer."
(let ((pred (car rule)) (let ((pred (car rule))
(plist (cdr rule))) (plist (cdr rule)))
(and (cond ((stringp pred) (string-match-p pred)) (and (cond ((and (stringp pred) buffer-file-name) (string-match-p pred buffer-file-name))
((symbolp pred) (eq major-mode pred))) ((symbolp pred) (eq major-mode pred)))
(or (not (plist-member plist :when)) (or (not (plist-member plist :when))
(funcall (plist-get plist :when) buffer-file-name)) (funcall (plist-get plist :when) buffer-file-name))
rule))) 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) (defun +file-templates-in-emacs-dirs-p (file)
"Returns t if FILE is in Doom or your private directory." "Returns t if FILE is in Doom or your private directory."
(or (file-in-directory-p file doom-private-dir) (or (file-in-directory-p file doom-private-dir)
(file-in-directory-p file doom-emacs-dir))) (file-in-directory-p file doom-emacs-dir)))
(setq +file-templates-alist (defun +file-templates|check ()
`(;; General "Check if the current buffer is a candidate for file template expansion. It
(gitignore-mode) must be non-read-only, empty, and there must be a rule in
(dockerfile-mode) `+file-templates-alist' that applies to it."
("/docker-compose\\.yml$" :mode yaml-mode) (when (and (not buffer-read-only)
("/Makefile$" :mode makefile-gmake-mode) (bobp) (eobp)
;; elisp (not (string-match-p "^ *\\*" (buffer-name))))
("/.dir-locals.el$") (when-let* ((rule (cl-find-if #'+file-template-p +file-templates-alist)))
("/packages\\.el$" :when +file-templates-in-emacs-dirs-p (apply #'+file-templates--expand rule))))
:trigger "__doom-packages"
:mode emacs-lisp-mode)
("/doctor\\.el$" :when +file-templates-in-emacs-dirs-p
:trigger "__doom-doctor"
:mode emacs-lisp-mode)
("/test/.+\\.el$" :when +file-templates-in-emacs-dirs-p
:trigger "__doom-test"
:mode emacs-lisp-mode)
("\\.el$" :when +file-templates-in-emacs-dirs-p
:trigger "__doom-module"
:mode emacs-lisp-mode)
("-test\\.el$" :mode emacs-ert-mode)
(emacs-lisp-mode :trigger "__initfile")
(snippet-mode)
;; C/C++
("/main\\.c\\(?:c\\|pp\\)$" :trigger "__main.cpp" :mode c++-mode)
("/win32_\\.c\\(?:c\\|pp\\)$" :trigger "__winmain.cpp" :mode c++-mode)
("\\.c\\(?:c\\|pp\\)$" :trigger "__cpp" :mode c++-mode)
("\\.h\\(?:h\\|pp\\|xx\\)$" :trigger "__hpp" :mode c++-mode)
("\\.h$" :trigger "__h" :mode c-mode)
(c-mode :trigger "__c" :mode c-mode)
;; go
("/main\\.go$" :trigger "__main.go" :mode go-mode :project t)
(go-mode :trigger "__.go")
;; web-mode
("/normalize\\.scss$" :trigger "__normalize.scss" :mode scss-mode)
("/master\\.scss$" :trigger "__master.scss" :mode scss-mode)
("\\.html$" :trigger "__.html" :mode web-mode)
(scss-mode)
;; java
("/main\\.java$" :trigger "__main" :mode java-mode)
("/build\\.gradle$" :trigger "__build.gradle" :mode android-mode)
("/src/.+\\.java$" :mode java-mode)
;; javascript
("/package\\.json$" :trigger "__package.json" :mode json-mode)
("/bower\\.json$" :trigger "__bower.json" :mode json-mode)
("/gulpfile\\.js$" :trigger "__gulpfile.js" :mode js-mode)
("/webpack\\.config\\.js$" :trigger "__webpack.config.js" :mode js-mode)
("\\.js\\(?:on\\|hintrc\\)$" :mode json-mode)
;; Lua
("/main\\.lua$" :trigger "__main.lua" :mode love-mode)
("/conf\\.lua$" :trigger "__conf.lua" :mode love-mode)
;; Markdown
(markdown-mode)
;; Org
("\\.org$" :trigger "__" :mode org-mode)
("/README\\.org$"
:when +file-templates-in-emacs-dirs-p
:trigger "__doom-readme"
:mode org-mode)
;; PHP
("\\.class\\.php$" :trigger "__.class.php" :mode php-mode)
(php-mode)
;; Python
;; TODO ("tests?/test_.+\\.py$" :trigger "__" :mode nose-mode)
;; TODO ("/setup\\.py$" :trigger "__setup.py" :mode python-mode)
(python-mode)
;; Ruby
("/lib/.+\\.rb$" :trigger "__module" :mode ruby-mode :project t)
("/spec_helper\\.rb$" :trigger "__helper" :mode rspec-mode :project t)
("_spec\\.rb$" :mode rspec-mode :project t)
("/\\.rspec$" :trigger "__.rspec" :mode rspec-mode :project t)
("\\.gemspec$" :trigger "__.gemspec" :mode ruby-mode :project t)
("/Gemfile$" :trigger "__Gemfile" :mode ruby-mode :project t)
("/Rakefile$" :trigger "__Rakefile" :mode ruby-mode :project t)
(ruby-mode)
;; Rust
("/Cargo.toml$" :trigger "__Cargo.toml" :mode rust-mode)
("/main\\.rs$" :trigger "__main.rs" :mode rust-mode)
;; Slim
("/\\(?:index\\|main\\)\\.slim$" :mode slim-mode)
;; Shell scripts
("\\.zunit$" :trigger "__zunit" :mode sh-mode)
(fish-mode)
(sh-mode)
))
;; ;;
;; Plugins ;; 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. ${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 + If possible, include a brief list of feature highlights here
+ Include links to major plugins that the module uses, if applicable + Like code completion, syntax checking or available snippets
+ Use links whenever you can + Include links to packages & external things where possible
+ Mention dependencies on other modules here}
* Table of Contents :TOC: * Table of Contents :TOC:
@ -25,11 +24,15 @@ This module provides no flags.
This module has no prereqisites. This module has no prereqisites.
* Features * 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 * Configuration
How to configure this module, including common problems and how to address them.
* Appendix * Appendix
** Commands ** 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 ** Hacks
+ Include a list of ways this module changes default behavior
$0 $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 identifier
(+lookup--online-provider (not current-prefix-arg)))))) (+lookup--online-provider (not current-prefix-arg))))))
(defvar ffap-file-finder)
;;;###autoload ;;;###autoload
(defun +lookup/file (path) (defun +lookup/file (path)
"Figure out PATH from whatever is at point and open it. "Figure out PATH from whatever is at point and open it.

View file

@ -122,33 +122,29 @@ ones."
;; ;;
(def-package! dumb-jump (def-package! dumb-jump
:commands (dumb-jump-go dumb-jump-quick-look :commands dumb-jump-result-follow
dumb-jump-back dumb-jump-result-follow)
:config :config
(setq dumb-jump-default-project doom-emacs-dir (setq dumb-jump-default-project doom-emacs-dir
dumb-jump-aggressive nil dumb-jump-aggressive nil
dumb-jump-selector dumb-jump-selector
(cond ((featurep! :completion ivy) 'ivy) (cond ((featurep! :completion ivy) 'ivy)
((featurep! :completion helm) 'helm) ((featurep! :completion helm) 'helm)
(t 'popup)))) ('popup))))
;; ;;
;; xref ;; xref
;; ;;
(def-package! xref ;; By default, `etags--xref-backend' is the default xref backend. No need. We'll
:commands (xref-backend-identifier-at-point xref-find-definitions xref-find-references) ;; set these up ourselves in other modules.
:config (setq-default xref-backend-functions '(t))
;; 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. ;; ...however, it breaks `projectile-find-tag', unless we put it back.
(defun +lookup*projectile-find-tag (orig-fn) (defun +lookup*projectile-find-tag (orig-fn)
(let ((xref-backend-functions '(etags--xref-backend t))) (let ((xref-backend-functions '(etags--xref-backend t)))
(funcall orig-fn))) (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 (def-package! ivy-xref
@ -168,41 +164,9 @@ ones."
;; ;;
(when (featurep! +docsets) (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 ;; Both packages depend on helm-dash
(def-package! helm-dash (def-package! helm-dash
:commands (helm-dash helm-dash-install-docset helm-dash-at-point :defer t
helm-dash-docset-installed-p helm-dash-installed-docsets)
:init :init
(setq helm-dash-enable-debugging doom-debug-mode (setq helm-dash-enable-debugging doom-debug-mode
helm-dash-browser-func #'eww) helm-dash-browser-func #'eww)
@ -214,7 +178,7 @@ Used by `+lookup/in-docsets' and `+lookup/documentation'."
(def-package! counsel-dash (def-package! counsel-dash
:when (featurep! :completion ivy) :when (featurep! :completion ivy)
:commands (counsel-dash counsel-dash-install-docset) :commands counsel-dash-install-docset
:config (setq counsel-dash-min-length 2))) :config (setq counsel-dash-min-length 2)))
@ -223,20 +187,11 @@ Used by `+lookup/in-docsets' and `+lookup/documentation'."
;; ;;
(when (featurep! +devdocs) (when (featurep! +devdocs)
(def-setting! :devdocs (modes docset) (after! devdocs-lookup
"Map major MODES (one major-mode symbol or a list of them) to a devdocs (unless (assoc "SCSS" devdocs-subjects)
DOCSET (a string). (setq devdocs-subjects
(append '(("SCSS" "scss")
See `devdocs-alist' for the defaults. " ("GFM" "markdown")
`(dolist (mode ',modes) ("Typescript" "typescript"))
(push (cons mode ,docset) devdocs-alist))) devdocs-subjects)))))
(def-package! devdocs-lookup
:commands (devdocs-setup devdocs-lookup)
:config
(setq devdocs-subjects
(append '(("SCSS" "scss")
("GFM" "markdown")
("Typescript" "typescript"))
devdocs-subjects))))

View file

@ -1,9 +1,16 @@
;;; feature/snippets/config.el -*- lexical-binding: t; -*- ;;; 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 (def-package! yasnippet
:commands (yas-minor-mode yas-minor-mode-on yas-expand yas-expand-snippet :commands (yas-minor-mode-on yas-expand yas-expand-snippet yas-lookup-snippet
yas-lookup-snippet yas-insert-snippet yas-new-snippet yas-insert-snippet yas-new-snippet yas-visit-snippet-file)
yas-visit-snippet-file snippet-mode)
:preface :preface
(defvar yas-minor-mode-map (defvar yas-minor-mode-map
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
@ -23,28 +30,25 @@
(setq yas-verbosity (if doom-debug-mode 3 0) (setq yas-verbosity (if doom-debug-mode 3 0)
yas-also-auto-indent-first-line t yas-also-auto-indent-first-line t
yas-prompt-functions (delq #'yas-dropdown-prompt yas-prompt-functions) yas-prompt-functions (delq #'yas-dropdown-prompt yas-prompt-functions)
;; Allow nested snippets yas-triggers-in-field t) ; Allow nested snippets
yas-triggers-in-field t)
(cl-pushnew (expand-file-name "snippets/" doom-private-dir) yas-snippet-dirs (add-to-list 'yas-snippet-dirs '+snippets-dir nil #'eq)
:test #'string=)
(defun +snippets|enable-project-modes (mode &rest _) (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) (if (symbol-value mode)
(yas-activate-extra-mode mode) (yas-activate-extra-mode mode)
(yas-deactivate-extra-mode mode))) (yas-deactivate-extra-mode mode)))
(add-hook 'doom-project-hook #'+snippets|enable-project-modes) (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 ;; 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 (after! auto-yasnippet
:commands (aya-create aya-expand aya-open-line aya-persist-snippet)
:config
(setq aya-persist-snippets-dir (concat doom-local-dir "auto-snippets/"))) (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)") (setq-hook! 'LaTeX-mode-hook +spellcheck-immediately nil)")
(def-package! flyspell ; built-in (def-package! flyspell ; built-in
:commands flyspell-mode :defer t
:init :init
(add-hook 'flyspell-mode-hook #'+spellcheck|immediately) (add-hook 'flyspell-mode-hook #'+spellcheck|immediately)
:config :config

View file

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

View file

@ -1,18 +1,11 @@
;;; feature/syntax-checker/config.el -*- lexical-binding: t; -*- ;;; 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 (def-package! flycheck
:commands (flycheck-mode flycheck-list-errors flycheck-buffer) :commands (flycheck-list-errors flycheck-buffer)
:config :config
;; Emacs feels snappier without checks on newline ;; Emacs feels snappier without checks on newline
(setq flycheck-check-syntax-automatically '(save idle-change mode-enabled)) (setq flycheck-check-syntax-automatically '(save idle-change mode-enabled))
;; Popup
(add-hook 'flycheck-mode-hook #'+syntax-checker-popup-mode)
(after! evil (after! evil
(defun +syntax-checkers|flycheck-buffer () (defun +syntax-checkers|flycheck-buffer ()
"Flycheck buffer on ESC in normal mode." "Flycheck buffer on ESC in normal mode."
@ -20,21 +13,16 @@
(ignore-errors (flycheck-buffer)) (ignore-errors (flycheck-buffer))
nil)) nil))
(add-hook 'doom-escape-hook #'+syntax-checkers|flycheck-buffer t) (add-hook 'doom-escape-hook #'+syntax-checkers|flycheck-buffer t)
(add-hook 'evil-insert-state-exit-hook #'+syntax-checkers|flycheck-buffer) (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)))
(def-package! flycheck-popup-tip (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 (def-package! flycheck-posframe
:when EMACS26+ :when (and EMACS26+ (featurep! +childframe))
:when (featurep! +childframe)
:commands flycheck-posframe-show-posframe :commands flycheck-posframe-show-posframe
:config :config
(setq flycheck-posframe-warning-prefix "" (setq flycheck-posframe-warning-prefix ""

View file

@ -1,10 +1,5 @@
;;; feature/version-control/+git.el -*- lexical-binding: t; -*- ;;; 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) (when (featurep! :feature evil)
(add-hook 'git-commit-mode-hook #'evil-insert-state)) (add-hook 'git-commit-mode-hook #'evil-insert-state))
@ -33,7 +28,7 @@
(ignore (git-gutter)))) (ignore (git-gutter))))
(add-hook 'doom-escape-hook #'+version-control|update-git-gutter t)) (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) (:body-pre (git-gutter-mode 1) :hint nil)
" "
@ -59,7 +54,7 @@
(def-package! git-timemachine (def-package! git-timemachine
:commands (git-timemachine git-timemachine-toggle) :defer t
:config :config
;; Sometimes I forget `git-timemachine' is enabled in a buffer, so instead of ;; Sometimes I forget `git-timemachine' is enabled in a buffer, so instead of
;; showing revision details in the minibuffer, show them in ;; showing revision details in the minibuffer, show them in
@ -67,10 +62,6 @@
(setq git-timemachine-show-minibuffer-details t) (setq git-timemachine-show-minibuffer-details t)
(advice-add #'git-timemachine--show-minibuffer-details :override #'+vcs*update-header-line) (advice-add #'git-timemachine--show-minibuffer-details :override #'+vcs*update-header-line)
;; Force evil to rehash keybindings for the current state (after! evil
(add-hook 'git-timemachine-mode-hook #'evil-force-normal-state)) ;; 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))

View file

@ -28,11 +28,11 @@
(defalias #'smerge-diff-upper-lower #'smerge-diff-mine-other) (defalias #'smerge-diff-upper-lower #'smerge-diff-mine-other)
(defalias #'smerge-diff-base-lower #'smerge-diff-base-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) :pre (smerge-mode 1)
;; Disable `smerge-mode' when quitting hydra if ;; Disable `smerge-mode' when quitting hydra if
;; no merge conflicts remain. ;; no merge conflicts remain.
:post (smerge-auto-leave)) :post (smerge-auto-leave))
" "
Movement Keep Diff Other smerge Movement Keep Diff Other smerge

View file

@ -211,7 +211,7 @@ current workspace (by name) from session files."
(completing-read (completing-read
"Workspace to load: " "Workspace to load: "
(persp-list-persp-names-in-file (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)) (if (not (+workspace-load name))
(+workspace-error (format "Couldn't load workspace %s" name)) (+workspace-error (format "Couldn't load workspace %s" name))
(+workspace/switch-to name) (+workspace/switch-to name)

View file

@ -27,7 +27,7 @@ new project directory.")
stored in `persp-save-dir'.") stored in `persp-save-dir'.")
(defun +workspaces-restore-last-session (&rest _) (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) (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 (display-buffer-in-side-window
warnings '((window-height . shrink-window-if-larger-than-buffer)))))))))) 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 :config
(setq persp-autokill-buffer-on-remove 'kill-weak (setq persp-autokill-buffer-on-remove 'kill-weak
persp-nil-hidden t persp-nil-hidden t

View file

@ -2,6 +2,7 @@
;;; feature/workspaces/test/autoload-workspaces.el ;;; feature/workspaces/test/autoload-workspaces.el
(require! :feature workspaces) (require! :feature workspaces)
(doom|init-custom-hooks)
(defmacro with-workspace!! (buffer-args &rest body) (defmacro with-workspace!! (buffer-args &rest body)
(declare (indent defun)) (declare (indent defun))
@ -13,7 +14,8 @@
(require 'persp-mode) (require 'persp-mode)
(let (noninteractive) (let (noninteractive)
(persp-mode +1)) (persp-mode +1))
(+workspace-switch +workspaces-main t) (let (persp-before-switch-functions persp-activated-functions)
(+workspace-switch +workspaces-main t))
(let* (,@buffers) (let* (,@buffers)
(cl-loop with persp = (get-current-persp) (cl-loop with persp = (get-current-persp)
for buf in (list ,@(mapcar #'car buffers)) 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) (interactive)
(unless (memq major-mode '(c-mode c++-mode objc-mode)) (unless (memq major-mode '(c-mode c++-mode objc-mode))
(user-error "Not a C/C++/ObjC buffer")) (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")) (user-error "No compile_commands.json file"))
;; first rtag ;; first rtag
(when (and (featurep 'rtags) (when (and (featurep 'rtags)
@ -89,13 +89,6 @@ compilation dbs."
nconc (list "-I" path))) nconc (list "-I" path)))
(doom-project-root))))) (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 ;;;###autoload
(defun +cc|cleanup-rtags () (defun +cc|cleanup-rtags ()
"Kill rtags server(s) if there are no C/C++ buffers open." "Kill rtags server(s) if there are no C/C++ buffers open."

View file

@ -55,10 +55,10 @@ compilation database is present in the project.")
:config :config
(set! :electric '(c-mode c++-mode objc-mode java-mode) (set! :electric '(c-mode c++-mode objc-mode java-mode)
:chars '(?\n ?\})) :chars '(?\n ?\}))
(set! :company-backend (set! :company-backend
'(c-mode c++-mode objc-mode) '(c-mode c++-mode objc-mode)
'(company-irony-c-headers company-irony)) '(company-irony-c-headers company-irony))
;;; Style/formatting ;;; Style/formatting
;; C/C++ style settings ;; C/C++ style settings
@ -101,8 +101,8 @@ compilation database is present in the project.")
(label . 0)))) (label . 0))))
;;; Keybindings ;;; Keybindings
;; Completely disable electric keys because it interferes with smartparens and ;; Disable electric keys because it interferes with smartparens and custom
;; custom bindings. We'll do this ourselves. ;; bindings. We'll do it ourselves (mostly).
(setq c-tab-always-indent nil (setq c-tab-always-indent nil
c-electric-flag nil) c-electric-flag nil)
(dolist (key '("#" "}" "/" "*" ";" "," ":" "(" ")" "\177")) (dolist (key '("#" "}" "/" "*" ";" "," ":" "(" ")" "\177"))
@ -129,6 +129,7 @@ compilation database is present in the project.")
(def-package! irony (def-package! irony
:when (featurep! +irony)
:commands (irony-install-server irony-mode) :commands (irony-install-server irony-mode)
:preface :preface
(setq irony-server-install-prefix (concat doom-etc-dir "irony-server/")) (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 (def-package! cmake-mode
:mode "/CMakeLists\\.txt$" :defer t
:mode "\\.cmake\\$"
:config :config
(set! :company-backend 'cmake-mode '(company-cmake company-yasnippet))) (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! demangle-mode
:hook llvm-mode)
(def-package! glsl-mode
:mode "\\.glsl$"
:mode "\\.vert$"
:mode "\\.frag$"
:mode "\\.geom$")
;; ;;
@ -213,7 +204,12 @@ compilation database is present in the project.")
(def-package! rtags (def-package! rtags
:commands rtags-executable-find :commands rtags-executable-find
:init :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 :config
(setq rtags-autostart-diagnostics t (setq rtags-autostart-diagnostics t
rtags-use-bookmarks nil 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))) (warn! "Couldn't find the rtag client and/or server programs %s. Disabling rtags support" bins)))
;; irony server ;; irony server
(require 'irony) (when (require 'irony nil t)
(unless (file-directory-p irony-server-install-prefix) (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) (when (featurep! :completion company)
;; glslangValidator ;; glslangValidator

View file

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

View file

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

View file

@ -1,17 +1,16 @@
;;; lang/csharp/config.el -*- lexical-binding: t; -*- ;;; lang/csharp/config.el -*- lexical-binding: t; -*-
(def-package! csharp-mode :mode "\\.cs$") (add-to-list 'auto-mode-alist '("\\.shader$" . shader-mode)) ; unity shaders
(def-package! shader-mode :mode "\\.shader$") ; unity shaders
(def-package! omnisharp (def-package! omnisharp
:after csharp-mode :hook (csharp-mode . omnisharp-mode)
:commands omnisharp-install-server
:preface :preface
(setq omnisharp-auto-complete-want-documentation nil (setq omnisharp-auto-complete-want-documentation nil
omnisharp-cache-directory (concat doom-cache-dir "omnisharp")) omnisharp-cache-directory (concat doom-cache-dir "omnisharp"))
:config :config
(add-hook! csharp-mode #'(flycheck-mode omnisharp-mode)) (add-hook 'csharp-mode-hook #'flycheck-mode)
(defun +csharp|cleanup-omnisharp-server () (defun +csharp|cleanup-omnisharp-server ()
"Clean up the omnisharp server once you kill the last csharp-mode buffer." "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; -*- ;;; 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 (def-package! graphql-mode
:mode "\\.g\\(?:raph\\)?ql$") :mode "\\.gql\\'")
(def-package! hexl ; For ROM hacking or debugging
:mode ("\\.hex$" . hexl-mode)
:mode ("\\.nes$" . hexl-mode))
(def-package! json-mode (def-package! json-mode
:mode "\\.js\\(?:on\\|[hl]int\\(rc\\)?\\)$" :mode "\\.js\\(?:on\\|[hl]int\\(rc\\)?\\)\\'"
:config :config
(when (featurep! :feature syntax-checker) (when (featurep! :feature syntax-checker)
(add-hook 'json-mode-hook #'flycheck-mode)) (add-hook 'json-mode-hook #'flycheck-mode))
(set! :electric 'json-mode :chars '(?\n ?: ?{ ?}))) (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 (def-package! vimrc-mode
:mode "/\\.?g?vimrc$" :mode "\\.?vimperatorrc\\'")
:mode "\\.vimp?$"
:mode "\\.?vimperatorrc$")
(def-package! yaml-mode
:mode "\\.ya?ml$")
;; ;;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,10 +4,7 @@
;; Plugins ;; Plugins
;; ;;
(def-package! go-mode (after! go-mode
:mode "\\.go$"
:interpreter "go"
:config
(set! :env "GOPATH" "GOROOT") (set! :env "GOPATH" "GOROOT")
(set! :repl 'go-mode #'gorepl-run) (set! :repl 'go-mode #'gorepl-run)
(set! :lookup 'go-mode (set! :lookup 'go-mode
@ -15,11 +12,12 @@
:references #'go-guru-referrers :references #'go-guru-referrers
:documentation #'godoc-at-point) :documentation #'godoc-at-point)
(when (executable-find "goimports") (when-let* ((goimports (executable-find "goimports")))
(setq gofmt-command "goimports")) (setq gofmt-command goimports))
(setq gofmt-show-errors nil) ; Leave it to flycheck (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! go-mode
(add-hook 'before-save-hook #'gofmt-before-save nil t)) (add-hook 'before-save-hook #'gofmt-before-save nil t))
@ -70,25 +68,13 @@
:v "r" #'go-play-region)) :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 (def-package! gorepl-mode
:commands (gorepl-run gorepl-run-load-current-file)) :commands gorepl-run-load-current-file)
(def-package! company-go (def-package! company-go
:when (featurep! :completion company) :when (featurep! :completion company)
:init (setq command-go-gocode-command "gocode")
:after go-mode :after go-mode
:config :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 ;; Common plugins
;; ;;
(def-package! haskell-mode (after! 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)
(set! :repl 'haskell-mode #'switch-to-haskell) (set! :repl 'haskell-mode #'switch-to-haskell)
(push ".hi" completion-ignored-extensions) (add-to-list 'completion-ignored-extensions ".hi"))
(autoload 'switch-to-haskell "inf-haskell" nil t)
(after! inf-haskell
(map! :map inferior-haskell-mode-map "ESC ESC" #'+popup/close)))

View file

@ -1,8 +1,8 @@
;;; lang/hy/config.el -*- lexical-binding: t; -*- ;;; lang/hy/config.el -*- lexical-binding: t; -*-
(def-package! hy-mode (def-package! hy-mode
:mode "\\.hy$" :mode "\\.hy\\'"
:interpreter "hy" :interpreter "hy"
:config :config
(set! :repl 'hy-mode #'hy-shell-start-or-switch-to-shell) (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,9 +24,9 @@
;;;###autoload ;;;###autoload
(defun +java|android-mode-maybe () (defun +java|android-mode-maybe ()
(when (doom-project-has! (or "local.properties" (when (project-file-exists-p! (or "local.properties"
"AndroidManifest.xml" "AndroidManifest.xml"
"src/main/AndroidManifest.xml")) "src/main/AndroidManifest.xml"))
(android-mode +1) (android-mode +1)
(doom/set-build-command "./gradlew %s" "build.gradle"))) (doom/set-build-command "./gradlew %s" "build.gradle")))

View file

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

View file

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

View file

@ -1,7 +1,6 @@
;;; lang/julia/config.el -*- lexical-binding: t; -*- ;;; lang/julia/config.el -*- lexical-binding: t; -*-
(use-package julia-mode (use-package julia-mode
:mode "\\.jl$"
:interpreter "julia" :interpreter "julia"
:config :config
(set! :repl 'julia-mode #'+julia/repl) (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." "Sets the directory where AUCTeX will search for PDFs associated to BibTeX references."
`(setq +latex-bibtex-dir ,dir)) `(setq +latex-bibtex-dir ,dir))
;; sp's default latex rules are obnoxious, so disable them
(provide 'smartparens-latex)
;; ;;
;; Plugins ;; Plugins
;; ;;
(def-package! tex-site (after! 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
;; Set some varibles to fontify common LaTeX commands. ;; Set some varibles to fontify common LaTeX commands.
(load! +fontification) (load! +fontification)
(setq ;; Enable parse on load. (setq ;; Enable parse on load.
@ -182,7 +173,6 @@
(def-package! bibtex (def-package! bibtex
:defer t :defer t
:mode ("\\.bib\\'" . bibtex-mode)
:config :config
(setq bibtex-dialect 'biblatex (setq bibtex-dialect 'biblatex
bibtex-align-at-equal-sign t bibtex-align-at-equal-sign t

View file

@ -1,8 +1,7 @@
;;; lang/ledger/config.el -*- lexical-binding: t; -*- ;;; lang/ledger/config.el -*- lexical-binding: t; -*-
(def-package! ledger-mode ;; `ledger-mode'
:mode "\\.ledger$" (setq ledger-clear-whole-transactions 1)
:config (setq ledger-clear-whole-transactions 1))
(def-package! evil-ledger (def-package! evil-ledger
@ -12,4 +11,5 @@
(def-package! flycheck-ledger (def-package! flycheck-ledger
:when (featurep! :feature syntax-checker) :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; -*- ;;; lang/lua/config.el -*- lexical-binding: t; -*-
(def-package! lua-mode (after! lua-mode
:mode "\\.lua$"
:interpreter "lua"
:init
;; sp's default lua rules are obnoxious, so disable them. Use snippets
;; instead!
(provide 'smartparens-lua)
:config
(add-hook 'lua-mode-hook #'flycheck-mode) (add-hook 'lua-mode-hook #'flycheck-mode)
(set! :lookup 'lua-mode :documentation 'lua-search-documentation) (set! :lookup 'lua-mode :documentation 'lua-search-documentation)
(set! :electric 'lua-mode :words '("else" "end")) (set! :electric 'lua-mode :words '("else" "end"))
(set! :repl 'lua-mode #'+lua/repl) (set! :repl 'lua-mode #'+lua/repl)
(set! :company-backend 'lua-mode '(company-lua company-yasnippet))
(def-menu! +lua/build-menu (def-menu! +lua/build-menu
"Build/compilation commands for `lua-mode' buffers." "Build/compilation commands for `lua-mode' buffers."
@ -24,15 +18,8 @@
:n "b" #'+lua/build-menu)) :n "b" #'+lua/build-menu))
(def-package! company-lua (after! moonscript
:after (:all company lua-mode) (defvaralias 'moonscript-indent-offset 'tab-width))
:config
(set! :company-backend 'lua-mode '(company-lua company-yasnippet)))
(def-package! moonscript
:mode ("\\.moon$" . moonscript-mode)
:config (defvaralias 'moonscript-indent-offset 'tab-width))
;; ;;

View file

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

View file

@ -1,32 +1,20 @@
;;; lang/nim/config.el -*- lexical-binding: t; -*- ;;; lang/nim/config.el -*- lexical-binding: t; -*-
(def-package! nim-mode (after! nim-mode
:mode "\\.nim\\'"
:mode ("\\.nim\\(ble\\|s\\)\\'" . nimscript-mode)
:config
(load "nim-mode-autoloads" nil t)
;; NOTE nim-mode autoloads sets up xref
(defun +nim|init-nimsuggest-mode () (defun +nim|init-nimsuggest-mode ()
"Conditionally load `nimsuggest-mode', instead of clumsily erroring out if "Conditionally load `nimsuggest-mode', instead of clumsily erroring out if
nimsuggest isn't installed." nimsuggest isn't installed."
(when (executable-find "nimsuggest") (when (file-executable-p nimsuggest-path)
(nimsuggest-mode))) (nimsuggest-mode)))
(add-hook 'nim-mode-hook #'+nim|init-nimsuggest-mode) (add-hook 'nim-mode-hook #'+nim|init-nimsuggest-mode)
(map! :map nim-mode-map (map! :map nim-mode-map
:localleader :localleader
:n "b" #'+nim/build-menu) :n "b" #'nim-compile))
(def-menu! +nim/build-menu
"Building commands for `nim-mode' buffers."
'(("Build & run" :exec nim-compile))
:prompt "Build"))
(def-package! flycheck-nim (def-package! flycheck-nim
:when (featurep! :feature syntax-checker) :when (featurep! :feature syntax-checker)
:after nim-mode :after nim-mode
:config :config (add-hook 'nimsuggest-mode-hook #'flycheck-mode))
(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; -*- ;;; lang/ocaml/config.el -*- lexical-binding: t; -*-
(def-package! tuareg (def-package! tuareg
:mode ("\\.ml[4ilpy]?$" . tuareg-mode)) :mode ("\\.ml[4ilpy]?\\'" . tuareg-mode))
(def-package! merlin (def-package! merlin
:after tuareg :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 ;; Plugins
;; ;;
(def-package! toc-org ;; `toc-org'
:commands toc-org-enable (setq toc-org-hrefify-default "org")
:config (setq toc-org-hrefify-default "org"))
(def-package! org-bullets
:commands org-bullets-mode)
(def-package! evil-org (def-package! evil-org
:when (featurep! :feature evil) :when (featurep! :feature evil)
@ -126,7 +122,13 @@ unfold to point on startup."
org-agenda-dim-blocked-tasks nil org-agenda-dim-blocked-tasks nil
org-agenda-files (ignore-errors (directory-files +org-dir t "\\.org$" t)) org-agenda-files (ignore-errors (directory-files +org-dir t "\\.org$" t))
org-agenda-inhibit-startup 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 () (defun +org|setup-ui ()
"Configures the UI for `org-mode'." "Configures the UI for `org-mode'."
@ -278,12 +280,14 @@ between the two."
:ni [M-return] (λ! (+org/insert-item 'below)) :ni [M-return] (λ! (+org/insert-item 'below))
:ni [S-M-return] (λ! (+org/insert-item 'above)) :ni [S-M-return] (λ! (+org/insert-item 'above))
;; more org-ish vim motion keys ;; more org-ish vim motion keys
:n "]]" (λ! (org-forward-heading-same-level nil) (org-beginning-of-line)) :m "]]" (λ! (org-forward-heading-same-level nil) (org-beginning-of-line))
:n "[[" (λ! (org-backward-heading-same-level nil) (org-beginning-of-line)) :m "[[" (λ! (org-backward-heading-same-level nil) (org-beginning-of-line))
:n "]l" #'org-next-link :m "]h" #'org-next-visible-heading
:n "[l" #'org-previous-link :m "[h" #'org-previous-visible-heading
:n "]s" #'org-babel-next-src-block :m "]l" #'org-next-link
:n "[s" #'org-babel-previous-src-block :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 "^" #'evil-org-beginning-of-line
:m "0" (λ! (let ((visual-line-mode)) (org-beginning-of-line))) :m "0" (λ! (let ((visual-line-mode)) (org-beginning-of-line)))
:n "gQ" #'org-fill-paragraph :n "gQ" #'org-fill-paragraph
@ -348,10 +352,11 @@ between the two."
(def-package! org-clock (def-package! org-clock
:commands org-clock-save :commands org-clock-save
:hook (org-mode . org-clock-load) :hook (org-mode . org-clock-load)
:config :init
(setq org-clock-persist 'history (setq org-clock-persist 'history
org-clock-persist-file (concat doom-etc-dir "org-clock-save.el")) 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) (when (featurep 'org)

View file

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

View file

@ -1,16 +1,18 @@
;;; lang/purescript/config.el -*- lexical-binding: t; -*- ;;; lang/purescript/config.el -*- lexical-binding: t; -*-
(def-package! purescript-mode (after! purescript-mode
:mode "\\.purs$"
:config
(add-hook! 'purescript-mode-hook (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 ;; (def-package! flycheck-purescript
;; :after purescript-mode ;; :after purescript-mode
;; :config ;; :config
;; (add-hook 'flycheck-mode-hook #'flycheck-purescript-setup)) ;; (add-hook 'flycheck-mode-hook #'flycheck-purescript-setup))
(def-package! psc-ide (def-package! psc-ide
:hook (purescript-mode . psc-ide-mode)) :hook (purescript-mode . psc-ide-mode))

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