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."