Major optimization refactor, across the board

+ enable lexical-scope everywhere (lexical-binding = t): ~5-10% faster
  startup; ~5-20% general boost
+ reduce consing, function calls & garbage collection by preferring
  cl-loop & dolist over lambda closures (for mapc[ar], add-hook, and
  various cl-lib filter/map/reduce functions) -- where possible
+ prefer functions with dedicated opcodes, like assq (see byte-defop's
  in bytecomp.el for more)
+ prefer pcase & cond (faster) over cl-case
+ general refactor for code readability
+ ensure naming & style conventions are adhered to
+ appease byte-compiler by marking unused variables with underscore
+ defer minor mode activation to after-init, emacs-startup or
  window-setup hooks; a customization opportunity for users + ensures
  custom functionality won't interfere with startup.
This commit is contained in:
Henrik Lissner 2017-06-08 11:47:56 +02:00
parent 64a142b3fc
commit c7254e7bdc
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
154 changed files with 1101 additions and 1118 deletions

View file

@ -1,4 +1,4 @@
;;; autoload.el
;;; core/autoload/buffers.el -*- lexical-binding: t; -*-
(defvar-local doom-buffer--narrowed-origin nil)
@ -25,20 +25,19 @@ the buffer (if narrowed).
Inspired from http://demonastery.org/2013/04/emacs-evil-narrow-region/"
(interactive "r")
(if (region-active-p)
(progn
(deactivate-mark)
(when clone-p
(let ((old-buf (current-buffer)))
(switch-to-buffer (clone-indirect-buffer nil nil))
(setq doom-buffer--narrowed-origin old-buf)))
(narrow-to-region beg end))
(if doom-buffer--narrowed-origin
(progn
(kill-this-buffer)
(switch-to-buffer doom-buffer--narrowed-origin)
(setq doom-buffer--narrowed-origin nil))
(widen))))
(cond ((region-active-p)
(deactivate-mark)
(when clone-p
(let ((old-buf (current-buffer)))
(switch-to-buffer (clone-indirect-buffer nil nil))
(setq doom-buffer--narrowed-origin old-buf)))
(narrow-to-region beg end))
(doom-buffer--narrowed-origin
(kill-this-buffer)
(switch-to-buffer doom-buffer--narrowed-origin)
(setq doom-buffer--narrowed-origin nil))
(t
(widen))))
;; Buffer Life and Death ;;;;;;;;;;;;;;;
@ -52,11 +51,12 @@ the current workspace."
(persp-buffer-list-restricted)
(buffer-list)))
(project-root (and project-p (doom-project-root t))))
(if project-root
(funcall (if (eq project-p 'not) #'cl-remove-if #'cl-remove-if-not)
(lambda (b) (projectile-project-buffer-p b project-root))
buffers)
buffers)))
(cond (project-root
(cl-loop for buf in buffers
if (projectile-project-buffer-p buf project-root)
collect buf))
(t
buffers))))
;;;###autoload
(defun doom-real-buffers-list (&optional buffer-list)
@ -99,8 +99,9 @@ only the buried buffers in BUFFER-LIST (a list of BUFFER-OR-NAMEs)."
(defun doom-matching-buffers (pattern &optional buffer-list)
"Get a list of all buffers (in the current workspace OR in BUFFER-LIST) that
match the regex PATTERN."
(cl-remove-if-not (lambda (buf) (string-match-p pattern (buffer-name buf)))
(or buffer-list (doom-buffer-list))))
(cl-loop for buf in (or buffer-list (doom-buffer-list))
when (string-match-p pattern (buffer-name buf))
collect buf))
(defun doom--cycle-real-buffers (&optional n)
"Switch to the next buffer N times (previous, if N < 0), skipping over unreal
@ -119,7 +120,7 @@ buffers. If there's nothing left, switch to `doom-fallback-buffer'. See
;; BUFFERS? Because `switch-to-next-buffer' and
;; `switch-to-prev-buffer' properly update buffer list order.
(while (not (memq (current-buffer) buffers))
(dotimes (i (abs n))
(dotimes (_i (abs n))
(funcall move-func))))))
(when (eq (current-buffer) (doom-fallback-buffer))
(cd project-dir))
@ -201,14 +202,15 @@ switched to a real buffer."
;;;###autoload
(defun doom-kill-buffer-and-windows (buffer)
"Kill the buffer and delete all the windows it's displayed in."
(unless (one-window-p t)
(mapc (lambda (win) (unless (one-window-p t) (delete-window win)))
(get-buffer-window-list buffer)))
(dolist (window (get-buffer-window-list buffer))
(unless (one-window-p t)
(delete-window window)))
(kill-buffer buffer))
;;;###autoload
(defun doom-kill-process-buffers ()
"Kill all processes that have no visible associated buffers."
"Kill all processes that have no visible associated buffers. Return number of
processes killed."
(interactive)
(let ((n 0))
(dolist (p (process-list))
@ -220,7 +222,7 @@ switched to a real buffer."
(not (buffer-live-p process-buffer)))))
(message "Killing %s" (process-name p))
(delete-process p)
(setq n (1+ n)))))
(cl-incf n))))
n))
;;;###autoload
@ -253,11 +255,11 @@ belong to the current project in this workspace."
"Kill all other buffers in this workspace. If PROJECT-P, kill only the other
buffers that belong to the current project."
(interactive "P")
(let ((buffers (doom-buffer-list project-p)))
(mapc (lambda (buf)
(unless (eq buf (current-buffer))
(doom-kill-buffer-and-windows buf)))
buffers)
(let ((buffers (doom-buffer-list project-p))
(current-buffer (current-buffer)))
(dolist (buf buffers)
(unless (eq buf current-buffer)
(doom-kill-buffer-and-windows buf)))
(when (called-interactively-p 'interactive)
(message "Killed %s buffers" (length buffers)))))

View file

@ -1,4 +1,4 @@
;;; debug.el
;;; core/autoload/debug.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom/what-face (&optional pos)
@ -22,8 +22,9 @@
;;;###autoload
(defun doom-active-minor-modes ()
"Get a list of active minor-mode symbols."
(cl-remove-if (lambda (m) (and (boundp m) (symbol-value m)))
minor-mode-list))
(cl-loop for mode in minor-mode-list
unless (and (boundp mode) (symbol-value mode))
collect mode))
;;;###autoload
(defun doom/what-minor-mode (mode)
@ -44,13 +45,13 @@ selection of all minor-modes, active or not."
(declare (interactive-only t))
(interactive)
(if-let (bad-hosts
(loop for bad
in `("https://wrong.host.badssl.com/"
"https://self-signed.badssl.com/")
if (condition-case e
(url-retrieve bad (lambda (retrieved) t))
(error nil))
collect bad))
(cl-loop for bad
in '("https://wrong.host.badssl.com/"
"https://self-signed.badssl.com/")
if (condition-case _e
(url-retrieve bad (lambda (_retrieved) t))
(error nil))
collect bad))
(error (format "tls seems to be misconfigured (it got %s)."
bad-hosts))
(url-retrieve "https://badssl.com"

View file

@ -1,4 +1,4 @@
;;; editor.el
;;; core/autoload/editor.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom/sudo-find-file (file)
@ -65,7 +65,7 @@ If already there, do nothing."
(looking-at-p match-str))))
;;;###autoload
(defun doom/dumb-indent (&optional smart)
(defun doom/dumb-indent ()
"Inserts a tab character (or spaces x tab-width)."
(interactive)
(if indent-tabs-mode
@ -142,11 +142,13 @@ possible, or just one char if that's not possible."
"Checks if point is surrounded by {} [] () delimiters and adds a
space on either side of the point if so."
(interactive)
(let ((command (or (command-remapping #'self-insert-command) #'self-insert-command)))
(if (doom--surrounded-p)
(progn (call-interactively command)
(save-excursion (call-interactively command)))
(call-interactively command))))
(let ((command (or (command-remapping #'self-insert-command)
#'self-insert-command)))
(cond ((doom--surrounded-p)
(call-interactively command)
(save-excursion (call-interactively command)))
(t
(call-interactively command)))))
;;;###autoload
(defun doom/deflate-space-maybe ()
@ -155,22 +157,24 @@ spaces on either side of the point if so. Resorts to
`doom/backward-delete-whitespace-to-column' otherwise."
(interactive)
(save-match-data
(if (doom--surrounded-p)
(let ((whitespace-match (match-string 1)))
(cond ((not whitespace-match)
(call-interactively #'delete-backward-char))
((string-match "\n" whitespace-match)
(funcall (if (featurep 'evil) #'evil-delete #'delete-region)
(point-at-bol) (point))
(call-interactively #'delete-backward-char)
(save-excursion (call-interactively #'delete-char)))
(t (just-one-space 0))))
(doom/backward-delete-whitespace-to-column))))
(cond ((doom--surrounded-p)
(let ((whitespace-match (match-string 1)))
(cond ((not whitespace-match)
(call-interactively #'delete-backward-char))
((string-match "\n" whitespace-match)
(funcall (if (featurep 'evil) #'evil-delete #'delete-region)
(point-at-bol) (point))
(call-interactively #'delete-backward-char)
(save-excursion (call-interactively #'delete-char)))
(t (just-one-space 0)))))
(t
(doom/backward-delete-whitespace-to-column)))))
;;;###autoload
(defun doom/newline-and-indent ()
"Inserts a newline and possibly indents it. Also cotinues comments if executed
from a commented line."
"Inserts a newline and possibly indents it. Also continues comments if
executed from a commented line; handling special cases for certain languages
with weak native support."
(interactive)
(cond ((sp-point-in-string)
(newline))

View file

@ -1,4 +1,4 @@
;;; ../core/autoload/help.el
;;; core/autoload/help.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom/describe-setting (setting)

View file

@ -1,4 +1,4 @@
;;; memoize.el
;;; core/autoload/memoize.el -*- lexical-binding: t; -*-
;;;###autoload
(defvar doom-memoized-table (make-hash-table :test 'equal :size 10)
@ -23,7 +23,9 @@ and the value is the function's return value.")
"Create a memoize'd function. NAME, ARGLIST, DOCSTRING and BODY
have the same meaning as in `defun'."
(declare (indent defun) (doc-string 3))
`(progn
`(,(if (bound-and-true-p byte-compile-current-file)
'with-no-warnings
'progn)
(defun ,name ,arglist ,@body)
(doom-memoize ',name)))

View file

@ -1,4 +1,4 @@
;;; message.el
;;; core/autoload/message.el -*- lexical-binding: t; -*-
(defconst doom-message-fg
'((reset . 0)
@ -40,12 +40,12 @@
"An alternative to `format' that strips out ANSI codes if used in an
interactive session."
`(cl-flet*
(,@(mapcar
(lambda (rule)
`(,(car rule)
(lambda (message &rest args)
(apply #'doom-ansi-apply ',(car rule) message args))))
(append doom-message-fg doom-message-bg doom-message-fx))
(,@(cl-loop for rule
in (append doom-message-fg doom-message-bg doom-message-fx)
collect
`(,(car rule)
(lambda (message &rest args)
(apply #'doom-ansi-apply ',(car rule) message args))))
(color (symbol-function 'doom-ansi-apply)))
(format ,message ,@args)))

View file

@ -1,4 +1,4 @@
;;; ../core/autoload/minibuffer.el
;;; core/autoload/minibuffer.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom/minibuffer-kill-word ()

View file

@ -1,5 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; packages.el
;;; core/autoload/packages.el -*- lexical-binding: t; -*-
(defvar doom--last-refresh nil)
@ -15,10 +14,11 @@
(progn
(message "Refreshing package archives")
(package-refresh-contents (not doom-debug-mode))
(let ((i 0))
(while package--downloads-in-progress
(sleep-for 0 250))
(persistent-soft-store 'last-pkg-refresh t "emacs" 900)))
(cl-loop for i from 0
while (and package--downloads-in-progress
(<= i 10))
do (sleep-for 0 250))
(persistent-soft-store 'last-pkg-refresh t "emacs" 900))
(error
(doom-refresh-clear-cache)
(message "Failed to refresh packages: %s" (cadr ex))))))
@ -85,7 +85,7 @@ list of the package."
(plist-get (cdr (assq name doom-packages)) :freeze))
;;;###autoload
(defun doom-get-packages (&optional backend)
(defun doom-get-packages ()
"Retrieves a list of explicitly installed packages (i.e. non-dependencies).
Each element is a cons cell, whose car is the package symbol and whose cdr is
the quelpa recipe (if any).
@ -96,12 +96,12 @@ the packages relevant to that backend.
Warning: this function is expensive; it re-evaluates all of doom's config files.
Be careful not to use it in a loop."
(doom-initialize-packages t)
(delq nil
(mapcar (lambda (pkgsym)
(or (assq pkgsym doom-packages)
(list (car (assq pkgsym package-alist)))))
(cl-delete-duplicates
(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)
if (or (assq sym doom-packages)
(and (assq sym package-alist)
(list sym)))
collect it))
;;;###autoload
(defun doom-get-depending-on (name)
@ -124,11 +124,11 @@ containing (PACKAGE-SYMBOL OLD-VERSION-LIST NEW-VERSION-LIST).
If INCLUDE-FROZEN-P is non-nil, check frozen packages as well.
Used by `doom/packages-update'."
(let ((pkgs (mapcar #'car (doom-get-packages))))
(delq nil
(mapcar #'doom-package-outdated-p
(if include-frozen-p pkgs
(cl-remove-if #'doom-package-frozen-p pkgs))))))
(cl-loop for pkg in (doom-get-packages)
if (or (and (doom-package-frozen-p (car pkg))
include-frozen-p)
(doom-package-outdated-p (car pkg)))
collect it))
;;;###autoload
(defun doom-get-orphaned-packages ()
@ -152,13 +152,14 @@ If INCLUDE-IGNORED-P is non-nil, includes missing packages that are ignored,
i.e. they have an :ignore property.
Used by `doom/packages-install'."
(cl-remove-if (lambda (pkgsym)
(let ((pkg (car pkgsym)))
(or (assq pkg package-alist)
(unless include-ignored-p (doom-package-ignored-p pkg))
(and (not (plist-get (assq pkg doom-packages) :pin))
(assq pkg package--builtins)))))
(doom-get-packages)))
(cl-loop for pkgsym in (doom-get-packages)
unless
(let ((pkg (car pkgsym)))
(or (assq pkg package-alist)
(unless include-ignored-p (doom-package-ignored-p pkg))
(and (not (plist-get (assq pkg doom-packages) :pin))
(assq pkg package--builtins))))
collect pkgsym))
;;;###autoload
(defun doom*package-delete (desc &rest _)
@ -180,16 +181,14 @@ Used by `doom/packages-install'."
(defun doom--packages-choose (prompt)
(doom-initialize)
(let* ((table (mapcar
(lambda (p) (cons (package-desc-full-name p) p))
(delq nil
(mapcar (lambda (p) (unless (package-built-in-p p) p))
(apply #'append (mapcar #'cdr package-alist))))))
(name (completing-read
prompt
(mapcar #'car table)
nil t)))
(cdr (assoc name table))))
(let ((table (cl-loop for pkg in package-alist
unless (package-built-in-p (cdr pkg))
collect (cons (package-desc-full-name (cdr pkg))
(cdr pkg)))))
(cdr (assoc (completing-read prompt
(mapcar #'car table)
nil t)
table))))
(defmacro doom--condition-case! (&rest body)
`(condition-case ex
@ -229,20 +228,21 @@ example; the package name can be omitted)."
(user-error "%s is already installed" name))
(let ((plist (or plist (cdr (assq name doom-packages))))
(inhibit-message (not doom-debug-mode))
(recipe (plist-get plist :recipe)))
(recipe (plist-get plist :recipe))
quelpa-upgrade-p)
(cond (recipe (quelpa recipe))
(t (package-install name))))
(when (package-installed-p name)
(cl-pushnew (cons name plist) doom-packages :test #'eq :key #'car)
t))
(t (package-install name)))
(when (package-installed-p name)
(cl-pushnew (cons name plist) doom-packages :test #'eq :key #'car)
t)))
(defun doom-update-package (name)
(defun doom-update-package (name &optional force-p)
"Updates package NAME if it is out of date, using quelpa or package.el as
appropriate."
(doom-initialize)
(unless (package-installed-p name)
(user-error "%s isn't installed" name))
(when (doom-package-outdated-p name)
(when (or force-p (doom-package-outdated-p name))
(let ((inhibit-message (not doom-debug-mode))
(desc (cadr (assq name package-alist))))
(pcase (doom-package-backend name)
@ -258,12 +258,11 @@ appropriate."
(package-compute-transaction (list archive) (package-desc-reqs archive))
(package-compute-transaction () (list (list archive))))))
(package-download-transaction packages))))
(when-let (old-dir (package-desc-dir desc))
(when (file-directory-p old-dir)
(delete-directory old-dir t)))
(version-list-<
(package-desc-version desc)
(package-desc-version (cadr (assq name package-alist)))))))
(unless (doom-package-outdated-p name)
(when-let (old-dir (package-desc-dir desc))
(when (file-directory-p old-dir)
(delete-directory old-dir t)))
t))))
(defun doom-delete-package (name &optional force-p)
"Uninstalls package NAME if it exists, and clears it from `quelpa-cache'."
@ -358,7 +357,7 @@ appropriate."
(message! "Updating %s" (car pkg))
(doom--condition-case!
(message!
(let ((result (doom-update-package (car pkg))))
(let ((result (doom-update-package (car pkg) t)))
(color (if result 'green 'red)
" %s"
(if result "DONE" "FAILED"))))))
@ -450,7 +449,7 @@ calls."
(if (y-or-n-p (format "%s will be updated from %s to %s. Update?"
package old-v-str new-v-str))
(message "%s %s (%s => %s)"
(if (doom-update-package package) "Updated" "Failed to update")
(if (doom-update-package package t) "Updated" "Failed to update")
package old-v-str new-v-str)
(message "Aborted")))
(message "%s is up-to-date" package))))

View file

@ -1,4 +1,4 @@
;;; popups.el
;;; core/autoload/popups.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom-popup-p (&optional target)
@ -13,7 +13,8 @@ current window if omitted."
;;;###autoload
(defun doom-popup-buffer (buffer &rest plist)
"Display BUFFER in a shackle popup. See `shackle-rules' for possible rules."
"Display BUFFER in a shackle popup. See `shackle-rules' for possible rules.
Returns the new popup window."
(declare (indent defun))
(unless (bufferp buffer)
(error "%s is not a valid buffer" buffer))
@ -106,9 +107,7 @@ only close popups that have an :autoclose property in their rule (see
`shackle-rules')."
(interactive)
(when-let (popups (doom-popup-windows))
(let ((orig-win (selected-window))
success
doom-popup-remember-history)
(let (success doom-popup-remember-history)
(setq doom-popup-history (mapcar #'doom--popup-data popups))
(dolist (window popups)
(when (or force-p
@ -145,6 +144,7 @@ only close popups that have an :autoclose property in their rule (see
;;;###autoload
(defun doom-popup-prop (prop &optional window)
"Returns a `doom-popup-rules' PROPerty from WINDOW."
(or (plist-get (or (if window
(buffer-local-value 'doom-popup-rules (window-buffer window))
doom-popup-rules)
@ -157,6 +157,7 @@ only close popups that have an :autoclose property in their rule (see
;;;###autoload
(defun doom-popup-side (&optional window)
"Return what side a popup WINDOW came from ('left 'right 'above or 'below)."
(let ((align (doom-popup-prop :align window)))
(when (eq align t)
(setq align shackle-default-alignment))
@ -166,6 +167,7 @@ only close popups that have an :autoclose property in their rule (see
;;;###autoload
(defun doom-popup-size (&optional window)
"Return the size of a popup WINDOW."
(let ((side (doom-popup-side window)))
(cond ((memq side '(left right))
(window-width window))

View file

@ -1,5 +1,4 @@
;;; system.el
(provide 'core-lib-system)
;;; core/autoload/system.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom-system-os (&optional os)
@ -17,9 +16,8 @@ is given, returns t if it matches the current system, and nil otherwise."
((memq system-type '(windows-nt cygwin))
'windows)
(t (error "Unknown OS: %s" system-type)))))
(if os
(eq os type)
type)))
(or (and os (eq os type))
type)))
;;;###autoload
(defun doom-sh (command &rest args)
@ -34,6 +32,7 @@ is given, returns t if it matches the current system, and nil otherwise."
(t
(princ (shell-command-to-string (apply #'format command args)))))))
(defvar tramp-verbose)
;;;###autoload
(defun doom-sudo (command &rest args)
"Like `doom-sh', but runs as root (prompts for password)."

View file

@ -1,4 +1,4 @@
;;; ../core/autoload/test.el
;;; core/autoload/test.el -*- lexical-binding: t; -*-
;;;###autoload
(defmacro def-test-group! (name &rest body)

View file

@ -1,4 +1,4 @@
;;; ui.el
;;; core/autoload/ui.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom/toggle-fullscreen ()
@ -15,7 +15,7 @@
(interactive "P")
(cond ((featurep 'nlinum)
(nlinum-mode (or arg (if nlinum-mode -1 +1))))
((featurep 'linum-mode)
((featurep 'linum)
(linum-mode (or arg (if linum-mode -1 +1))))
(t
(error "No line number plugin detected"))))
@ -38,7 +38,6 @@ window changes before then, the undo expires."
(delete-other-windows)))
(defvar doom--window-enlargened nil)
;;;###autoload
(defun doom/window-enlargen ()
"Enlargen the current window. Activate again to undo."

View file

@ -1,4 +1,4 @@
;;; core-editor.el --- filling the editor shaped hole in the Emacs OS
;;; core-editor.el -*- lexical-binding: t; -*-
(defvar doom-large-file-size 1
"Size (in MB) above which the user will be prompted to open the file literally
@ -48,10 +48,12 @@ modes are active and the buffer is read-only.")
vc-follow-symlinks t)
;; ediff: use existing frame instead of creating a new one
(add-hook! 'ediff-load-hook
(defun doom|init-ediff ()
(setq ediff-diff-options "-w"
ediff-split-window-function #'split-window-horizontally
ediff-window-setup-function #'ediff-setup-windows-plain)) ; no extra frames
;; no extra frames
ediff-window-setup-function #'ediff-setup-windows-plain))
(add-hook 'ediff-load-hook #'doom|init-ediff)
(defun doom|dont-kill-scratch-buffer ()
"Don't kill the scratch buffer."
@ -61,8 +63,7 @@ modes are active and the buffer is read-only.")
(defun doom*delete-trailing-whitespace (orig-fn &rest args)
"Don't affect trailing whitespace on current line."
(let ((spaces (1- (current-column)))
(linestr (buffer-substring-no-properties
(let ((linestr (buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))
(apply orig-fn args)
@ -106,7 +107,7 @@ fundamental-mode) for performance sake."
savehist-autosave-interval nil ; save on kill only
savehist-additional-variables '(kill-ring search-ring regexp-search-ring)
save-place-file (concat doom-cache-dir "saveplace"))
(add-hook! 'after-init-hook #'(savehist-mode save-place-mode))
(add-hook! 'emacs-startup-hook #'(savehist-mode save-place-mode))
;; Keep track of recently opened files
(def-package! recentf
@ -145,10 +146,12 @@ fundamental-mode) for performance sake."
(t (error "%s is an invalid action for :editorconfig" action)))))
:config
(editorconfig-mode +1)
;; Show whitespace in tabs indentation mode
(add-hook! 'editorconfig-custom-hooks
(if indent-tabs-mode (whitespace-mode +1))))
(add-hook 'emacs-startup-hook #'editorconfig-mode)
(defun doom|editorconfig-whitespace-mode-maybe (&rest _)
"Show whitespace-mode when file uses TABS (ew)."
(if indent-tabs-mode (whitespace-mode +1)))
(add-hook 'editorconfig-custom-hooks #'doom|editorconfig-whitespace-mode-maybe))
;; Auto-close delimiters and blocks as you type
(def-package! smartparens
@ -161,7 +164,7 @@ fundamental-mode) for performance sake."
sp-max-pair-length 3)
:config
(smartparens-global-mode 1)
(add-hook 'emacs-startup-hook #'smartparens-global-mode)
(require 'smartparens-config)
;; Smartparens interferes with Replace mode
(add-hook 'evil-replace-state-entry-hook #'turn-off-smartparens-mode)

View file

@ -1,8 +1,8 @@
;;; core-keybinds.el
;;; core-keybinds.el -*- lexical-binding: t; -*-
;; A centralized keybinds system, integrated with `which-key' to preview
;; available keys, and `evil', if it's enabled. All built into one powerful
;; macro: `map!'.
;; available keybindings. All built into one powerful macro: `map!'. If evil is
;; never loaded, then evil bindings set with `map!' will be ignored.
(defvar doom-leader-key "SPC"
"The leader prefix key, for global commands.")
@ -11,13 +11,13 @@
"The localleader prefix key, for major-mode specific commands.")
(defvar doom-evil-state-alist
'(("n" . normal)
("v" . visual)
("i" . insert)
("e" . emacs)
("o" . operator)
("m" . motion)
("r" . replace))
'((?n . normal)
(?v . visual)
(?i . insert)
(?e . emacs)
(?o . operator)
(?m . motion)
(?r . replace))
"A list of cons cells that map a letter to a evil state symbol.")
@ -33,7 +33,7 @@
;; embolden local bindings
(set-face-attribute 'which-key-local-map-description-face nil :weight 'bold)
(which-key-setup-side-window-bottom)
(which-key-mode +1))
(add-hook 'window-setup-hook #'which-key-mode))
;;
@ -56,14 +56,11 @@ IGNORE is a list of keyword letters that should be ignored.
For example, :nvi will map to (list 'normal 'visual 'insert). See
`doom-evil-state-alist' to customize this."
(delq nil
(mapcar (lambda (l)
(let ((state (cdr (assoc l doom-evil-state-alist))))
(unless state
(unless (or (eq ignore t) (member l ignore))
(error "not a valid state: %s" l)))
state))
(split-string (substring (symbol-name keyword) 1) "" t))))
(cl-loop for l across (substring (symbol-name keyword) 1)
if (cdr (assq l doom-evil-state-alist))
collect it
else if (not (or (eq ignore t) (member l ignore)))
do (error "not a valid state: %s" l)))
;; Register keywords for proper indentation (see `map!')
@ -79,6 +76,11 @@ For example, :nvi will map to (list 'normal 'visual 'insert). See
(put ':localleader 'lisp-indent-function 'defun)
(put ':textobj 'lisp-indent-function 'defun)
;; specials
(defvar doom--keymaps nil)
(defvar doom--prefix nil)
(defvar doom--defer nil)
(defmacro map! (&rest rest)
"A nightmare of a key-binding macro that will use `evil-define-key*',
`define-key', `local-set-key' and `global-set-key' depending on context and
@ -130,9 +132,9 @@ Example
(:when IS-MAC
:n \"M-s\" 'some-fn
:i \"M-o\" (lambda (interactive) (message \"Hi\"))))"
(let ((keymaps (if (boundp 'keymaps) keymaps))
(prefix (if (boundp 'prefix) prefix))
(defer (if (boundp 'defer) defer))
(let ((doom--keymaps doom--keymaps)
(doom--prefix doom--prefix)
(doom--defer doom--defer)
local key def states forms desc modes)
(while rest
(setq key (pop rest))
@ -156,19 +158,19 @@ Example
(:unless (push `(if (not ,(pop rest)) ,(macroexpand `(map! ,@rest))) forms) (setq rest '()))
(:after (push `(after! ,(pop rest) ,(macroexpand `(map! ,@rest))) forms) (setq rest '()))
(:desc (setq desc (pop rest)))
(:map* (setq defer t) (push :map rest))
(:map* (setq doom--defer t) (push :map rest))
(:map
(setq keymaps
(setq doom--keymaps
(let ((car (pop rest)))
(if (listp car) car (list car)))))
(:mode
(setq modes
(let ((car (pop rest)))
(if (listp car) car (list car))))
(unless keymaps
(setq keymaps
(mapcar (lambda (m) (intern (format "%s-map" (symbol-name m))))
modes))))
(unless doom--keymaps
(setq doom--keymaps
(cl-loop for m in modes
collect (intern (format "%s-map" (symbol-name m)))))))
(:textobj
(let* ((key (pop rest))
(inner (pop rest))
@ -178,20 +180,20 @@ Example
forms)))
(:prefix
(let ((def (pop rest)))
(setq prefix `(vconcat ,prefix (kbd ,def)))
(setq doom--prefix `(vconcat ,doom--prefix (kbd ,def)))
(when desc
(push `(doom--keybind-register ,(key-description (eval prefix))
(push `(doom--keybind-register ,(key-description (eval doom--prefix))
,desc ',modes)
forms)
(setq desc nil))))
(otherwise ; might be a state prefix
(_ ; might be a state doom--prefix
(setq states (doom--keyword-to-states key '("L")))
(let (case-fold-search)
(when (string-match-p "L" (symbol-name key))
(setq local t)
(cond ((= (length states) 0)
(user-error "local keybinding for %s must accompany another state" key))
((> (length keymaps) 0)
((> (length doom--keymaps) 0)
(user-error "local keybinding for %s cannot accompany a keymap" key))))))))
;; It's a key-def pair
@ -205,8 +207,8 @@ Example
(setq key `(kbd ,key)))
((stringp key)
(setq key (kbd key))))
(when prefix
(setq key (append prefix (list key))))
(when doom--prefix
(setq key (append doom--prefix (list key))))
(unless (> (length rest) 0)
(user-error "map! has no definition for %s key" key))
(setq def (pop rest))
@ -214,10 +216,10 @@ Example
(push `(doom--keybind-register ,(key-description (eval key))
,desc ',modes)
forms))
(cond ((and keymaps states)
(cond ((and doom--keymaps states)
(unless (featurep 'evil) (throw 'skip 'evil))
(dolist (keymap keymaps)
(push `(,(if defer 'evil-define-key 'evil-define-key*)
(dolist (keymap doom--keymaps)
(push `(,(if doom--defer 'evil-define-key 'evil-define-key*)
',states ,keymap ,key ,def)
forms)))
(states
@ -227,8 +229,8 @@ Example
,(intern (format "evil-%s-state-%smap" state (if local "local-" "")))
,key ,def)
forms)))
(keymaps
(dolist (keymap keymaps)
(doom--keymaps
(dolist (keymap doom--keymaps)
(push `(define-key ,keymap ,key ,def) forms)))
(t (push `(,(if local 'local-set-key 'global-set-key) ,key ,def)
forms))))

View file

@ -1,4 +1,4 @@
;;; core-lib.el
;;; core-lib.el -*- lexical-binding: t; -*-
;; I don't use use-package for these to save on the `fboundp' lookups it does
;; for its :commands property. I use dolists instead of mapc to avoid extra
@ -35,23 +35,21 @@
'default-directory
(or root `(doom-project-root))))))
((listp paths)
(let (forms)
(dolist (i paths (nreverse forms))
(push (doom--resolve-paths i root) forms))))
(cl-loop for i in paths
collect (doom--resolve-paths i root)))
(t paths)))
(defun doom--resolve-hooks (hooks)
(let ((quoted-p (eq (car-safe hooks) 'quote))
ret-hooks)
(let ((quoted-p (eq (car-safe hooks) 'quote)))
(when quoted-p
(setq hooks (cadr hooks)))
(dolist (hook (if (listp hooks) hooks (list hooks)) (nreverse ret-hooks))
(push (cond ((eq (car-safe hook) 'quote)
(cadr hook))
(quoted-p hook)
(t
(intern (format "%s-hook" (symbol-name hook)))))
ret-hooks))))
(cl-loop with hooks = (if (listp hooks) hooks (list hooks))
for hook in hooks
if (eq (car-safe hook) 'quote)
collect (cadr hook)
else if quoted-p
collect hook
else collect (intern (format "%s-hook" (symbol-name hook))))))
;;
@ -67,8 +65,7 @@
"A smart wrapper around `with-eval-after-load'. Supresses warnings during
compilation."
(declare (indent defun) (debug t))
`(,(if (or (not (boundp 'byte-compile-current-file))
(not byte-compile-current-file)
`(,(if (or (not (bound-and-true-p byte-compile-current-file))
(if (symbolp feature)
(require feature nil :no-error)
(load feature :no-message :no-error)))
@ -139,12 +136,13 @@ Examples:
Body forms can access the hook's arguments through the let-bound variable
`args'."
(declare (indent defun) (debug t))
(let ((hook-fn (if (boundp 'hook-fn) hook-fn))
hook append-p local-p)
(let ((hook-fn 'add-hook)
append-p local-p)
(while (keywordp (car args))
(pcase (pop args)
(:append (setq append-p t))
(:local (setq local-p t))))
(:local (setq local-p t))
(:remove (setq hook-fn 'remove-hook))))
(let ((hooks (doom--resolve-hooks (pop args)))
(funcs
(let ((val (car args)))
@ -157,7 +155,7 @@ Body forms can access the hook's arguments through the let-bound variable
(dolist (fn funcs)
(setq fn (if (symbolp fn)
`(function ,fn)
`(lambda (&rest args) ,@args)))
`(lambda (&rest _) ,@args)))
(dolist (hook hooks)
(push (cond ((eq hook-fn 'remove-hook)
`(remove-hook ',hook ,fn ,local-p))
@ -169,17 +167,16 @@ Body forms can access the hook's arguments through the let-bound variable
(defmacro remove-hook! (&rest args)
"Convenience macro for `remove-hook'. Takes the same arguments as
`add-hook!'."
(let ((hook-fn 'remove-hook))
(macroexpand `(add-hook! ,@args))))
`(add-hook! :remove ,@args))
(defmacro associate! (mode &rest plist)
"Associate a minor mode to certain patterns and project files."
(declare (indent 1))
(unless noninteractive
(let* ((modes (plist-get plist :modes))
(match (plist-get plist :match))
(files (plist-get plist :files))
(pred-form (plist-get plist :when)))
(let ((modes (plist-get plist :modes))
(match (plist-get plist :match))
(files (plist-get plist :files))
(pred-form (plist-get plist :when)))
(cond ((or files modes pred-form)
(when (and files
(not (or (listp files)
@ -196,9 +193,8 @@ Body forms can access the hook's arguments through the let-bound variable
,(or pred-form t))
(,mode 1)))
,@(if (and modes (listp modes))
(let (forms)
(dolist (hook (doom--resolve-hooks modes) (nreverse forms))
(push `(add-hook ',hook ',hook-name) forms)))
(cl-loop for hook in (doom--resolve-hooks modes)
collect `(add-hook ',hook ',hook-name))
`((add-hook 'after-change-major-mode-hook ',hook-name))))))
(match
`(push (cons ,match ',mode) doom-auto-minor-mode-alist))

View file

@ -1,4 +1,4 @@
;;; core-os.el
;;; core-os.el -*- lexical-binding: t; -*-
(defconst IS-MAC (eq system-type 'darwin))
(defconst IS-LINUX (eq system-type 'gnu/linux))

View file

@ -1,4 +1,4 @@
;;; core-packages.el
;;; core-packages.el --- package management system -*- lexical-binding: t; -*-
;; Emacs package management is opinionated. Unfortunately, so am I. I've bound
;; together `use-package', `quelpa' and package.el to create my own,
@ -76,7 +76,7 @@ base by `doom!' and for calculating how many packages exist.")
(defvar doom--refresh-p nil)
(setq load-prefer-newer noninteractive
(setq load-prefer-newer (or noninteractive doom-debug-mode)
package--init-file-ensured t
package-user-dir (expand-file-name "elpa" doom-packages-dir)
package-enable-at-startup nil
@ -96,7 +96,7 @@ base by `doom!' and for calculating how many packages exist.")
use-package-always-defer t
use-package-always-ensure nil
use-package-expand-minimally (eval-when-compile (not doom-debug-mode))
use-package-expand-minimally (not doom-debug-mode)
use-package-debug nil
use-package-verbose doom-debug-mode
use-package-minimum-reported-time (if doom-debug-mode 0 0.1)
@ -144,7 +144,7 @@ to speed up startup."
;; Also, in some edge cases involving package initialization during a
;; non-interactive session, `package-initialize' fails to fill `load-path'.
;; If we want something done right, do it ourselves!
(setq doom--package-load-path (directory-files package-user-dir t "^\\w" t)
(setq doom--package-load-path (directory-files package-user-dir t "^[^.]" t)
load-path (append load-path doom--package-load-path))
;; Ensure core packages are installed
@ -164,7 +164,7 @@ to speed up startup."
(setq doom-init-p t)))
(defun doom-initialize-autoloads (&optional inhibit-reload-p)
(defun doom-initialize-autoloads ()
"Ensures that `doom-autoload-file' exists and is loaded. Otherwise run
`doom/reload-autoloads' to generate it."
(unless (file-exists-p doom-autoload-file)
@ -189,15 +189,16 @@ This aggressively reloads core autoload files."
(funcall load-fn (expand-file-name "init.el" doom-emacs-dir))
(funcall load-fn (doom-module-path :private user-login-name "init.el"))
(when load-p
(mapc (lambda (file) (funcall load-fn file t))
(append (nreverse (file-expand-wildcards (concat doom-core-dir "core*.el")))
(file-expand-wildcards (concat doom-core-dir "autoload/*.el"))
(doom--module-paths "config.el")))))
(cl-loop for file
in (append (nreverse (file-expand-wildcards (expand-file-name "core*.el" doom-core-dir)))
(file-expand-wildcards (expand-file-name "autoload/*.el" doom-core-dir))
(doom--module-paths "config.el"))
do (funcall load-fn file t))))
(when (or force-p (not doom-packages))
(setq doom-packages nil)
(funcall load-fn (expand-file-name "packages.el" doom-core-dir))
(mapc (lambda (file) (funcall load-fn file t))
(doom--module-paths "packages.el")))))
(dolist (file (doom--module-paths "packages.el"))
(funcall load-fn file t)))))
(defun doom-initialize-modules (modules)
"Adds MODULES to `doom-modules'. MODULES must be in mplist format.
@ -213,15 +214,12 @@ This aggressively reloads core autoload files."
(error "No namespace specified on `doom!' for %s" m))
((eq m '*)
(doom-initialize-modules
(cons mode
(mapcar
(lambda (dir) (intern (file-name-nondirectory dir)))
(cl-remove-if-not
#'file-directory-p
(directory-files (expand-file-name
(substring (symbol-name mode) 1)
doom-modules-dir)
t "^\\w"))))))
(cl-loop with modpath = (expand-file-name (substring (symbol-name mode) 1) doom-modules-dir)
for path in (directory-files modpath t "^\\w")
if (file-directory-p path)
collect (intern (file-name-nondirectory path)) into paths
finally return (cons mode paths)
finally do (message "== %s %s" mode paths))))
(t
(doom--enable-module mode m))))))
@ -243,11 +241,9 @@ This aggressively reloads core autoload files."
(defun doom--module-pairs ()
"Returns `doom-modules' as a list of (MODULE . SUBMODULE) cons cells. The list
is sorted by order of insertion."
(let (pairs)
(when (hash-table-p doom-modules)
(maphash (lambda (key value) (push (cons (car key) (cdr key)) pairs))
doom-modules)
(nreverse pairs))))
(when (hash-table-p doom-modules)
(cl-loop for key being the hash-keys of doom-modules
collect (cons (car key) (cdr key)))))
(defun doom--module-paths (&optional append-file)
"Returns a list of absolute file paths to modules, with APPEND-FILE added, if
@ -291,19 +287,17 @@ byte-compilation."
(unless noninteractive
(load ,(doom-module-path :private user-login-name "init") t t)
,@(let (forms)
(dolist (module (doom--module-pairs))
(push `(require! ,(car module) ,(cdr module) t) forms))
(unless (doom-module-loaded-p :private (intern user-login-name))
(push `(require! :private ,user-login-name t) forms))
(nreverse forms))
,@(cl-loop for (module . submodule) in (doom--module-pairs)
collect `(require! ,module ,submodule t))
,(unless (doom-module-loaded-p :private (intern user-login-name))
`(require! :private ,user-login-name t))
(when (display-graphic-p)
(require 'server)
(unless (server-running-p)
(server-start)))
(add-hook 'after-init-hook #'doom--display-benchmark t))))
(add-hook 'emacs-startup-hook #'doom--display-benchmark t))))
(defmacro def-package! (name &rest plist)
"A thin wrapper around `use-package'."
@ -425,7 +419,7 @@ SUBMODULE is a symbol."
;; Commands
;;
(defun doom/reload (&optional ignorable-p)
(defun doom/reload ()
"Reload `load-path' and recompile files (if necessary). Useful if you
modify/update packages outside of emacs. Automatically called (through the
server, if necessary) by `doom/packages-install', `doom/packages-update' and
@ -434,7 +428,7 @@ server, if necessary) by `doom/packages-install', `doom/packages-update' and
(cond (noninteractive
(message "Reloading...")
(require 'server)
(unless (ignore-errors (server-eval-at "server" '(doom/reload t)))
(unless (ignore-errors (server-eval-at "server" '(doom/reload)))
(message "Recompiling")
(doom/recompile)))
(t
@ -454,35 +448,34 @@ In modules, checks modules/*/autoload.el and modules/*/autoload/*.el.
Rerun this whenever init.el is modified. You can also use `make autoloads` from
the commandline."
(interactive)
;; This function must not use `cl-lib', autoloaded functions or external
;; dependencies. It must assume nothing is set up!
;; This function must not use autoloaded functions or external dependencies.
;; It must assume nothing is set up!
(doom-initialize-packages (not noninteractive))
(let ((generated-autoload-file doom-autoload-file)
(autoload-files
(let ((evil-p (featurep! :feature evil))
(targets
(file-expand-wildcards
(expand-file-name "autoload/*.el" doom-core-dir))))
(dolist (path (doom--module-paths))
(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 autoload-files))
(push auto-file targets))
(when (file-directory-p auto-dir)
(mapc (lambda (file)
;; Make evil*.el autoload files a special case; don't load
;; them unless evil is enabled.
(unless (and (string-prefix-p "evil" (file-name-nondirectory file))
(not (featurep! :feature evil)))
(push file autoload-files)))
(file-expand-wildcards (expand-file-name "*.el" auto-dir) t)))))
(when (file-exists-p generated-autoload-file)
(delete-file generated-autoload-file)
(dolist (file (file-expand-wildcards (expand-file-name "*.el" auto-dir) t))
;; Make evil*.el autoload files a special case; don't load
;; them unless evil is enabled.
(unless (and (string-prefix-p "evil" (file-name-nondirectory file))
(not evil-p))
(push file targets))))))
(when (file-exists-p doom-autoload-file)
(delete-file doom-autoload-file)
(message "Deleted old autoloads.el"))
(dolist (file (nreverse autoload-files))
(dolist (file (nreverse targets))
(let ((inhibit-message (not doom-debug-mode)))
(update-file-autoloads file))
(update-file-autoloads file nil doom-autoload-file))
(message "Scanned %s" (file-relative-name file doom-emacs-dir)))
(condition-case ex
(let ((buf (get-file-buffer generated-autoload-file)))
(let ((buf (get-file-buffer doom-autoload-file)))
(unwind-protect
(with-current-buffer buf
(save-buffer)
@ -490,7 +483,7 @@ the commandline."
(message "Finished generating autoloads.el!"))
(kill-buffer buf)))
('error
(delete-file generated-autoload-file)
(delete-file doom-autoload-file)
(error "Couldn't evaluate autoloads.el: %s" (cadr ex))))))
(defun doom/compile (&optional lite-p only-recompile-p)
@ -506,46 +499,50 @@ If ONLY-RECOMPILE-P is non-nil, only recompile out-of-date files."
;; Ensure all relevant config files are loaded and up-to-date. This way we
;; don't need eval-when-compile and require blocks scattered all over.
(doom-initialize-packages t t)
(let ((targets (append (list "init.el" doom-core-dir)
(unless lite-p (doom--module-paths))))
(let ((targets
(cond ((equal (car command-line-args-left) "--")
(cl-loop for file in command-line-args-left
if (file-exists-p file)
collect (expand-file-name file)
finally do (setq command-line-args-list nil)) )
(t
(append (list (expand-file-name "init.el" doom-emacs-dir)
doom-core-dir)
(unless lite-p (doom--module-paths))))))
(total-success 0)
(total-fail 0)
(total-nocomp 0)
el-files)
(mapc (lambda (file)
(when (or (not only-recompile-p)
(let ((elc-file (byte-compile-dest-file file)))
(and (file-exists-p elc-file)
(file-newer-than-file-p file elc-file))))
(let ((result (byte-compile-file file))
(short-name (file-relative-name file doom-emacs-dir)))
(cl-incf
(cond ((eq result 'no-byte-compile)
(message! (dark (white "Ignored %s" short-name)))
total-nocomp)
((null result)
(message! (red "Failed to compile %s" short-name))
total-fail)
(t
(message! (green "Compiled %s" short-name))
total-success))))))
(dolist (path targets (reverse el-files))
(let ((path (expand-file-name path doom-emacs-dir)))
(cond ((file-directory-p path)
(setq el-files (append (directory-files-recursively path "\\.el$") el-files)))
((file-exists-p path)
(push path el-files))
(t
(error "Invalid path: %s" path))))))
(message!
(bold
(color (if (zerop total-fail) 'green 'red)
"%s %s file(s) %s"
(if only-recompile-p "Recompiled" "Compiled")
(format (if el-files "%d/%d" "%d")
total-success
(- (length el-files) total-nocomp))
(format "(%s not compiled)" total-nocomp))))))
(total-nocomp 0))
(let ((el-files (cl-loop for path in targets
if (file-directory-p path)
nconc (nreverse (directory-files-recursively path "\\.el$"))
else if (file-exists-p path)
collect path)))
(dolist (file el-files)
(when (or (not only-recompile-p)
(let ((elc-file (byte-compile-dest-file file)))
(and (file-exists-p elc-file)
(file-newer-than-file-p file elc-file))))
(let ((result (byte-compile-file file))
(short-name (file-relative-name file doom-emacs-dir)))
(cl-incf
(cond ((eq result 'no-byte-compile)
(message! (dark (white "Ignored %s" short-name)))
total-nocomp)
((null result)
(message! (red "Failed to compile %s" short-name))
total-fail)
(t
(message! (green "Compiled %s" short-name))
total-success))))))
(message!
(bold
(color (if (= total-fail 0) 'green 'red)
"%s %s file(s) %s"
(if only-recompile-p "Recompiled" "Compiled")
(format (if el-files "%d/%d" "%d")
total-success
(- (length el-files) total-nocomp))
(format "(%s ignored)" total-nocomp)))))))
(defun doom/recompile ()
"Recompile any compiled *.el files in your Emacs configuration."
@ -554,12 +551,6 @@ If ONLY-RECOMPILE-P is non-nil, only recompile out-of-date files."
;; In case `load-path' has changed (e.g. after an update)
(byte-recompile-file (expand-file-name "core.el" doom-core-dir) t))
(defun doom/compile-lite ()
"A light-weight version of `doom/compile' which only compiles core files in
your emacs configuration (init.el and core/**/*.el)."
(interactive)
(doom/compile t))
(defun doom/clean-cache ()
"Clear local cache (`doom-cache-dir'). You may need to restart Emacs for some
components to feel its effects."
@ -571,15 +562,14 @@ components to feel its effects."
"Delete all compiled elc files in DOOM emacs, excluding compiled ELPA/QUELPA
package files."
(interactive)
(let ((elc-files (append
(let ((init-elc (expand-file-name "init.elc" doom-emacs-dir)))
(if (file-exists-p init-elc) (list init-elc)))
(directory-files-recursively doom-core-dir "\\.elc$")
(directory-files-recursively doom-modules-dir "\\.elc$"))))
(if elc-files
(dolist (file elc-files)
(delete-file file)
(message "Deleting %s" (file-relative-name file doom-emacs-dir)))
(let ((targets (append (list (expand-file-name "init.elc" doom-emacs-dir))
(directory-files-recursively doom-core-dir "\\.elc$")
(directory-files-recursively doom-modules-dir "\\.elc$"))))
(unless (cl-loop for path in targets
if (file-exists-p path)
collect path
and do (delete-file path)
and do (message "Deleted %s" (file-relative-name path)))
(message "Everything is clean"))))

View file

@ -1,15 +1,16 @@
;;; core-popups.el --- taming sudden yet inevitable windows
;;; core-popups.el -*- lexical-binding: t; -*-
;; I want a "real"-buffer-first policy in my Emacsian utpoia; popup buffers
;; ought to be second-class citizens to "real" buffers. No need for a wall or
;; controversial immigration policies -- all we need is `shackle'.
;; controversial immigration policies -- all we need is `shackle' (and it will
;; actually work).
;;
;; The gist is: popups should always be displayed on one side of the frame, away
;; from 'real' buffers; they should be easy to dispose of when we don't want to
;; see them; and easily brought back in case we change our minds. Also, popups
;; should typically have no mode-line.
;; The gist is: popups should be displayed on one side of the frame, away from
;; 'real' buffers. They should be easy to dispose of when we don't want to see
;; them and easily brought back in case we change our minds. Also, popups should
;; typically have no mode-line.
;;
;; Be warned, this requires a lot of hackery and voodoo that could break with an
;; Be warned, this requires a lot of hackery voodoo that could break with an
;; emacs update or an update to any of the packages it tries to tame (like helm
;; or org-mode).
@ -43,7 +44,8 @@ is enabled/disabled.'")
;; Bootstrap
;;
(def-package! shackle :demand t
(def-package! shackle
:demand t
:init
(setq shackle-default-alignment 'below
shackle-default-size 8
@ -85,10 +87,8 @@ is enabled/disabled.'")
("^ \\*" :regexp t :size 12 :noselect t :autokill t :autoclose t)))
:config
(if (display-graphic-p)
(shackle-mode +1)
(add-transient-hook! 'after-make-frame-functions (shackle-mode +1))
(add-hook 'after-init-hook 'shackle-mode))
(add-transient-hook! 'after-make-frame-functions (shackle-mode +1))
(add-hook 'window-setup-hook #'shackle-mode)
(defun doom*shackle-always-align (plist)
"Ensure popups are always aligned and selected by default. Eliminates the need
@ -418,7 +418,7 @@ the command buffer."
(t
(magit-display-buffer-traditional buffer))))
(defun doom-magit-quit-window (kill-buffer)
(defun doom-magit-quit-window (_kill-buffer)
"Close the current magit window properly."
(let ((last (current-buffer)))
(cond ((when-let (dest (doom-buffers-in-mode
@ -438,7 +438,7 @@ the command buffer."
(after! mu4e
(defun doom*mu4e-popup-window (buf height)
(defun doom*mu4e-popup-window (buf _height)
(doom-popup-buffer buf :size 10 :noselect t)
buf)
(advice-add #'mu4e~temp-window :override #'doom*mu4e-popup-window))
@ -501,7 +501,7 @@ you came from."
;; Ensure these settings are attached to org-load-hook as late as possible,
;; giving other modules a chance to add their own hooks.
(add-hook! 'after-init-hook
(add-hook! 'emacs-startup-hook
(add-hook! 'org-load-hook
(set! :popup
'("*Calendar*" :size 0.4 :noselect t)
@ -532,7 +532,7 @@ you came from."
;; `org-edit-src-code' simply clones and narrows the buffer to a src block,
;; so we are secretly manipulating the same buffer. Since truely killing it
;; would kill the original org buffer we've got to do things differently.
(defun doom*org-src-switch-to-buffer (buffer context)
(defun doom*org-src-switch-to-buffer (buffer _context)
(if (eq org-src-window-setup 'switch-invisibly)
(set-buffer buffer)
(pop-to-buffer buffer)))

View file

@ -1,14 +1,11 @@
;;; core-projects.el --- tools for getting around your project
;; I want Emacs to be aware of the projects. `projectile' provides tools for
;; digging through project files and exposing an API I can use to make other
;; plugins/features project-aware.
;;; core-projects.el -*- lexical-binding: t; -*-
(defvar doom-project-hook nil
"Hook run when a project is enabled. The name of the project's mode and its
state are passed in.")
(def-package! projectile :demand t
(def-package! projectile
:demand t
:init
(setq projectile-cache-file (concat doom-cache-dir "projectile.cache")
projectile-enable-caching (not noninteractive)
@ -24,7 +21,7 @@ state are passed in.")
"build.gradle"))
:config
(projectile-mode +1)
(add-hook 'after-init-hook #'projectile-mode)
(setq projectile-other-file-alist
(append '(("less" "css")

View file

@ -1,4 +1,4 @@
;; core-ui.el --- draw me like one of your French editors
;; core-ui.el -*- lexical-binding: t; -*-
(defvar doom-ui-fringe-size '4 "Default fringe width")
@ -40,9 +40,6 @@
(fset #'yes-or-no-p #'y-or-n-p) ; y/n instead of yes/no
;; auto-enabled in Emacs 25+; I'd rather enable it manually
(global-eldoc-mode -1)
;; show typed keystrokes in minibuffer
(setq echo-keystrokes 0.02)
;; ...but hide them while isearch is active
@ -94,7 +91,7 @@ local value, whether or not it's permanent-local. Therefore, we cycle
(setq show-paren-delay 0.1
show-paren-highlight-openparen t
show-paren-when-point-inside-paren t)
(show-paren-mode +1)
(add-hook 'window-setup-hook #'show-paren-mode)
;;; More reliable inter-window border
;; The native border "consumes" a pixel of the fringe on righter-most splits,
@ -102,7 +99,7 @@ local value, whether or not it's permanent-local. Therefore, we cycle
(setq-default window-divider-default-places t
window-divider-default-bottom-width 1
window-divider-default-right-width 1)
(window-divider-mode +1)
(add-hook 'window-setup-hook #'window-divider-mode)
;; like diminish, but for major-modes. [pedantry intensifies]
(defvar doom-ui-mode-names
@ -122,13 +119,17 @@ mode is detected.")
;; Bootstrap
;;
;; auto-enabled in Emacs 25+; I'd rather enable it manually
(global-eldoc-mode -1)
;; draw me like one of your French editors
(tooltip-mode -1) ; relegate tooltips to echo area only
(menu-bar-mode -1)
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
(when (display-graphic-p)
(scroll-bar-mode -1)
;; buffer name in frame title
;; buffer name in frame title
(setq-default frame-title-format '("DOOM Emacs"))
;; standardize fringe width
(push (cons 'left-fringe doom-ui-fringe-size) default-frame-alist)
@ -191,7 +192,7 @@ file."
(set-buffer-modified-p nil))
nil)
(add-hook! (highlight-indentation-mode highlight-indentation-current-column-mode)
(defun doom|init-highlight-indentation ()
(if (or highlight-indentation-mode highlight-indentation-current-column-mode)
(progn
(doom|inject-trailing-whitespace)
@ -199,7 +200,9 @@ file."
(add-hook 'after-save-hook #'doom|inject-trailing-whitespace nil t))
(remove-hook 'before-save-hook #'delete-trailing-whitespace t)
(remove-hook 'after-save-hook #'doom|inject-trailing-whitespace t)
(delete-trailing-whitespace))))
(delete-trailing-whitespace)))
(add-hook! (highlight-indentation-mode highlight-indentation-current-column-mode)
#'doom|init-highlight-indentation))
;; For modes that don't adequately highlight numbers
(def-package! highlight-numbers :commands highlight-numbers-mode)
@ -265,8 +268,8 @@ file."
;; indicators for empty lines past EOF
(def-package! vi-tilde-fringe
:when (display-graphic-p)
:demand t
:config (global-vi-tilde-fringe-mode t))
:commands global-vi-tilde-fringe-mode
:init (add-hook 'window-setup-hook #'global-vi-tilde-fringe-mode))
;; For a distractions-free-like UI, that dynamically resizes margets and can
;; center a buffer.
@ -292,12 +295,11 @@ file."
(byte-compile #',sym))))))
(defsubst doom--prepare-modeline-segments (segments)
(let (segs)
(dolist (seg segments (nreverse segs))
(push (if (stringp seg)
seg
(list (intern (format "doom-modeline-segment--%s" (symbol-name seg)))))
segs))))
(cl-loop for seg in segments
if (stringp seg)
collect seg
else
collect (list (intern (format "doom-modeline-segment--%s" (symbol-name seg))))))
(defmacro def-modeline! (name lhs &optional rhs)
"Defines a modeline format and byte-compiles it. NAME is a symbol to identify

View file

@ -1,16 +1,16 @@
;;; core.el --- The heart of the beast
;;; core.el --- the heart of the beast -*- lexical-binding: t; -*-
;;; Naming conventions:
;;
;; doom-... public variables or functions (non-interactive)
;; doom-... public variables or non-interactive functions
;; doom--... private anything (non-interactive), not safe for direct use
;; doom/... an interactive function
;; doom/... an interactive function; safe for M-x or keybinding
;; doom:... an evil operator, motion or command
;; doom|... hook function
;; doom*... advising functions
;; ...! a macro or function that configures DOOM
;; %... functions used for in-snippet logic
;; +... Any of the above, but part of a module, e.g. +emacs-lisp|init-hook
;; +... Any of the above but part of a module, e.g. `+emacs-lisp|init-hook'
;;
;; Autoloaded functions are in core/autoload/*.el and modules/*/*/autoload.el or
;; modules/*/*/autoload/*.el.
@ -94,7 +94,7 @@ there are problems.")
;; History & backup settings (save nothing, that's what git is for)
auto-save-default nil
create-lockfiles nil
history-length 1000
history-length 500
make-backup-files nil
;; files
abbrev-file-name (concat doom-local-dir "abbrev.el")
@ -117,6 +117,7 @@ there are problems.")
(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)
@ -150,34 +151,41 @@ enable multiple minor modes for the same regexp.")
;;;
;; Bootstrap
(setq gc-cons-threshold 402653184
gc-cons-percentage 0.6)
(eval-and-compile
(defvar doom--file-name-handler-alist file-name-handler-alist)
(setq gc-cons-threshold 402653184
gc-cons-percentage 0.6
file-name-handler-alist nil)
(let (file-name-handler-alist)
(require 'cl-lib)
(eval-and-compile
(require 'core-packages (concat doom-core-dir "core-packages")))
(eval-when-compile
(doom-initialize))
(setq load-path (eval-when-compile load-path)
doom--package-load-path (eval-when-compile doom--package-load-path))
(require 'core-packages (concat doom-core-dir "core-packages")))
;;; Let 'er rip
(require 'core-lib)
(require 'core-os) ; consistent behavior across Oses
(with-demoted-errors "AUTOLOAD ERROR: %s"
(require 'autoloads doom-autoload-file t))
(eval-when-compile
(doom-initialize))
(unless noninteractive
(require 'core-ui) ; draw me like one of your French editors
(require 'core-popups) ; taming sudden yet inevitable windows
(require 'core-editor) ; baseline configuration for text editing
(require 'core-projects) ; making Emacs project-aware
(require 'core-keybinds))) ; centralized keybind system + which-key
(setq load-path (eval-when-compile load-path)
doom--package-load-path (eval-when-compile doom--package-load-path))
(add-hook! '(after-init-hook doom-reload-hook)
;;; Let 'er rip
(require 'core-lib)
(require 'core-os) ; consistent behavior across Oses
(with-demoted-errors "AUTOLOAD ERROR: %s"
(require 'autoloads doom-autoload-file t))
(unless noninteractive
(require 'core-ui) ; draw me like one of your French editors
(require 'core-popups) ; taming sudden yet inevitable windows
(require 'core-editor) ; baseline configuration for text editing
(require 'core-projects) ; making Emacs project-aware
(require 'core-keybinds)) ; centralized keybind system + which-key
(defun doom|init ()
(setq gc-cons-threshold 16777216
gc-cons-percentage 0.1))
gc-cons-percentage 0.1
file-name-handler-alist doom--file-name-handler-alist))
(add-hook! '(emacs-startup-hook doom-reload-hook)
#'doom|init)
(provide 'core)
;;; core.el ends here