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

View file

@ -1,4 +1,4 @@
;;; init.el
;;; init.el -*- lexical-binding: t; -*-
;;
;; Author: Henrik Lissner <henrik@lissner.net>
;; URL: https://github.com/hlissner/.emacs.d

View file

@ -1,15 +1,15 @@
;;; app/email/autoload/email.el
;;; app/email/autoload/email.el -*- lexical-binding: t; -*-
;;;###autoload
(defun =email ()
"Start email client."
(interactive)
(call-interactively 'mu4e))
(call-interactively #'mu4e))
;;;###autoload
(defun +email/compose ()
"Compose a new email."
(interactive)
;; TODO Interactively select email account
(call-interactively 'mu4e-compose-new))
(call-interactively #'mu4e-compose-new))

View file

@ -1,4 +1,4 @@
;;; app/email/autoload/evil.el
;;; app/email/autoload/evil.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +email/mark (&optional beg end)
@ -8,11 +8,12 @@
(let* ((beg (or (and (region-active-p) evil-visual-beginning) (line-beginning-position)))
(end (or (and (region-active-p) evil-visual-end) (line-end-position)))
(key (this-command-keys))
(command (car (cl-find-if (lambda (mark) (equal (car (plist-get (cdr mark) :char)) key))
mu4e-marks))))
(command
(car (cl-find-if (lambda (mark) (equal (car (plist-get (cdr mark) :char)) key))
mu4e-marks))))
(unless command
(error "Not a valid mark command: %s" key))
(when (featurep 'evil)
(when (bound-and-true-p evil-mode)
(evil-normal-state))
(goto-char beg)
(dotimes (_ (count-lines beg end))

View file

@ -1,4 +1,4 @@
;;; app/email/config.el
;;; app/email/config.el -*- lexical-binding: t; -*-
;; I want to live in Emacs. Living is incomplete without email, so Emacs needs
;; to give me the ability to read, search, write and send my email. It does so
@ -16,9 +16,9 @@
(def-setting! :email (label letvars &optional default)
"Registers an email address for mu4e."
(let* ((name (or (cdr (assq 'user-full-name letvars)) user-full-name))
(address (cdr (assq 'user-mail-address letvars))))
(dolist (var letvars letvars)
(let ((name (or (cdr (assq 'user-full-name letvars)) user-full-name))
(address (cdr (assq 'user-mail-address letvars))))
(dolist (var letvars)
(let ((val (cdr var)))
(when (and (stringp val) (string-match-p "%s" val))
(setcdr var (format val label)))))
@ -96,15 +96,15 @@
("mime:image/*" "Messages with images" ?p)))
;; Add a column to display what email account the email belongs to.
(push '(:account
:name "Account"
:shortname "Account"
:help "Which account this email belongs to"
:function
(lambda (msg)
(let ((maildir (mu4e-message-field msg :maildir)))
(format "%s" (substring maildir 1 (string-match-p "/" maildir 1))))))
mu4e-header-info-custom)
(cl-pushnew '(:account
:name "Account"
:shortname "Account"
:help "Which account this email belongs to"
:function
(lambda (msg)
(let ((maildir (mu4e-message-field msg :maildir)))
(format "%s" (substring maildir 1 (string-match-p "/" maildir 1))))))
mu4e-header-info-custom)
;; In my workflow, emails won't be moved at all. Only their flags/labels are
;; changed. Se we redefine the trash and refile marks not to do any moving.

View file

@ -1,4 +1,4 @@
;;; app/present/autoload.el
;;; app/present/autoload.el -*- lexical-binding: t; -*-
;; --- impatient-mode -------------------------------------------------------------
@ -14,8 +14,9 @@
(+present--cleanup-impatient-mode)))
(defun +present--cleanup-impatient-mode ()
(unless (cl-remove-if-not (lambda (buf) (buffer-local-value 'impatient-mode buf))
(doom-buffer-list))
(unless (cl-loop for buf in (doom-buffer-list)
if (buffer-local-value 'impatient-mode buf)
return t)
(httpd-stop)
(remove-hook 'kill-buffer-hook '+present--cleanup-impatient-mode)))
@ -60,8 +61,9 @@
(text-scale-set +present-scale)))
(defun +present--cleanup-org-tree-slides-mode ()
(unless (cl-remove-if-not (lambda (buf) (buffer-local-value 'org-tree-slide-mode buf))
(doom-buffers-in-mode 'org-mode))
(unless (cl-loop for buf in (doom-buffers-in-mode 'org-mode)
if (buffer-local-value 'org-tree-slide-mode buf)
return t)
(org-tree-slide-mode -1)
(remove-hook 'kill-buffer-hook #'+present--cleanup-org-tree-slides-mode)))

View file

@ -1,4 +1,4 @@
;;; app/present/config.el
;;; app/present/config.el -*- lexical-binding: t; -*-
;; Sometimes you just get that urge to show off. I don't have a fancy car, so
;; my code or Emacs will have to do.
@ -68,7 +68,8 @@
(add-hook! 'org-tree-slide-mode-after-narrow-hook
#'(+present|detect-slide +present|add-overlays org-display-inline-images))
(add-hook! 'org-tree-slide-mode-hook
(defun +present|org-tree-present-mode ()
"TODO"
(doom/window-zoom)
(let ((arg (if org-tree-slide-mode +1 -1)))
(centered-window-mode arg)
@ -87,8 +88,10 @@
(set-face-attribute 'org-level-2 nil :height 1.0)
(+present|remove-overlays)
(org-remove-inline-images)))))
(add-hook 'org-tree-slide-mode-hook #'+present|org-tree-present-mode)
(defun +present*org-tree-slide-narrow-exclude-header (orig-fn &rest args)
"TODO"
(cl-letf (((symbol-function 'org-narrow-to-subtree)
(lambda () (save-excursion
(save-match-data

View file

@ -1,4 +1,4 @@
;;; app/rss/autoload.el
;;; app/rss/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun =rss ()

View file

@ -1,4 +1,4 @@
;;; app/rss/config.el
;;; app/rss/config.el -*- lexical-binding: t; -*-
;; This is an opinionated workflow that turns Emacs into an RSS reader, inspired
;; by apps Reeder and Readkit. It can be invoked via `=rss'. Otherwise, if you
@ -31,8 +31,8 @@
(make-directory elfeed-db-directory t)
;; Ensure elfeed buffers are treated as real
(push (lambda (buf) (string-match-p "^\\*elfeed" (buffer-name buf)))
doom-real-buffer-functions)
(cl-pushnew (lambda (buf) (string-match-p "^\\*elfeed" (buffer-name buf)))
doom-real-buffer-functions)
;; Enhance readability of a post
(add-hook 'elfeed-show-mode-hook #'+rss|elfeed-wrap)

View file

@ -1,4 +1,4 @@
;;; app/twitter/autoload.el
;;; app/twitter/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun =twitter ()
@ -7,7 +7,7 @@
(delete-other-windows)
(condition-case ex
(progn
(call-interactively 'twit)
(call-interactively #'twit)
(unless (get-buffer (car twittering-initial-timeline-spec-string))
(error "Failed to open twitter"))
(switch-to-buffer (car twittering-initial-timeline-spec-string))

View file

@ -1,4 +1,4 @@
;;; app/twitter/config.el
;;; app/twitter/config.el -*- lexical-binding: t; -*-
(def-package! twittering-mode
:commands twit

View file

@ -1,7 +1,8 @@
;;; app/write/autoload.el
;;; app/write/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(define-minor-mode +write-mode
"TODO"
:init-value nil
:keymap nil
(let ((arg (if +write-mode +1 -1))

View file

@ -1,4 +1,4 @@
;;; company.el
;;; completion/company/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +company/complete ()
@ -15,17 +15,18 @@
C-x C-l."
(interactive (list 'interactive))
(require 'company)
(unless (bound-and-true-p company-mode) (company-mode))
(let ((lines (split-string
(replace-regexp-in-string
"^[\t\s]+" ""
(concat (buffer-substring-no-properties (point-min) (line-beginning-position))
(buffer-substring-no-properties (line-end-position) (point-max))))
"\\(\r\n\\|[\n\r]\\)" t)))
(cl-case command
(interactive (company-begin-backend '+company/whole-lines))
(prefix (company-grab-line "^[\t\s]*\\(.+\\)" 1))
(candidates (all-completions arg lines)))))
(pcase command
('interactive (company-begin-backend '+company/whole-lines))
('prefix (company-grab-line "^[\t\s]*\\(.+\\)" 1))
('candidates
(all-completions
arg
(split-string
(replace-regexp-in-string
"^[\t\s]+" ""
(concat (buffer-substring-no-properties (point-min) (line-beginning-position))
(buffer-substring-no-properties (line-end-position) (point-max))))
"\\(\r\n\\|[\n\r]\\)" t)))))
;;;###autoload
(defun +company/dict-or-keywords ()

View file

@ -1,12 +1,11 @@
;;; completion/company/config.el
;;; completion/company/config.el -*- lexical-binding: t; -*-
(def-setting! :company-backend (modes backends)
"Register company BACKENDS to MODES."
(let* ((modes (if (listp modes) modes (list modes)))
(backends (if (listp backends) backends (list backends)))
(def-name (intern (format "doom--init-company-%s"
(mapconcat #'identity (mapcar #'symbol-name modes) "-"))))
(quoted (eq (car-safe backends) 'quote)))
(mapconcat #'identity (mapcar #'symbol-name modes) "-")))))
;; TODO more type checks
`(prog1
(defun ,def-name ()

View file

@ -1,7 +1,7 @@
;;; emacs/ido/config.el
;;; completion/ido/config.el -*- lexical-binding: t; -*-
(def-package! ido
:init
:config
(setq ido-ignore-buffers
'("\\` " "^\\*ESS\\*" "^\\*Messages\\*" "^\\*Help\\*" "^\\*Buffer"
"^\\*.*Completions\\*$" "^\\*Ediff" "^\\*tramp" "^\\*cvs-"
@ -16,7 +16,6 @@
ido-enable-last-directory-history t
ido-save-directory-list-file (concat doom-cache-dir "ido.last"))
:config
(push "\\`.DS_Store$" ido-ignore-files)
(push "Icon\\?$" ido-ignore-files)
@ -24,15 +23,15 @@
(ido-everywhere 1)
(require 'ido-ubiquitous)
(add-hook! ido-setup
(defun +ido|init ()
(require 'ido-vertical-mode)
(require 'flx-ido)
(require 'crm-custom)
(map! :map (ido-common-completion-map ido-completion-map ido-file-completion-map)
"C-n" #'ido-next-match
"C-p" #'ido-prev-match
"C-w" #'ido-delete-backward-word-updir))
(add-hook 'ido-setup-hook #'+ido|init)
(defun +ido*sort-mtime ()
"Sort ido filelist by mtime instead of alphabetically."
@ -43,16 +42,16 @@
(sixth (file-attributes (concat ido-current-directory b)))
(sixth (file-attributes (concat ido-current-directory a)))))))
(ido-to-end ;; move . files to end (again)
(delq nil (mapcar
(lambda (x) (and (char-equal (string-to-char x) ?.) x))
ido-temp-list))))
(cl-loop for x in ido-temp-list
if (char-equal (string-to-char x) ?.)
collect x)))
(advice-add #'ido-sort-mtime :override #'+ido*sort-mtime)
(add-hook! (ido-make-file-list ido-make-dir-list) #'+ido*sort-mtime)
(defun +ido|setup-home-keybind ()
"Go to $HOME with ~"
(define-key ido-file-completion-map (kbd "~")
(λ! (if (looking-back "/")
(λ! (if (looking-back "/" (point-min))
(insert "~/")
(call-interactively #'self-insert-command)))))
(add-hook 'ido-setup-hook #'+ido|setup-home-keybind))

View file

@ -1,5 +1,5 @@
;; -*- no-byte-compile: t; -*-
;;; emacs/ido/packages.el
;;; completion/ido/packages.el
(package! flx-ido)
(package! ido-ubiquitous)

View file

@ -1,4 +1,4 @@
;;; completion/ivy/autoload/evil.el
;;; completion/ivy/autoload/evil.el -*- lexical-binding: t; -*-
;;;###autoload (autoload '+ivy:swiper "completion/ivy/autoload/evil" nil t)
(evil-define-command +ivy:swiper (&optional search)
@ -19,7 +19,7 @@
(defvar +ivy--file-search-recursion-p t)
(defvar +ivy--file-search-all-files-p nil)
(defun +ivy--file-search (engine beg end query &optional directory prompt)
(defun +ivy--file-search (engine beg end query &optional directory)
(let* ((directory (or directory (doom-project-root)))
(recursion-p +ivy--file-search-recursion-p)
(all-files-p +ivy--file-search-all-files-p)

View file

@ -1,4 +1,4 @@
;;; completion/ivy/autoload/ivy.el
;;; completion/ivy/autoload/ivy.el -*- lexical-binding: t; -*-
;; Show more information in ivy-switch-buffer; and only display
;; workgroup-relevant buffers.
@ -6,33 +6,35 @@
(let ((min-name 5)
(min-mode 5)
(proot (doom-project-root)))
(mapcar
(lambda (b) (format (format "%%-%ds %%-%ds %%s" min-name min-mode)
(nth 0 b)
(nth 1 b)
(or (nth 2 b) "")))
(mapcar (lambda (b)
(with-current-buffer b
(let ((buffer-name (buffer-name b))
(mode-name (symbol-name major-mode)))
(when (> (length buffer-name) min-name)
(setq min-name (+ (length buffer-name) 15)))
(when (> (length mode-name) min-mode)
(setq min-mode (+ (length mode-name) 3)))
(list (concat
(propertize buffer-name
'face (cond ((string-match-p "^ ?\\*" buffer-name)
'font-lock-comment-face)
((not (string= proot (doom-project-root)))
'font-lock-keyword-face)
(buffer-read-only
'error)))
(when (and buffer-file-name (buffer-modified-p))
(propertize "[+]" 'face 'doom-modeline-buffer-modified)))
(propertize mode-name 'face 'font-lock-constant-face)
(when buffer-file-name
(abbreviate-file-name (file-name-directory buffer-file-name)))))))
(or buffer-list (doom-buffer-list))))))
(cl-loop for buf in (or buffer-list (doom-buffer-list))
collect
(destructuring-bind (type mode path)
(+ivy--get-buffer-attrs buf proot)
(format (format "%%-%ds %%-%ds %%s" min-name min-mode)
type mode (or path ""))))))
(defun +ivy--get-buffer-attrs (b &optional project-root)
(with-current-buffer b
(let ((buffer-name (buffer-name b))
(mode-name (symbol-name major-mode)))
(when (> (length buffer-name) min-name)
(setq min-name (+ (length buffer-name) 15)))
(when (> (length mode-name) min-mode)
(setq min-mode (+ (length mode-name) 3)))
(list (concat
(propertize buffer-name
'face (cond ((string-match-p "^ ?\\*" buffer-name)
'font-lock-comment-face)
((and project-root
(not (string= project-root (doom-project-root))))
'font-lock-keyword-face)
(buffer-read-only
'error)))
(when (and buffer-file-name (buffer-modified-p))
(propertize "[+]" 'face 'doom-modeline-buffer-modified)))
(propertize mode-name 'face 'font-lock-constant-face)
(when buffer-file-name
(abbreviate-file-name (file-name-directory buffer-file-name)))))))
(defun +ivy--select-buffer-action (buffer)
(ivy--switch-buffer-action
@ -66,54 +68,54 @@ limit to buffers in the current workspace."
:keymap ivy-switch-buffer-map
:caller '+ivy/switch-workspace-buffer))
;; TODO refactor ivy task candidate functions (messy!)
(defun +ivy--tasks-candidates (tasks)
"Generate a list of task tags (specified by `+ivy-task-tags') for
`+ivy/tasks'."
(let* ((max-type-width (seq-max (mapcar #'length (mapcar #'car +ivy-task-tags))))
(max-desc-width (seq-max (mapcar #'length (mapcar #'cl-cdadr tasks))))
(max-width (max 25 (min (- (frame-width) (+ max-type-width 1))
max-desc-width)))
(fmt (format "%%-%ds %%-%ds%%s%%s:%%s" max-type-width max-desc-width))
lines)
(dolist (alist tasks (nreverse lines))
(let-alist alist
(push (format fmt
(propertize .type 'face (cdr (assoc .type +ivy-task-tags)))
(substring .desc 0 (min max-desc-width (length .desc)))
(propertize " | " 'face 'font-lock-comment-face)
(propertize (abbreviate-file-name .file) 'face 'font-lock-keyword-face)
(propertize .line 'face 'font-lock-constant-face))
lines)))))
(let* ((max-type-width
(cl-loop for task in +ivy-task-tags maximize (length (car task))))
(max-desc-width
(cl-loop for task in tasks maximize (length (cl-cdadr task))))
(max-width (max (- (frame-width) (1+ max-type-width) max-desc-width)
25)))
(cl-loop
with fmt = (format "%%-%ds %%-%ds%%s%%s:%%s" max-type-width max-width)
for alist in tasks
collect
(let-alist alist
(format fmt
(propertize .type 'face (cdr (assoc .type +ivy-task-tags)))
(substring .desc 0 (min max-desc-width (length .desc)))
(propertize " | " 'face 'font-lock-comment-face)
(propertize (abbreviate-file-name .file) 'face 'font-lock-keyword-face)
(propertize .line 'face 'font-lock-constant-face))))))
(defun +ivy--tasks (target)
(let (case-fold-search)
(delq
nil
(mapcar (lambda (x)
(save-match-data
(when (string-match (concat "^\\([^:]+\\):\\([0-9]+\\):.+\\("
(string-join (mapcar #'car +ivy-task-tags) "\\|")
"\\):?\\s-*\\(.+\\)")
x)
`((type . ,(match-string 3 x))
(desc . ,(match-string 4 x))
(file . ,(match-string 1 x))
(line . ,(match-string 2 x))))))
(let ((command (or (let ((bin (executable-find "rg")))
(and bin (concat bin " --line-number")))
(let ((bin (executable-find "ag")))
(and bin (concat bin " --numbers")))
(error "Neither ripgrep or the_silver_searcher is available")))
(args (concat " -- "
(shell-quote-argument
(concat "\\s("
(string-join (mapcar #'car +ivy-task-tags) "|")
")([\\s:]|\\([^)]+\\):?)")))))
(when-let (out (shell-command-to-string
(format "%s -H -S --no-heading %s %s"
command args target)))
(split-string out "\n" t)))))))
(let* (case-fold-search
(task-tags (mapcar #'car +ivy-task-tags))
(cmd
(format "%s -H -S --no-heading -- %s %s"
(or (when-let (bin (executable-find "rg"))
(concat bin " --line-number"))
(when-let (bin (executable-find "ag"))
(concat bin " --numbers"))
(error "ripgrep & the_silver_searcher are unavailable"))
(shell-quote-argument
(concat "\\s("
(string-join task-tags "|")
")([\\s:]|\\([^)]+\\):?)"))
target)))
(save-match-data
(cl-loop with out = (shell-command-to-string cmd)
for x in (and out (split-string out "\n" t))
when (string-match
(concat "^\\([^:]+\\):\\([0-9]+\\):.+\\("
(string-join task-tags "\\|")
"\\):?\\s-*\\(.+\\)")
x)
collect `((type . ,(match-string 3 x))
(desc . ,(match-string 4 x))
(file . ,(match-string 1 x))
(line . ,(match-string 2 x)))))))
(defun +ivy--tasks-open-action (x)
"Jump to the file and line of the current task."
@ -180,27 +182,27 @@ counsel-rg)."
(defun +ivy/wgrep-occur ()
"Invoke the search+replace wgrep buffer on the current ag/rg search results."
(interactive)
(if (not (window-minibuffer-p))
(user-error "No completion session is active")
(require 'wgrep)
(let* ((caller (ivy-state-caller ivy-last))
(occur-fn (plist-get ivy--occurs-list caller))
(buffer
(generate-new-buffer
(format "*ivy-occur%s \"%s\"*"
(if caller (concat " " (prin1-to-string caller)) "")
ivy-text))))
(with-current-buffer buffer
(let ((inhibit-read-only t))
(erase-buffer)
(funcall occur-fn))
(setf (ivy-state-text ivy-last) ivy-text)
(setq ivy-occur-last ivy-last)
(setq-local ivy--directory ivy--directory))
(ivy-exit-with-action
`(lambda (_)
(pop-to-buffer ,buffer)
(ivy-wgrep-change-to-wgrep-mode))))))
(unless (window-minibuffer-p)
(user-error "No completion session is active"))
(require 'wgrep)
(let* ((caller (ivy-state-caller ivy-last))
(occur-fn (plist-get ivy--occurs-list caller))
(buffer
(generate-new-buffer
(format "*ivy-occur%s \"%s\"*"
(if caller (concat " " (prin1-to-string caller)) "")
ivy-text))))
(with-current-buffer buffer
(let ((inhibit-read-only t))
(erase-buffer)
(funcall occur-fn))
(setf (ivy-state-text ivy-last) ivy-text)
(setq ivy-occur-last ivy-last)
(setq-local ivy--directory ivy--directory))
(ivy-exit-with-action
`(lambda (_)
(pop-to-buffer ,buffer)
(ivy-wgrep-change-to-wgrep-mode)))))
;;;###autoload
(defun +ivy-yas-prompt (prompt choices &optional display-fn)

View file

@ -1,7 +1,8 @@
;;; completion/ivy/packages.el
;;; completion/ivy/config.el -*- lexical-binding: t; -*-
(defvar +ivy-task-tags '(("TODO" . warning)
("FIXME" . error))
(defvar +ivy-task-tags
'(("TODO" . warning)
("FIXME" . error))
"An alist of tags for `+ivy/tasks' to include in its search, whose CDR is the
face to render it with.")
@ -20,7 +21,8 @@ session)."
;; Packages
;;
(def-package! ivy :demand t
(def-package! ivy
:demand t
:config
(setq ivy-height 12
ivy-do-completion-in-region nil
@ -38,7 +40,7 @@ session)."
(after! magit (setq magit-completing-read-function #'ivy-completing-read))
(after! yasnippet (push #'+ivy-yas-prompt yas-prompt-functions))
(ivy-mode +1)
(add-hook 'window-setup-hook #'ivy-mode)
(map! :map ivy-mode-map
[remap describe-face] #'counsel-describe-face
@ -79,12 +81,16 @@ session)."
;; Configure `counsel-rg', `counsel-ag' & `counsel-pt'
(set! :popup 'ivy-occur-grep-mode :size (+ 2 ivy-height) :regexp t :autokill t)
(dolist (cmd '(counsel-ag counsel-rg counsel-pt))
(ivy-add-actions
cmd
'(("O" +ivy-git-grep-other-window-action "open in other window"))))
;; 1. Remove character limit from `counsel-ag-function'
;; 2. Disable ivy's over-zealous parentheses quoting behavior (if i want
;; literal parentheses, I'll escape them myself).
;; 3. This may need to be updated frequently, to meet changes upstream
;; 4. counsel-ag, counsel-rg and counsel-pt all use this function
(advice-add #'counsel-ag-function :override #'+ivy*counsel-ag-function))

View file

@ -1,42 +0,0 @@
;;; feature/debug/autoload.el
;;;###autoload
(defun +debug/quit ()
(interactive)
(ignore-errors (call-interactively 'realgud:cmd-quit))
(doom/popup-close)
(evil-normal-state))
;;;###autoload (autoload '+debug:debug-toggle-breakpoint "feature/debug/autoload" nil t)
;;;###autoload (autoload '+debug:run "feature/debug/autoload" nil t)
(after! evil
(evil-define-command +debug:run (&optional path)
"Initiate debugger for current major mode"
(interactive "<f>")
(let ((default-directory (doom-project-root)))
(cond ((memq major-mode '(c-mode c++-mode))
(realgud:gdb (if path (concat "gdb " path))))
((memq major-mode '(ruby-mode enh-ruby-mode))
(doom:repl nil (format "run '%s'" (file-name-nondirectory (or path buffer-file-name)))))
((eq major-mode 'sh-mode)
(let ((shell sh-shell))
(when (string= shell "sh")
(setq shell "bash"))
(cond ((string= shell "bash")
(realgud:bashdb (if path (concat "bashdb " path))))
((string= shell "zsh")
(realgud:zshdb (if path (concat "zshdb " path))))
(t (user-error "No shell debugger for %s" shell)))))
;; TODO Add python debugging
((memq major-mode '(js-mode js2-mode js3-mode))
(realgud:trepanjs))
((eq major-mode 'haskell-mode)
(haskell-debug))
(t (user-error "No debugger for %s" major-mode)))))
(evil-define-command +debug:debug-toggle-breakpoint (&optional bang)
(interactive "<!>")
(call-interactively (if bang 'realgud:cmd-clear 'realgud:cmd-break))))

View file

@ -0,0 +1,9 @@
;;; feature/debug/autoload/debug.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +debug/quit ()
(interactive)
(ignore-errors (call-interactively 'realgud:cmd-quit))
(doom/popup-close)
(evil-normal-state))

View file

@ -0,0 +1,31 @@
;;; feature/debug/autoload/evil.el -*- lexical-binding: t; -*-
;;;###autoload (autoload '+debug:run "feature/debug/autoload/evil" nil t)
(evil-define-command +debug:run (&optional path)
"Initiate debugger for current major mode"
(interactive "<f>")
(let ((default-directory (doom-project-root)))
(cond ((memq major-mode '(c-mode c++-mode))
(realgud:gdb (if path (concat "gdb " path))))
((memq major-mode '(ruby-mode enh-ruby-mode))
(doom:repl nil (format "run '%s'" (file-name-nondirectory (or path buffer-file-name)))))
((eq major-mode 'sh-mode)
(let ((shell sh-shell))
(when (string= shell "sh")
(setq shell "bash"))
(cond ((string= shell "bash")
(realgud:bashdb (if path (concat "bashdb " path))))
((string= shell "zsh")
(realgud:zshdb (if path (concat "zshdb " path))))
(t (user-error "No shell debugger for %s" shell)))))
;; TODO Add python debugging
((memq major-mode '(js-mode js2-mode js3-mode))
(realgud:trepanjs))
((eq major-mode 'haskell-mode)
(haskell-debug))
(t (user-error "No debugger for %s" major-mode)))))
;;;###autoload (autoload '+debug:toggle-breakpoint "feature/debug/autoload/evil" nil t)
(evil-define-command +debug:toggle-breakpoint (&optional bang)
(interactive "<!>")
(call-interactively (if bang 'realgud:cmd-clear 'realgud:cmd-break)))

View file

@ -1,4 +1,4 @@
;;; feature/debug/config.el
;;; feature/debug/config.el -*- lexical-binding: t; -*-
(def-package! realgud
:commands (realgud:gdb realgud:trepanjs realgud:bashdb realgud:zshdb)
@ -11,7 +11,7 @@
;; (def-tmp-excmd! doom:def-debug-on doom:def-debug-off
;; ("n[ext]" . realgud:cmd-next)
;; ("s[tep]" . realgud:cmd-step)
;; ("b[reak]" . doom:debug-toggle-breakpoint)
;; ("b[reak]" . +debug:toggle-breakpoint)
;; ("c[ontinue]" . realgud:cmd-continue))
;; (advice-add #'realgud-cmdbuf-init :after #'doom:def-debug-on)
;; (advice-add #'realgud:cmd-quit :after #'doom:def-debug-off)
@ -21,28 +21,26 @@
;; FIXME Causes realgud:cmd-* to focus popup on every invocation
(defun +debug*realgud-run-process
(debugger-name script-filename cmd-args minibuffer-history &optional no-reset)
(let ((cmd-buf))
(setq cmd-buf
(apply #'realgud-exec-shell debugger-name script-filename
(car cmd-args) no-reset (cdr cmd-args)))
(let ((process (get-buffer-process cmd-buf)))
(if (and process (eq 'run (process-status process)))
(progn
(pop-to-buffer cmd-buf)
(define-key evil-emacs-state-local-map (kbd "ESC ESC") #'+debug/quit)
(realgud:track-set-debugger debugger-name)
(realgud-cmdbuf-info-in-debugger?= 't)
(realgud-cmdbuf-info-cmd-args= cmd-args)
(when cmd-buf
(switch-to-buffer cmd-buf)
(when realgud-cmdbuf-info
(let* ((info realgud-cmdbuf-info)
(cmd-args (realgud-cmdbuf-info-cmd-args info))
(cmd-str (mapconcat #'identity cmd-args " ")))
(set minibuffer-history
(list-utils-uniq (cons cmd-str (eval minibuffer-history))))))))
(if cmd-buf (switch-to-buffer cmd-buf))
(message "Error running command: %s" (mapconcat #'identity cmd-args " "))))
(let* ((cmd-buf (apply #'realgud-exec-shell debugger-name script-filename
(car cmd-args) no-reset (cdr cmd-args)))
(process (get-buffer-process cmd-buf)))
(cond ((and process (eq 'run (process-status process)))
(pop-to-buffer cmd-buf)
(define-key evil-emacs-state-local-map (kbd "ESC ESC") #'+debug/quit)
(realgud:track-set-debugger debugger-name)
(realgud-cmdbuf-info-in-debugger?= 't)
(realgud-cmdbuf-info-cmd-args= cmd-args)
(when cmd-buf
(switch-to-buffer cmd-buf)
(when realgud-cmdbuf-info
(let* ((info realgud-cmdbuf-info)
(cmd-args (realgud-cmdbuf-info-cmd-args info))
(cmd-str (mapconcat #'identity cmd-args " ")))
(set minibuffer-history
(list-utils-uniq (cons cmd-str (eval minibuffer-history))))))))
(t
(if cmd-buf (switch-to-buffer cmd-buf))
(message "Error running command: %s" (mapconcat #'identity cmd-args " "))))
cmd-buf))
(advice-add #'realgud:run-process :override #'+debug*realgud-run-process))

View file

@ -1,4 +1,4 @@
;;; feature/eval/autoload/build.el
;;; feature/eval/autoload/build.el -*- lexical-binding: t; -*-
(defvar-local +eval-last-builder nil
"The last builder run in the current buffer.")
@ -22,9 +22,7 @@ functions.")
:key 'cdr))
(if (= (length builders) 1)
(car builders)
(when-let (builder (completing-read "Build: "
(mapcar #'car builders)
nil t))
(when-let (builder (completing-read "Build: " (mapcar #'car builders) nil t))
(assq (intern builder) builders)))))
;;;###autoload
@ -36,9 +34,8 @@ functions.")
(error "No builder for this buffer"))))
(unless builder
(error "Builder not found in registered builders"))
(let* ((name (car builder))
(plist (cdr builder))
(fn (plist-get plist :fn)))
(let ((name (car builder))
(fn (plist-get (cdr builder) :fn)))
(message "Running %s" name)
(if (or (functionp fn)
(and (symbolp fn) (fboundp fn)))

View file

@ -1,4 +1,4 @@
;;; feature/eval/autoload/eval.el
;;; feature/eval/autoload/eval.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +eval/buffer ()

View file

@ -1,4 +1,4 @@
;;; feature/eval/autoload/evil.el
;;; feature/eval/autoload/evil.el -*- lexical-binding: t; -*-
;;;###autoload (autoload '+eval:region "feature/eval/autoload/evil" nil t)
(evil-define-operator +eval:region (beg end)

View file

@ -1,28 +1,28 @@
;;; feature/eval/autoload/repl.el
;;; feature/eval/autoload/repl.el -*- lexical-binding: t; -*-
(defvar +eval-repl-buffer nil
"The buffer of the last open repl.")
(defun +eval--ensure-in-repl-buffer (&optional command)
(if (eq (current-buffer) +eval-repl-buffer)
t
(if (and +eval-repl-buffer (buffer-live-p +eval-repl-buffer))
(if-let (win (get-buffer-window +eval-repl-buffer))
(select-window win)
(doom-popup-buffer +eval-repl-buffer))
(when command
(let ((repl-buffer (save-window-excursion (call-interactively command))))
(unless (bufferp repl-buffer)
(error "REPL command didn't return a buffer"))
(with-current-buffer repl-buffer (+eval-repl-mode +1))
(setq +eval-repl-buffer repl-buffer)
(select-window (doom-popup-buffer repl-buffer)))))
(when (eq (current-buffer) +eval-repl-buffer)
(goto-char (if (and (derived-mode-p 'comint-mode)
(cdr comint-last-prompt))
(cdr comint-last-prompt)
(point-max)))
t)))
(or (eq (current-buffer) +eval-repl-buffer)
(progn
(if (and +eval-repl-buffer (buffer-live-p +eval-repl-buffer))
(if-let (win (get-buffer-window +eval-repl-buffer))
(select-window win)
(doom-popup-buffer +eval-repl-buffer))
(when command
(let ((repl-buffer (save-window-excursion (call-interactively command))))
(unless (bufferp repl-buffer)
(error "REPL command didn't return a buffer"))
(with-current-buffer repl-buffer (+eval-repl-mode +1))
(setq +eval-repl-buffer repl-buffer)
(select-window (doom-popup-buffer repl-buffer)))))
(when (eq (current-buffer) +eval-repl-buffer)
(goto-char (if (and (derived-mode-p 'comint-mode)
(cdr comint-last-prompt))
(cdr comint-last-prompt)
(point-max)))
t))))
;;;###autoload
(defun +eval/repl ()
@ -31,8 +31,8 @@ the cursor at the prompt."
(interactive)
(when-let (command (cdr (assq major-mode +eval-repls)))
(when (+eval--ensure-in-repl-buffer command)
(when (and (featurep 'evil) evil-mode)
(call-interactively 'evil-append-line))
(when (bound-and-true-p evil-mode)
(call-interactively #'evil-append-line))
t)))
;;;###autoload
@ -43,8 +43,8 @@ execute it immediately after."
(let ((selection (buffer-substring-no-properties beg end)))
(unless (+eval--ensure-in-repl-buffer)
(error "No REPL open"))
(when (and (featurep 'evil) evil-mode)
(call-interactively 'evil-append-line))
(when (bound-and-true-p evil-mode)
(call-interactively #'evil-append-line))
(insert (string-trim selection))
(when auto-execute-p
;; I don't use `comint-send-input' because different REPLs may have their

View file

@ -1,4 +1,4 @@
;;; feature/eval/config.el
;;; feature/eval/config.el -*- lexical-binding: t; -*-
;;
;; Code building

View file

@ -1,4 +1,4 @@
;;; feature/evil/autoload/evil-mc.el
;;; feature/evil/autoload/evil-mc.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +evil/mc-toggle-cursors ()
@ -21,9 +21,7 @@ cursors."
(interactive)
(cond ((memq evil-this-type '(block line))
(let ((col (evil-column))
(line-at-pt (line-number-at-pos))
(beg evil-visual-beginning)
(end evil-visual-end))
(line-at-pt (line-number-at-pos)))
;; Fix off-by-one error
(when (= evil-visual-direction 1)
(cl-decf col)
@ -36,7 +34,7 @@ cursors."
(move-to-column col)
(when (= (current-column) col)
(evil-mc-make-cursor-here))))
beg
evil-visual-beginning
(if (eq evil-this-type 'line) (1- evil-visual-end) evil-visual-end)
nil)
(evil-exit-visual-state))))

View file

@ -1,4 +1,4 @@
;;; feature/evil/autoload/evil.el
;;; feature/evil/autoload/evil.el -*- lexical-binding: t; -*-
(eval-when-compile (require 'subr-x))
@ -36,16 +36,13 @@ flags. See http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers
"\\([#%]\\)"
"\\(\\(?::\\(?:[PphtreS~.]\\|g?s[^:\t\n ]+\\)\\)*\\)"))
(matches
(let ((all-strings ())
(i 0))
(while (and (< i (length file-name))
(string-match regexp file-name i))
(setq i (1+ (match-beginning 0)))
(let (strings)
(push (dotimes (i (/ (length (match-data)) 2) (nreverse strings))
(push (match-string i file-name) strings))
all-strings)))
(nreverse all-strings))))
(cl-loop with i = 0
while (and (< i (length file-name))
(string-match regexp file-name i))
do (setq i (1+ (match-beginning 0)))
and collect
(cl-loop for j to (/ (length (match-data)) 2)
collect (match-string j file-name)))))
(dolist (match matches)
(let ((flags (split-string (car (cdr (cdr match))) ":" t))
(path (and buffer-file-name
@ -113,16 +110,18 @@ evil-window-move-* (e.g. `evil-window-move-far-left')"
(doom-popup-p that-window))
(setq that-buffer nil that-window nil))
(if (not (or that-window (one-window-p t)))
(funcall (case direction
('left 'evil-window-move-far-left)
('right 'evil-window-move-far-right)
('up 'evil-window-move-very-top)
('down 'evil-window-move-very-bottom)))
(funcall (pcase direction
('left #'evil-window-move-far-left)
('right #'evil-window-move-far-right)
('up #'evil-window-move-very-top)
('down #'evil-window-move-very-bottom)))
(unless that-window
(setq that-window
(split-window this-window nil (cond ((eq direction 'up) 'above)
((eq direction 'down) 'below)
(t direction))))
(split-window this-window nil
(pcase direction
('up 'above)
('down 'below)
(_ direction))))
(with-selected-window that-window
(switch-to-buffer doom-buffer))
(setq that-buffer (window-buffer that-window)))
@ -172,20 +171,22 @@ evil-window-move-* (e.g. `evil-window-move-far-left')"
;; --- custom arg handlers ----------------
(defvar +evil--flag nil)
(defun +evil--ex-match-init (name &optional face update-hook)
(with-current-buffer evil-ex-current-buffer
(cond
((eq flag 'start)
((eq +evil--flag 'start)
(evil-ex-make-hl name
:face (or face 'evil-ex-substitute-matches)
:update-hook (or update-hook #'evil-ex-pattern-update-ex-info))
(setq flag 'update))
(setq +evil--flag 'update))
((eq flag 'stop)
((eq +evil--flag 'stop)
(evil-ex-delete-hl name)))))
(defun +evil--ex-buffer-match (arg &optional hl-name flags beg end)
(when (and (eq flag 'update)
(when (and (eq +evil--flag 'update)
evil-ex-substitute-highlight-all
(not (zerop (length arg))))
(condition-case lossage
@ -209,21 +210,24 @@ evil-window-move-* (e.g. `evil-window-move-far-left')"
;;;###autoload
(defun +evil-ex-buffer-match (flag &optional arg)
(let ((hl-name 'evil-ex-buffer-match))
(let ((hl-name 'evil-ex-buffer-match)
(+evil--flag flag))
(with-selected-window (minibuffer-selected-window)
(+evil--ex-match-init hl-name)
(+evil--ex-buffer-match arg hl-name (list (if evil-ex-substitute-global ?g))))))
;;;###autoload
(defun +evil-ex-global-match (flag &optional arg)
(let ((hl-name 'evil-ex-global-match))
(let ((hl-name 'evil-ex-global-match)
(+evil--flag flag))
(with-selected-window (minibuffer-selected-window)
(+evil--ex-match-init hl-name)
(+evil--ex-buffer-match arg hl-name nil (point-min) (point-max)))))
;;;###autoload
(defun +evil-ex-global-delim-match (flag &optional arg)
(let ((hl-name 'evil-ex-global-delim-match))
(let ((hl-name 'evil-ex-global-delim-match)
(+evil--flag flag))
(with-selected-window (minibuffer-selected-window)
(+evil--ex-match-init hl-name)
(let ((result (car-safe (evil-delimited-arguments arg 2))))
@ -249,7 +253,7 @@ evil-window-move-* (e.g. `evil-window-move-far-left')"
"A wrapper around `evil-delete' for `wgrep' buffers that will invoke
`wgrep-mark-deletion' on lines you try to delete."
(interactive "<R><x><y>")
(condition-case ex
(condition-case _ex
(evil-delete beg end type register yank-handler)
('text-read-only
(evil-apply-on-block

View file

@ -1,4 +1,4 @@
;;; feature/evil/autoload/files.el
;;; feature/evil/autoload/files.el -*- lexical-binding: t; -*-
(defun +evil--forget-file (old-path &optional new-path)
"Ensure `recentf', `projectile' and `save-place' forget OLD-PATH."
@ -23,11 +23,9 @@ kills the buffer. If FORCE-P, force the deletion (don't ask for confirmation)."
(buf (current-buffer)))
(cond ((not (file-exists-p fname))
(error "File doesn't exist: %s" fname))
((not (or force-p (y-or-n-p (format "Really delete %s?" fbase))))
(message "Aborted")
nil)
(t
(unwind-protect
(progn (delete-file fname) t)
@ -38,8 +36,7 @@ kills the buffer. If FORCE-P, force the deletion (don't ask for confirmation)."
;; to real buffers (`doom-real-buffer-p')
(doom-force-kill-buffer buf t)
(+evil--forget-file fname)
(message "Successfully deleted %s" short-path)
)))))))
(message "Successfully deleted %s" short-path))))))))
(defun +evil--copy-file (old-path new-path &optional force-p)
(let* ((new-path (expand-file-name new-path))

View file

@ -1,9 +1,9 @@
;;; feature/evil/autoload/folds.el
;;; feature/evil/autoload/folds.el -*- lexical-binding: t; -*-
;; It's frustrating how hideshow is a decent code folding implementation, but it
;; won't let you create custom folds. Meanwhile, evil-vimish-fold offers custom
;; folds, but essentially ignores any other type of folding (indent or custom
;; markers, which hs-minor-mode gives you).
;; `hideshow' is a decent code folding implementation, but it won't let you
;; create custom folds. `evil-vimish-fold' offers custom folds, but essentially
;; ignores any other type of folding (indent or custom markers, which
;; hs-minor-mode gives you).
;;
;; So this is my effort to combine them.

View file

@ -1,4 +1,4 @@
;;; feature/evil/config.el
;;; feature/evil/config.el -*- lexical-binding: t; -*-
;; 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.
@ -41,7 +41,7 @@
shift-select-mode nil)
:config
(evil-mode +1)
(add-hook 'emacs-startup-hook #'evil-mode)
(evil-select-search-module 'evil-search-module 'evil-search)
(set! :popup
@ -170,7 +170,7 @@ across windows."
(def-package! evil-easymotion
:defer 1
:after evil-snipe
:config
(defvar +evil--snipe-repeat-fn
(evilem-create #'evil-snipe-repeat
@ -185,7 +185,6 @@ across windows."
(setq evil-embrace-show-help-p nil)
(evil-embrace-enable-evil-surround-integration)
;; Defuns
(defun +evil--embrace-get-pair (char)
(if-let (pair (cdr-safe (assoc (string-to-char char) evil-surround-pairs-alist)))
pair
@ -234,15 +233,15 @@ across windows."
(def-package! evil-escape
:demand t
:commands evil-escape-mode
:init
(setq evil-escape-excluded-states '(normal visual multiedit emacs)
evil-escape-excluded-major-modes '(neotree-mode)
evil-escape-key-sequence "jk"
evil-escape-delay 0.25)
(add-hook 'emacs-startup-hook #'evil-escape-mode)
:config
(evil-escape-mode +1)
(map! :irvo "C-g" #'evil-escape))
@ -330,7 +329,7 @@ the new algorithm is confusing, like in python or ruby."
(?\] "[]})]")
(?\; "[;:]")))
:config
(evil-snipe-override-mode +1))
(add-hook 'emacs-startup-hook #'evil-snipe-override-mode))
(def-package! evil-surround

View file

@ -1,4 +1,4 @@
;;; feature/file-templates/config.el
;;; feature/file-templates/config.el -*- lexical-binding: t; -*-
(require! :feature snippets)
@ -31,12 +31,13 @@
(overlay-get yas--active-field-overlay 'yas--field)))
(evil-initialize-state 'insert))))
(defun +file-templates|add (regexp trigger mode &optional project-only-p)
(define-auto-insert
regexp
(vector `(lambda () (+file-templates--expand ,trigger ',mode ,project-only-p)))))
(defun +file-templates-add (args)
(destructuring-bind (regexp trigger mode &optional project-only-p) args
(define-auto-insert
regexp
(vector `(lambda () (+file-templates--expand ,trigger ',mode ,project-only-p))))))
(mapc (lambda (args) (apply #'+file-templates|add args))
(mapc #'+file-templates-add
;; General
'(("/\\.gitignore$" "__" gitignore-mode)
("/Dockerfile$" "__" dockerfile-mode)

View file

@ -1,3 +1,3 @@
;;; `(file-relative-name buffer-file-name doom-modules-dir)`
;;; `(file-relative-name buffer-file-name doom-modules-dir)` -*- lexical-binding: t; -*-
$0

View file

@ -1,4 +1,4 @@
;;; `(file-name-nondirectory buffer-file-name)`${1: --- ${2:description}}
;;; `(file-name-nondirectory buffer-file-name)`${1: --- ${2:description}} -*- lexical-binding: t; -*-
$0

View file

@ -1,4 +1,4 @@
;;; feature/jump/autoload/evil.el
;;; feature/jump/autoload/evil.el -*- lexical-binding: t; -*-
;;;###autoload (autoload '+jump:online "feature/jump/autoload/evil" nil t)
(evil-define-command +jump:online (query &optional bang)
@ -6,11 +6,12 @@
reuse it on consecutive uses of this command. If BANG, always prompt for search
engine."
(interactive "<a><!>")
(setq query (or query (thing-at-point 'symbol t)))
(unless query
(user-error "The search query is empty"))
(let ((engine (or (and (not bang) (bound-and-true-p +jump--online-last))
(completing-read (format "Search on (%s): " query)
(mapcar #'car +jump-search-url-alist)
nil t))))
(+jump/online engine query)))
(let ((query (or query (thing-at-point 'symbol t))))
(unless query
(user-error "The search query is empty"))
(+jump/online
(or (and (not bang) (bound-and-true-p +jump--online-last))
(completing-read (format "Search on (%s): " query)
(mapcar #'car +jump-search-url-alist)
nil t))
query)))

View file

@ -1,4 +1,4 @@
;;; feature/jump/autoload.el
;;; feature/jump/autoload.el -*- lexical-binding: t; -*-
(defvar +jump--rg-installed-p (executable-find "rg"))
(defvar +jump--ag-installed-p (executable-find "ag"))
@ -42,12 +42,11 @@ Tries xref and falls back to `dumb-jump', then rg/ag, then
((and (featurep 'evil)
evil-mode
(let ((bounds (bounds-of-thing-at-point 'symbol))
(orig-pt (point)))
(destructuring-bind (beg end) (bounds-of-thing-at-point 'symbol)
(evil-goto-definition)
(let ((pt (point)))
(not (and (>= pt (car bounds))
(< pt (cdr bounds))))))))
(not (and (>= pt beg)
(< pt end)))))))
(t (user-error "Couldn't find '%s'" sym)))))
@ -58,9 +57,8 @@ Tries xref and falls back to `dumb-jump', then rg/ag, then
Tries `xref-find-references' and falls back to rg/ag."
(interactive)
(let ((sym (thing-at-point 'symbol t)))
(cond ((progn
(ignore-errors (xref-find-references sym)
t)))
(cond ((ignore-errors (xref-find-references sym)
t))
((and sym
(featurep 'counsel)
@ -87,7 +85,7 @@ Interactively, you are prompted to choose a source from
(mapcar #'car +jump-search-url-alist)
nil t))
(thing-at-point 'symbol t)))
(condition-case ex
(condition-case _ex
(let ((url (cdr (assoc where +jump-search-url-alist))))
(unless url
(error "'%s' is an invalid search engine" where))

View file

@ -1,4 +1,4 @@
;;; feature/jump/config.el
;;; feature/jump/config.el -*- lexical-binding: t; -*-
;; "What am I looking at?"
;;

View file

@ -1,4 +1,4 @@
;;; feature/snippets/autoload/evil.el
;;; feature/snippets/autoload/evil.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +snippets/expand-on-region ()

View file

@ -1,4 +1,4 @@
;;; feature/snippets/autoload/snippets.el
;;; feature/snippets/autoload/snippets.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +snippets/goto-start-of-field ()

View file

@ -1,4 +1,4 @@
;;; feature/snippets/config.el
;;; feature/snippets/config.el -*- lexical-binding: t; -*-
;; Snippets! I've thrown together a few hacks to make `yasnippet' and `evil'
;; behave together.

View file

@ -1,4 +1,4 @@
;;; feature/spellcheck/config.el
;;; feature/spellcheck/config.el -*- lexical-binding: t; -*-
(def-package! flyspell ; built-in
:commands flyspell-mode

View file

@ -1,4 +1,4 @@
;;; feature/syntax-checker/config.el
;;; feature/syntax-checker/config.el -*- lexical-binding: t; -*-
;; pkg-info doesn't get autoloaded when `flycheck-version' needs it, so we do
;; it ourselves:

View file

@ -1,4 +1,4 @@
;;; feature/version-control/+git.el
;;; feature/version-control/+git.el -*- lexical-binding: t; -*-
(def-package! gitconfig-mode
:mode "/\\.?git/?config$"

View file

@ -1,4 +1,4 @@
;;; feature/version-control/autoload.el
;;; feature/version-control/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +vcs-root ()
@ -15,8 +15,8 @@
"Open the website for the current version controlled file. Fallback to
repository root."
(interactive)
(let ((git-link-open-in-browser t))
(call-interactively 'git-link)))
(destructuring-bind (beg end) (if buffer-file-name (git-link--get-region))
(git-link (git-link--select-remote) beg end)))
;;;###autoload
(defun +vcs/git-browse-issues ()

View file

@ -1,4 +1,4 @@
;;; feature/version-control/config.el
;;; feature/version-control/config.el -*- lexical-binding: t; -*-
(setq vc-make-backup-files nil)

View file

@ -1,4 +1,4 @@
;;; feature/workspaces/autoload/evil.el
;;; feature/workspaces/autoload/evil.el -*- lexical-binding: t; -*-
;;;###autoload (autoload '+workspace:save-session "feature/workspaces/autoload/evil" nil t)
(evil-define-command +workspace:save-session (&optional bang name)

View file

@ -1,4 +1,4 @@
;;; feature/workspaces/autoload/workspaces.el
;;; feature/workspaces/autoload/workspaces.el -*- lexical-binding: t; -*-
(defvar +workspace-workspace-file "_workspaces"
"The file basename in which to store single workspace perspectives.")
@ -139,12 +139,11 @@ perspective or its hash table."
(persp-frame-switch name))
(defun +workspace--generate-id ()
(let ((numbers (mapcar (lambda (it) (string-to-number (substring it 1)))
(cl-remove-if-not (lambda (it) (string-match-p "^#[0-9]+$" it))
(+workspace-list)))))
(if numbers
(1+ (car (sort numbers (lambda (it other) (> it other)))))
1)))
(or (cl-loop for name in (+workspace-list)
when (string-match-p "^#[0-9]+$" name)
maximize (string-to-number (substring name 1)) into max
finally return (if max (1+ max)))
1))
(defun +workspace-protected-p (name)
(or (equal name persp-nil-name)
@ -373,17 +372,16 @@ the workspace and move to the next."
(defun +workspace--tabline (&optional names)
(let ((names (or names (+workspace-list)))
(current-name (+workspace-current-name))
(i 0))
(current-name (+workspace-current-name)))
(mapconcat
#'identity
(mapcar (lambda (it)
(cl-incf i)
(propertize (format " [%d] %s " i it)
'face (if (equal current-name it)
'+workspace-tab-selected-face
'+workspace-tab-face)))
names)
(cl-loop for name in names
for i to (length names)
collect
(propertize (format " [%d] %s " i name)
'face (if (equal current-name name)
'+workspace-tab-selected-face
'+workspace-tab-face)))
" ")))
(defun +workspace--message-body (message &optional type)

View file

@ -1,4 +1,4 @@
;;; feature/workspaces/config.el
;;; feature/workspaces/config.el -*- lexical-binding: t; -*-
;; `persp-mode' gives me workspaces, a workspace-restricted `buffer-list', and
;; file-based session persistence. I had used workgroups2 before this, but
@ -24,7 +24,8 @@ renamed.")
;; Plugins
;;
(def-package! persp-mode :demand t
(def-package! persp-mode
:demand t
:config
(setq persp-autokill-buffer-on-remove 'kill-weak
persp-nil-name "nil"
@ -44,35 +45,34 @@ renamed.")
(defun +workspaces|init (&rest _)
(unless persp-mode
(persp-mode +1))
;; The default perspective persp-mode makes (defined by `persp-nil-name') is
;; special and doesn't actually represent a real persp object, so buffers
;; can't really be assigned to it, among other quirks. We create a *real*
;; main workspace to fill this role.
(persp-add-new +workspaces-main)
;; Switch to it if we aren't auto-loading the last session
(when (or (= persp-auto-resume-time -1)
(equal (safe-persp-name (get-current-persp)) persp-nil-name))
(persp-frame-switch +workspaces-main)))
(persp-mode +1)
;; The default perspective persp-mode makes (defined by `persp-nil-name')
;; is special and doesn't actually represent a real persp object, so
;; buffers can't really be assigned to it, among other quirks. We create a
;; *real* main workspace to fill this role.
(persp-add-new +workspaces-main)
;; Switch to it if we aren't auto-loading the last session
(when (or (= persp-auto-resume-time -1)
(equal (safe-persp-name (get-current-persp)) persp-nil-name))
(persp-frame-switch +workspaces-main))))
(add-hook! 'after-init-hook
(if (display-graphic-p)
(+workspaces|init)
(add-hook 'after-make-frame-functions #'+workspaces|init)))
(add-hook 'emacs-startup-hook #'+workspaces|init)
(add-hook 'after-make-frame-functions #'+workspaces|init)
(define-key persp-mode-map [remap delete-window] #'+workspace/close-window-or-workspace)
;; Spawn a perspective for each new frame
(setq persp-init-new-frame-behaviour-override nil
persp-interactive-init-frame-behaviour-override
(lambda (frame &optional new-frame-p)
(lambda (frame &optional _new-frame-p)
(select-frame frame)
(+workspace/new)
(set-frame-parameter frame 'assoc-persp (+workspace-current-name))))
(defun +workspaces*delete-frame-and-persp (frame)
"Delete workspace associated with current frame IF it has no real buffers."
(when (and (string= (or (frame-parameter frame 'assoc-persp) "") (+workspace-current-name))
(when (and (string= (or (frame-parameter frame 'assoc-persp) "")
(+workspace-current-name))
(not (delq (doom-fallback-buffer) (doom-real-buffers-list))))
(+workspace/delete persp-name)))
(add-hook 'delete-frame-functions #'+workspaces*delete-frame-and-persp)

View file

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

View file

@ -1,4 +1,4 @@
;;; lang/cc/autoload.el
;;; lang/cc/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +cc/autoclose->-maybe ()

View file

@ -1,4 +1,4 @@
;;; lang/cc/config.el --- C, C++, and Objective-C
;;; lang/cc/config.el --- c, c++, and obj-c -*- lexical-binding: t; -*-
(def-package! cc-mode
:commands (c-mode c++-mode objc-mode java-mode)
@ -67,7 +67,7 @@
(c-set-offset 'arglist-intro '+)
(c-set-offset 'arglist-close '0)
(defun +cc--c-lineup-inclass (langelem)
(defun +cc--c-lineup-inclass (_langelem)
(if (memq major-mode '(c-mode c++-mode))
(let ((inclass (assq 'inclass c-syntactic-context)))
(save-excursion
@ -115,12 +115,15 @@
(def-package! irony
:after cc-mode
:commands irony-install-server
:init
(add-hook! 'c-mode-common-hook
(when (memq major-mode '(c-mode c++-mode objc-mode))
(irony-mode +1)))
:config
:preface
(setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
:init
(defun +cc|init-irony-mode ()
(when (memq major-mode '(c-mode c++-mode objc-mode))
(when (file-directory-p irony-server-install-prefix)
(irony-mode +1))))
(add-hook 'c-mode-common-hook #'+cc|init-irony-mode)
:config
(add-hook! 'irony-mode-hook #'(irony-eldoc flycheck-mode))
(add-hook! 'c++-mode-hook
(make-local-variable 'irony-additional-clang-options)

View file

@ -1,4 +1,4 @@
;;; lang/clojure/config.el
;;; lang/clojure/config.el -*- lexical-binding: t; -*-
(def-package! clojure-mode
:mode "\\.clj$")
@ -6,5 +6,4 @@
(def-package! cider
:commands (cider-jack-in cider-mode)
:config
(setq
nrepl-hide-special-buffers t))
(setq nrepl-hide-special-buffers t))

View file

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

View file

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

View file

@ -1,4 +1,4 @@
;;; module-data.el
;;; lang/data/config.el -*- lexical-binding: t; -*-
(push '("/sxhkdrc" . conf-mode) auto-mode-alist)

View file

@ -1,2 +1,2 @@
;;; lang/elixir/autoload/elixir.el
;;; lang/elixir/autoload/elixir.el -*- lexical-binding: t; -*-

View file

@ -1,10 +1,9 @@
;;; lang/elixir/config.el
;;; lang/elixir/config.el -*- lexical-binding: t; -*-
(def-package! elixir-mode
:mode ("\\.ex$")
:mode "\\.ex$"
:init
(add-hook 'elixir-mode-hook #'turn-off-smartparens-mode)
(add-hook 'elixir-mode-hook #'alchemist)
(add-hook! 'elixir-mode-hook #'(turn-off-smartparens-mode alchemist))
:config
(set! :company-backend 'elixir-mode '(alchemist-company company-yasnippet)))

View file

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

View file

@ -1,4 +1,4 @@
;;; lang/emacs-lisp/autoload.el
;;; lang/emacs-lisp/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +emacs-lisp/repl ()
@ -20,18 +20,16 @@ to a pop up buffer."
(buf (get-buffer-create "*doom eval*"))
(inhibit-read-only t)
lines)
(unwind-protect
(progn
(with-current-buffer buf
(read-only-mode +1)
(erase-buffer)
(setq-local scroll-margin 0)
(emacs-lisp-mode)
(prin1 result buf)
(pp-buffer)
(setq lines (count-lines (point-min) (point-max)))
(goto-char (point-min))
(if (> lines 1)
(doom-popup-buffer buf)
(message "%s" (buffer-substring (point-min) (point-max)))
(kill-buffer buf)))))))
(with-current-buffer buf
(read-only-mode +1)
(erase-buffer)
(setq-local scroll-margin 0)
(emacs-lisp-mode)
(prin1 result buf)
(pp-buffer)
(setq lines (count-lines (point-min) (point-max)))
(goto-char (point-min))
(if (> lines 1)
(doom-popup-buffer buf)
(message "%s" (buffer-substring (point-min) (point-max)))
(kill-buffer buf)))))

View file

@ -1,10 +1,9 @@
;;; lang/emacs-lisp/config.el
;;; lang/emacs-lisp/config.el -*- lexical-binding: t; -*-
(def-package! elisp-mode ; built-in
:mode ("/Cask$" . emacs-lisp-mode)
:init
(add-hook 'emacs-lisp-mode-hook #'+emacs-lisp|hook)
:config
(set! :repl 'emacs-lisp-mode #'+emacs-lisp/repl)
(set! :eval 'emacs-lisp-mode #'+emacs-lisp-eval)

View file

@ -1,4 +1,4 @@
;;; lang/go/autoload.el
;;; lang/go/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
;; TODO (defun +go/build ())

View file

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

View file

@ -1,4 +1,4 @@
;;; module-haskell.el
;;; lang/haskell/config.el -*- lexical-binding: t; -*-
(def-package! haskell-mode
:mode "\\.hs$"
@ -10,7 +10,6 @@
(load "haskell-mode-autoloads" nil t)
(set! :repl 'haskell-mode #'switch-to-haskell)
(push ".hi" completion-ignored-extensions)
(autoload 'switch-to-haskell "inf-haskell" nil t)

View file

@ -1,4 +1,4 @@
;;; lang/java/config.el
;;; lang/java/config.el -*- lexical-binding: t; -*-
;; yasnippet defuns
;;;###autoload
@ -9,7 +9,7 @@
;;;###autoload
(defun +java-android-mode-in-tags (&rest tags)
(-contains? tags (android-mode-tag-name)))
(cl-find (android-mode-tag-name) tags))
;;;###autoload
(defun +java-android-mode-tag-name ()

View file

@ -1,4 +1,4 @@
;;; lang/java/config.el
;;; lang/java/config.el -*- lexical-binding: t; -*-
(def-package! meghanada
:commands meghanada-mode

View file

@ -1,4 +1,4 @@
;;; lang/javascript/+screeps.el
;;; lang/javascript/+screeps.el -*- lexical-binding: t; -*-
;; TODO Constants may be out-of-date
@ -171,8 +171,9 @@
:match "/screeps/.+$"
:modes (+javascript-npm-mode))
(add-hook! '+javascript-screeps-mode-hook
(defun +javascript|init-screeps-mode ()
(when (eq major-mode 'js2-mode)
(push 'javascript-jshint flycheck-disabled-checkers)
(cl-pushnew 'javascript-jshint flycheck-disabled-checkers)
(setq js2-additional-externs (append '("_") screeps-objects screeps-constants))))
(add-hook '+javascript-screeps-mode-hook #'+javascript|init-screeps-mode)

View file

@ -1,4 +1,4 @@
;;; lang/javascript/autoload.el
;;; lang/javascript/autoload.el -*- lexical-binding: t; -*-
(defvar +javascript-npm-conf (make-hash-table :test 'equal))
@ -17,13 +17,13 @@ ignore the cache."
;;;###autoload
(defun +javascript-npm-dep-p (packages &optional project-root refresh-p)
(when-let (data (and (bound-and-true-p +javascript-npm-mode)
(+javascript-npm-conf)))
(+javascript-npm-conf project-root refresh-p)))
(let ((deps (append (cdr (assq 'dependencies data))
(cdr (assq 'devDependencies data)))))
(cond ((listp packages)
(funcall (if (eq (car packages) 'and)
'cl-every
'cl-some)
#'cl-every
#'cl-some)
(lambda (pkg) (assq pkg deps))
(if (listp packages) packages (list packages))))
((symbolp packages)

View file

@ -1,4 +1,4 @@
;; lang/javascript/config.el
;;; lang/javascript/config.el -*- lexical-binding: t; -*-
(load! +screeps)
@ -17,12 +17,13 @@
(add-hook! 'js2-mode-hook (setq js-switch-indent-offset js-indent-level))
;; Favor local eslint over global, if available
(add-hook! 'flycheck-mode-hook
(defun +javascript|init-flycheck-elint ()
(when (derived-mode-p 'js-mode 'js2-mode)
(when-let ((eslint (expand-file-name "node_modules/eslint/bin/eslint.js" (doom-project-root)))
(exists-p (file-exists-p eslint))
(executable-p (file-executable-p eslint)))
(setq-local flycheck-javascript-eslint-executable eslint))))
(add-hook 'flycheck-mode-hook #'+javascript|init-flycheck-elint)
(set! :repl 'js2-mode '+javascript/repl)
(set! :electric 'js2-mode :chars '(?\} ?\) ?.))

View file

@ -1,4 +1,4 @@
;;; lang/julia/autoload.el
;;; lang/julia/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +julia/repl ()

View file

@ -1,4 +1,4 @@
;;; lang/julia/config.el
;;; lang/julia/config.el -*- lexical-binding: t; -*-
(use-package julia-mode
:mode "\\.jl$"

View file

@ -1,4 +1,4 @@
;;; lang/latex/config.el
;;; lang/latex/config.el -*- lexical-binding: t; -*-
(defvar +latex-bibtex-dir "~/work/writing/biblio/"
"Where bibtex files are kept.")

View file

@ -1,9 +1,9 @@
;;; lang/lua/autoload.el
;;; lang/lua/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +lua/repl ()
"Open Lua REPL."
(interactive)
(lua-start-process "lua" "lua")
(pop-to-buffer lua-process-buffer))

View file

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

View file

@ -1,7 +1,7 @@
;;; lang/markdown/autoload.el
;;; lang/markdown/autoload.el -*- lexical-binding: t; -*-
;; Implement strike-through formatting
(defvar +text--markdown-regex-del
(defvar +markdown--regex-del
"\\(^\\|[^\\]\\)\\(\\(~\\{2\\}\\)\\([^ \n \\]\\|[^ \n ]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(\\3\\)\\)")
;;;###autoload
@ -11,12 +11,13 @@
(let ((delim "~~"))
(if (markdown-use-region-p)
;; Active region
(let ((bounds (markdown-unwrap-things-in-region
(region-beginning) (region-end)
+text--markdown-regex-del 2 4)))
(markdown-wrap-or-insert delim delim nil (car bounds) (cdr bounds)))
(destructuring-bind (beg end)
(markdown-unwrap-things-in-region
(region-beginning) (region-end)
+markdown--regex-del 2 4)
(markdown-wrap-or-insert delim delim nil beg end))
;; Bold markup removal, bold word at point, or empty markup insertion
(if (thing-at-point-looking-at +text--markdown-regex-del)
(if (thing-at-point-looking-at +markdown--regex-del)
(markdown-unwrap-thing-at-point nil 2 4)
(markdown-wrap-or-insert delim delim 'word nil nil)))))

View file

@ -1,4 +1,4 @@
;;; lang/markdown/config.el
;;; lang/markdown/config.el -*- lexical-binding: t; -*-
(def-package! markdown-mode
:mode ("\\.m\\(d\\|arkdown\\)$" "/README$"

View file

@ -1,4 +1,4 @@
;;; lang/php/autoload.el
;;; lang/php/autoload.el -*- lexical-binding: t; -*-
(defvar +php-composer-conf (make-hash-table :test 'equal))

View file

@ -1,4 +1,4 @@
;;; lang/php/config.el
;;; lang/php/config.el -*- lexical-binding: t; -*-
;; (def-package! hack-mode
;; :mode "\\.hh$"
@ -52,7 +52,8 @@
;; company will set up itself
(advice-add #'php-extras-company-setup :override #'ignore)
:config
(setq php-extras-eldoc-functions-file (concat doom-etc-dir "php-extras-eldoc-functions"))
(setq php-extras-eldoc-functions-file
(concat doom-etc-dir "php-extras-eldoc-functions"))
;; Make expensive php-extras generation async
(unless (file-exists-p (concat php-extras-eldoc-functions-file ".el"))

View file

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

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