Merge branch 'develop' of https://github.com/hlissner/doom-emacs into develop

This commit is contained in:
hackeryarn 2018-08-19 14:29:21 -05:00
commit 765a078685
62 changed files with 1072 additions and 3245 deletions

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash
":"; EMACS=${EMACS:-emacs} # -*-emacs-lisp-*-
":"; [[ $EMACS = *"term"* ]] && EMACS=emacs || EMACS=${EMACS:-emacs} # -*-emacs-lisp-*-
":"; command -v $EMACS >/dev/null || { >&2 echo "Emacs isn't installed"; exit 1; }
":"; VERSION=$($EMACS --version | head -n1)
":"; [[ $VERSION == *\ 2[0-2].[0-1].[0-9] ]] && { echo "You're running $VERSION"; echo "That version is too old to run Doom. Check your PATH"; echo; exit 2; }
@ -88,6 +88,8 @@
(setq argv nil
noninteractive 'doom)
(condition-case e (doom-dispatch args)
(user-error
(signal (car e) (cdr e)))
((debug error)
(message "--------------------------------------------------\n")
(message "There was an unexpected error:")

View file

@ -11,7 +11,8 @@
"Returns diagnostic information about the current Emacs session in markdown,
ready to be pasted in a bug report on github."
(require 'vc-git)
(let ((default-directory doom-emacs-dir))
(let ((default-directory doom-emacs-dir)
(doom-modules (doom-modules)))
(format
(concat "- OS: %s (%s)\n"
"- Emacs: %s (%s)\n"
@ -47,7 +48,7 @@ ready to be pasted in a bug report on github."
(insert (format "%s" system-type)))
(string-trim (buffer-string))))
(or (cl-loop with cat = nil
for key being the hash-keys of (doom-modules)
for key being the hash-keys of doom-modules
if (or (not cat) (not (eq cat (car key))))
do (setq cat (car key)) and collect cat
else collect
@ -124,16 +125,13 @@ branch and commit."
;;;###autoload
(defun doom/copy-backtrace ()
"Copy the first 1000 bytes from the *Backtrace* window into your clipboard for
easy pasting into a bug report or discord."
"Copy the contents of the *Backtrace* window into your clipboard for easy
pasting into a bug report or discord."
(interactive)
(if-let* ((buf (get-buffer "*Backtrace*")))
(with-current-buffer buf
(kill-new
(string-trim
(buffer-substring-no-properties
(point-min)
(min (point-max) 1000)))))
(string-trim (buffer-string))))
(user-error "No backtrace buffer detected")))
@ -141,8 +139,9 @@ easy pasting into a bug report or discord."
;; Vanilla sandbox
;;
(defun doom--run-vanilla-sandbox ()
"TODO"
(defvar doom--sandbox-init-doom-p nil)
(defun doom--run-vanilla-sandbox (&optional load-doom-p)
(interactive)
(let ((contents (buffer-string))
(file (make-temp-file "/tmp/doom-eval-")))
@ -150,31 +149,43 @@ easy pasting into a bug report or discord."
(require 'pp)
(require 'restart-emacs)
(restart-emacs--launch-other-emacs
(list "-Q"
"--eval"
(prin1-to-string
`(setq user-emacs-directory ,doom-emacs-dir
package--init-file-ensured t
package-user-dir ,package-user-dir
package-archives ',package-archives
debug-on-error t))
"-f" "package-initialize"
"--eval" (prin1-to-string `(unwind-protect (load ,file) (delete-file ,file)))))))
(append (list "-Q")
(if load-doom-p
(list "--eval"
(prin1-to-string
`(setq doom-private-dir "/tmp/does/not/exist"
doom-modules ,doom-modules))
"-l" (shell-quote-argument user-init-file))
(list "--eval"
(prin1-to-string
`(setq user-emacs-directory ,doom-emacs-dir
package--init-file-ensured t
package-user-dir ,package-user-dir
package-archives ',package-archives))))
(list "--eval"
(prin1-to-string
`(unwind-protect (load ,file)
(delete-file ,file))))))))
(defun doom--run-vanilla-doom-sandbox ()
(interactive)
(doom--run-vanilla-sandbox t))
;;;###autoload
(defun doom/open-vanilla-sandbox ()
"Open an Emacs Lisp buffer destinated to run in a blank Emacs session.
"Open an Emacs Lisp buffer destinated to run in a blank Emacs session (and
optionally load only Doom and its modules, without your private config).
This vanilla sandbox is started with emacs -Q, and provides a testbed for
debugging code without Doom standing in the way, and without sacrificing
access to the installed packages."
This provides a testbed for debugging code without Doom (or your private config)
standing in the way, and without sacrificing access to installed packages."
(interactive)
(let ((buf (get-buffer-create "*doom:vanilla-sandbox*")))
(with-current-buffer buf
(emacs-lisp-mode)
(local-set-key (kbd "C-c C-c") #'doom--run-vanilla-sandbox)
(local-set-key (kbd "C-c C-d") #'doom--run-vanilla-doom-sandbox)
(local-set-key (kbd "C-c C-k") #'kill-this-buffer)
(setq header-line-format "C-c C-c to run the session / C-c C-k to abort it")
(setq header-line-format "C-c C-c to run the session / C-c C-d to run it with vanilla Doom loaded / C-c C-k to abort it")
(setq-local default-directory doom-emacs-dir)
(doom-template-insert "VANILLA_SANDBOX")
(goto-char (point-max)))
@ -280,19 +291,26 @@ If INIT-FILE is non-nil, profile that instead of USER-INIT-FILE."
(setq esup-server-process (esup-server-create (esup-select-port)))
(setq esup-server-port (process-contact esup-server-process :service))
(message "esup process started on port %s" esup-server-port)
(let ((process-args `("*esup-child*"
"*esup-child*"
,esup-emacs-path
"-q"
"-L" ,esup-load-path
"-l" "esup-child"
,(format "--eval=(esup-child-run \"%s\" \"%s\" %d)"
init-file
esup-server-port
esup-depth)
"--eval=(doom|run-all-startup-hooks)")))
(let ((process-args
(append `("*esup-child*"
"*esup-child*"
,esup-emacs-path
"-Q"
"--eval=(setq after-init-time nil)"
"-L" ,esup-load-path)
(when (bound-and-true-p early-init-file)
`("-l" ,early-init-file))
`("-l" "esup-child"
,(format "--eval=(let ((load-file-name \"%s\")) (esup-child-run \"%s\" \"%s\" %d))"
init-file
init-file
esup-server-port
esup-depth)
"--eval=(doom|run-all-startup-hooks)"))))
(when esup-run-as-batch-p
(setq process-args (append process-args '("--batch"))))
(setq esup-child-process (apply #'start-process process-args)))
(set-process-sentinel esup-child-process 'esup-child-process-sentinel)))
;;;###autoload
(advice-add #'esup :override #'doom/profile-emacs)

View file

@ -28,7 +28,7 @@ they are absolute."
;;
;;;###autoload
(defun doom//reload-project ()
(defun doom/reload-project ()
"Reload the project root cache."
(interactive)
(projectile-invalidate-cache nil)

View file

@ -103,3 +103,24 @@ presentations."
(mapc #'disable-theme custom-enabled-themes))
(doom|init-theme)
(doom|init-fonts)))
;;;###autoload
(defun doom/switch-theme (theme)
"Like `load-theme', but will unload currently loaded themes before switching
to a new one."
(interactive
(list (completing-read
"Load theme: "
(mapcar #'symbol-name
(custom-available-themes)))))
(condition-case nil
(progn
(mapc #'disable-theme custom-enabled-themes)
(load-theme (intern theme) t)
(when (fboundp 'powerline-reset)
(powerline-reset)))
(error "Problem loading theme %s" x)))
;;;###autoload
(defun doom*recenter (&rest _)
(recenter))

View file

@ -190,6 +190,20 @@ recompile. Run this whenever you:
3. Add or remove autoloaded functions in module autoloaded files.
4. Update Doom outside of Doom (e.g. with git)")
(dispatcher! (patch-macos) (doom-patch-macos args)
"Patches Emacs.app to respect your shell environment.
This searches for Emacs.app in /Applications and ~/Applications, then moves
Contents/MacOS/Emacs to Contents/MacOS/RunEmacs, and replaces the former with
the following wrapper script:
#!/usr/bin/env bash
args=\"$@\"
pwd=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\"; pwd -P)\"
exec \"$SHELL\" -c \"$pwd/RunEmacs $args\"
This ensures that Emacs is always aware of your shell environment.")
;;
;; Quality of Life Commands
@ -281,12 +295,14 @@ problems with doom."
This deploys a barebones config to `doom-private-dir', installs all missing
packages and regenerates the autoloads file."
;; Create `doom-private-dir'
(let ((short-private-dir (abbreviate-file-name doom-private-dir)))
(if (file-directory-p doom-private-dir)
(print! (yellow "%s directory already exists. Skipping." short-private-dir))
(print! "Creating %s" short-private-dir)
(make-directory doom-private-dir t)
(print! (green "Done!")))
;; Create init.el
(let ((init-file (expand-file-name "init.el" doom-private-dir)))
(if (file-exists-p init-file)
(print! (yellow "%sinit.el already exists. Skipping." short-private-dir))
@ -294,6 +310,7 @@ packages and regenerates the autoloads file."
(copy-file (expand-file-name "init.example.el" doom-emacs-dir)
init-file)
(print! (green "Done!"))))
;; Create config.el
(let ((config-file (expand-file-name "config.el" doom-private-dir)))
(if (file-exists-p config-file)
(print! "%sconfig.el already exists. Skipping." short-private-dir)
@ -309,6 +326,49 @@ packages and regenerates the autoloads file."
(doom-template-insert "QUICKSTART_INTRO")
(print! (buffer-string))))
(defun doom-patch-macos (args)
"Patches Emacs.app to respect your shell environment."
(unless IS-MAC
(user-error "You don't seem to be running MacOS"))
(let ((appdir
(cl-find-if #'file-exists-p
(list "/Applications/Emacs.app"
"~/Applications/Emacs.app"))))
(unless appdir
(user-error "Couldn't find Emacs.app in /Applications or ~/Applications"))
(let ((oldbin (expand-file-name "Contents/MacOS/Emacs" appdir))
(newbin (expand-file-name "Contents/MacOS/RunEmacs" appdir)))
(cond ((or (member "--undo" args)
(member "-u" args))
(unless (file-exists-p newbin)
(user-error "Emacs.app is not patched"))
(copy-file newbin oldbin 'ok-if-already-exists nil nil 'preserve-permissions)
(unless (file-exists-p oldbin)
(error "Failed to copy %s to %s" newbin oldbin))
(delete-file newbin)
(message "%s successfully unpatched" appdir))
((file-exists-p newbin)
(user-error "%s is already patched" appdir))
((or doom-auto-accept
(progn
(print! "/Applications/Emacs.app needs to be patched.")
(print! "\nWhy? So that Emacs will respect your shell configuration when not launched from the shell.")
(print! "\nHow? By replacing Emacs.app/Contents/MacOS/Emacs with a wrapper that launches Emacs from your shell.")
(y-or-n-p "Patch Emacs.app?")))
(copy-file oldbin newbin nil nil nil 'preserve-permissions)
(unless (file-exists-p newbin)
(error "Failed to copy %s to %s" oldbin newbin))
(with-temp-buffer
(insert "#!/usr/bin/env bash\n"
"args=\"$@\"\n"
"pwd=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\"; pwd -P)\"\n"
"exec \"$SHELL\" -c \"$pwd/RunEmacs $args\"")
(write-file oldbin)
(chmod oldbin (file-modes newbin)))
(message "%s successfully patched" appdir))))))
;;
;; Autoload file generation

View file

@ -102,7 +102,10 @@ fundamental-mode) for performance sake."
(defun doom|unpropertize-kill-ring ()
"Remove text properties from `kill-ring' in the interest of shrinking the
savehist file."
(setq kill-ring (mapcar #'substring-no-properties kill-ring)))
(setq kill-ring (cl-loop for item in kill-ring
if (stringp item)
collect (substring-no-properties item)
else if item collect it)))
(add-hook 'kill-emacs-hook #'doom|unpropertize-kill-ring))
;; persistent point location in buffers
@ -143,6 +146,8 @@ savehist file."
:defer 1
:after-call (pre-command-hook after-find-file)
:config
(when-let* ((name (getenv "EMACS_SERVER_NAME")))
(setq server-name name))
(unless (server-running-p)
(server-start)))
@ -257,7 +262,7 @@ savehist file."
command-log-mode-open-log-turns-on-mode t
command-log-mode-is-global t)
;; `expand-region'
(def-package! expand-region
:commands (er/contract-region er/mark-symbol er/mark-word)
:config
@ -268,18 +273,12 @@ savehist file."
(advice-add #'evil-escape :before #'doom*quit-expand-region)
(advice-add #'doom/escape :before #'doom*quit-expand-region))
;; A better *help* buffer
(def-package! helpful
:defer t
:init
(setq counsel-describe-function-function #'helpful-callable
counsel-describe-variable-function #'helpful-variable)
(define-key! 'global
[remap describe-function] #'helpful-callable
[remap describe-command] #'helpful-command
[remap describe-variable] #'helpful-variable
[remap describe-key] #'helpful-key))
;; `helpful' --- a better *help* buffer
(define-key! 'global
[remap describe-function] #'helpful-callable
[remap describe-command] #'helpful-command
[remap describe-variable] #'helpful-variable
[remap describe-key] #'helpful-key)
(provide 'core-editor)
;;; core-editor.el ends here

View file

@ -408,7 +408,8 @@ The available conditions are:
(and (fboundp ',mode)
(not (bound-and-true-p ,mode))
(and buffer-file-name (not (file-remote-p buffer-file-name)))
,(if match `(if buffer-file-name (string-match-p ,match buffer-file-name)) t)
,(or (not match)
`(if buffer-file-name (string-match-p ,match buffer-file-name)))
,(or (not files)
(doom--resolve-path-forms
(if (stringp (car files)) (cons 'and files) files)

View file

@ -40,6 +40,9 @@ non-nil."
(setq doom-init-modules-p t)
(load! "init" doom-private-dir t)
(unless doom-modules
(setq doom-modules (make-hash-table :test #'equal)))
(maphash (lambda (key plist)
(let ((doom--current-module key)
(doom--current-flags (plist-get plist :flags)))

View file

@ -130,8 +130,9 @@ Relevant: `doom-project-hook'."
,on-load
(setq ,init-var t)))
,on-enter))
,(when add-hooks
`(setq ,(intern (format "%s-hook" name)) ',add-hooks))
,@(cl-loop for hook in add-hooks
collect `(add-hook ',(intern (format "%s-hook" name))
#',hook))
,(when (or modes match files when)
`(associate! ,name
:modes ,modes

View file

@ -28,35 +28,6 @@ shorter major mode name in the mode-line. See `doom|set-mode-name'.")
(defvar doom-init-ui-hook nil
"List of hooks to run when the UI has been initialized.")
(defvar doom-load-theme-hook nil
"Hook run when the theme (and font) is initialized (or reloaded
with `doom/reload-theme').")
(defvar doom-before-switch-window-hook nil
"Hook run before `switch-window' or `switch-frame' are called. See
`doom-enter-window-hook'.")
(defvar doom-after-switch-window-hook nil
"Hook run after `switch-window' or `switch-frame' are called. See
`doom-exit-window-hook'.")
(defvar doom-before-switch-buffer-hook nil
"Hook run after `switch-to-buffer', `pop-to-buffer' or `display-buffer' are
called. The buffer to be switched to is current when these hooks run.
Also see `doom-after-switch-buffer-hook'.")
(defvar doom-after-switch-buffer-hook nil
"Hook run before `switch-to-buffer', `pop-to-buffer' or `display-buffer' are
called. The buffer to be switched to is current when these hooks run.
Also see `doom-exit-buffer-hook'.")
(define-obsolete-variable-alias 'doom-after-switch-buffer-hook 'doom-enter-buffer-hook "2.1.0")
(define-obsolete-variable-alias 'doom-before-switch-buffer-hook 'doom-exit-buffer-hook "2.1.0")
(define-obsolete-variable-alias 'doom-after-switch-window-hook 'doom-enter-window-hook "2.1.0")
(define-obsolete-variable-alias 'doom-before-switch-window-hook 'doom-exit-window-hook "2.1.0")
(setq-default
ansi-color-for-comint-mode t
bidi-display-reordering nil ; disable bidirectional text for tiny performance boost
@ -138,27 +109,14 @@ Also see `doom-exit-buffer-hook'.")
(add-hook 'completion-list-mode-hook #'hide-mode-line-mode)
(add-hook 'Man-mode-hook #'hide-mode-line-mode)
;; `highlight-numbers-mode' -- better number literal fontification in code
(setq highlight-numbers-generic-regexp "\\_<[[:digit:]]+.*\\_>")
(add-hook 'prog-mode-hook #'highlight-numbers-mode)
;; `highlight-numbers' -- better number literal fontification in code
(def-package! highlight-numbers
:hook (prog-mode . highlight-numbers-mode)
:config (setq highlight-numbers-generic-regexp "\\_<[[:digit:]]+.*\\_>"))
;; `highlight-escape-sequences'
(def-package! highlight-escape-sequences
:after-call after-find-file
:config
(defconst hes-python-escape-sequence-re
(rx (submatch
(and ?\\ (submatch
(or (repeat 1 3 (in "0-7"))
(and ?x (repeat 2 xdigit))
(and ?u (repeat 4 xdigit))
(and ?U (repeat 8 xdigit))
(and ?N "{" (one-or-more alpha) "}")
(any "\"\'\\abfnrtv")))))))
(add-to-list 'hes-mode-alist `(python-mode . ,hes-python-escape-sequence-re))
(add-to-list 'hes-mode-alist `(enh-ruby-mode . ,hes-ruby-escape-sequence-keywords))
(hes-mode +1))
:hook ((prog-mode conf-mode) . highlight-escape-sequences-mode))
;; `rainbow-delimiters' Helps us distinguish stacked delimiter pairs. Especially
;; in parentheses-drunk languages like Lisp.
@ -289,51 +247,6 @@ from the default."
(add-hook 'after-change-major-mode-hook #'doom|show-whitespace-maybe)
;;
;; Custom hooks
;;
(defvar doom-inhibit-switch-buffer-hooks nil)
(defvar doom-inhibit-switch-window-hooks nil)
(defun doom*switch-window-hooks (orig-fn window &optional norecord)
(if (or doom-inhibit-switch-window-hooks
(null window)
(eq window (selected-window))
(window-minibuffer-p)
(window-minibuffer-p window))
(funcall orig-fn window norecord)
(let ((doom-inhibit-switch-window-hooks t))
(run-hooks 'doom-exit-window-hook)
(prog1 (funcall orig-fn window norecord)
(with-selected-window window
(run-hooks 'doom-enter-window-hook))))))
(defun doom*switch-buffer-hooks (orig-fn buffer-or-name &rest args)
(if (or doom-inhibit-switch-buffer-hooks
(eq (get-buffer buffer-or-name) (current-buffer)))
(apply orig-fn buffer-or-name args)
(let ((doom-inhibit-switch-buffer-hooks t))
(run-hooks 'doom-exit-buffer-hook)
(prog1 (apply orig-fn buffer-or-name args)
(with-current-buffer buffer-or-name
(run-hooks 'doom-enter-buffer-hook))))))
(defun doom|init-custom-hooks (&optional disable)
(dolist (spec '((select-window . doom*switch-window-hooks)
(switch-to-buffer . doom*switch-buffer-hooks)
(display-buffer . doom*switch-buffer-hooks)
(pop-to-buffer . doom*switch-buffer-hooks)))
(if disable
(advice-remove (car spec) (cdr spec))
(advice-add (car spec) :around (cdr spec)))))
(add-hook 'doom-init-ui-hook #'doom|init-custom-hooks)
(defun doom*load-theme-hooks (theme &rest _)
(setq doom-theme theme)
(run-hooks 'doom-load-theme-hook))
(advice-add #'load-theme :after #'doom*load-theme-hooks)
;;
;; Silence motion errors in minibuffer
;;
@ -540,14 +453,18 @@ frame's window-system, the theme will be reloaded.")
(setq frame-title-format '("%b Doom Emacs"))
;; draw me like one of your French editors
(tooltip-mode -1) ; relegate tooltips to echo area only
;; prompts the user for confirmation when deleting a non-empty frame
(define-key global-map [remap delete-frame] #'doom/delete-frame)
;; a good indicator that Emacs isn't frozen
(add-hook 'doom-init-ui-hook #'blink-cursor-mode)
;; line numbers in most modes
(add-hook! (prog-mode text-mode conf-mode) #'doom|enable-line-numbers)
;; More sensibile replacements for default commands
(define-key! 'global
;; prompts the user for confirmation when deleting a non-empty frame
[remap delete-frame] #'doom/delete-frame
;; a more sensible load-theme, that disables previous themes first
[remap load-theme] #'doom/switch-theme)
(defun doom*fix-whitespace-mode-in-childframes (orig-fn &rest args)
(let ((frame (apply orig-fn args)))
(with-selected-frame frame

View file

@ -28,39 +28,39 @@ line or use --debug-init to enable this.")
;;
(defconst doom-emacs-dir
(defvar doom-emacs-dir
(eval-when-compile (file-truename user-emacs-directory))
"The path to this emacs.d directory. Must end in a slash.")
(defconst doom-core-dir (concat doom-emacs-dir "core/")
(defvar doom-core-dir (concat doom-emacs-dir "core/")
"Where essential files are stored.")
(defconst doom-modules-dir (concat doom-emacs-dir "modules/")
(defvar doom-modules-dir (concat doom-emacs-dir "modules/")
"The main directory where Doom modules are stored.")
(defconst doom-local-dir (concat doom-emacs-dir ".local/")
(defvar doom-local-dir (concat doom-emacs-dir ".local/")
"Root directory for local Emacs files. Use this as permanent storage for files
that are safe to share across systems (if this config is symlinked across
several computers).")
(defconst doom-etc-dir (concat doom-local-dir "etc/")
(defvar doom-etc-dir (concat doom-local-dir "etc/")
"Directory for non-volatile storage.
Use this for files that don't change much, like servers binaries, external
dependencies or long-term shared data.")
(defconst doom-cache-dir (concat doom-local-dir "cache/")
(defvar doom-cache-dir (concat doom-local-dir "cache/")
"Directory for volatile storage.
Use this for files that change often, like cache files.")
(defconst doom-packages-dir (concat doom-local-dir "packages/")
(defvar doom-packages-dir (concat doom-local-dir "packages/")
"Where package.el and quelpa plugins (and their caches) are stored.")
(defconst doom-docs-dir (concat doom-emacs-dir "docs/")
(defvar doom-docs-dir (concat doom-emacs-dir "docs/")
"Where the Doom manual is stored.")
(defconst doom-private-dir
(defvar doom-private-dir
(eval-when-compile
(or (getenv "DOOMDIR")
(let ((xdg-path
@ -72,10 +72,10 @@ Use this for files that change often, like cache files.")
"Where your private customizations are placed. Must end in a slash. Respects
XDG directory conventions if ~/.config/doom exists.")
(defconst doom-autoload-file (concat doom-local-dir "autoloads.el")
(defvar doom-autoload-file (concat doom-local-dir "autoloads.el")
"Where `doom-reload-doom-autoloads' will generate its core autoloads file.")
(defconst doom-package-autoload-file (concat doom-local-dir "autoloads.pkg.el")
(defvar doom-package-autoload-file (concat doom-local-dir "autoloads.pkg.el")
"Where `doom-reload-package-autoloads' will generate its package.el autoloads
file.")
@ -97,18 +97,6 @@ Doom was setup, which can cause problems.")
(defvar doom-site-load-path load-path
"The starting load-path, before it is altered by `doom-initialize'.")
(defvar doom-init-hook nil
"Hooks run after all init.el files are loaded, including your private and all
module init.el files, but before their config.el files are loaded.")
(defvar doom-post-init-hook nil
"A list of hooks run when Doom is fully initialized. Fires at the end of
`emacs-startup-hook', as late as possible. Guaranteed to run after everything
else (except for `window-setup-hook').")
(defvar doom-reload-hook nil
"A list of hooks to run when `doom//reload-load-path' is called.")
(defvar doom--last-emacs-file (concat doom-local-dir "emacs-version.el"))
(defvar doom--last-emacs-version nil)
(defvar doom--refreshed-p nil)
@ -236,6 +224,97 @@ original value of `symbol-file'."
(fset #'display-startup-echo-area-message #'ignore)
;;
;; Custom hooks
;;
(defvar doom-init-hook nil
"Hooks run after all init.el files are loaded, including your private and all
module init.el files, but before their config.el files are loaded.")
(defvar doom-post-init-hook nil
"A list of hooks run when Doom is fully initialized. Fires at the end of
`emacs-startup-hook', as late as possible. Guaranteed to run after everything
else (except for `window-setup-hook').")
(defvar doom-reload-hook nil
"A list of hooks to run when `doom//reload-load-path' is called.")
(defvar doom-load-theme-hook nil
"Hook run when the theme (and font) is initialized (or reloaded
with `doom/reload-theme').")
(defvar doom-exit-window-hook nil
"Hook run before `switch-window' or `switch-frame' are called. See
`doom-enter-window-hook'.")
(defvar doom-enter-window-hook nil
"Hook run after `switch-window' or `switch-frame' are called. See
`doom-exit-window-hook'.")
(defvar doom-exit-buffer-hook nil
"Hook run after `switch-to-buffer', `pop-to-buffer' or `display-buffer' are
called. The buffer to be switched to is current when these hooks run.
Also see `doom-enter-buffer-hook'.")
(defvar doom-enter-buffer-hook nil
"Hook run before `switch-to-buffer', `pop-to-buffer' or `display-buffer' are
called. The buffer to be switched to is current when these hooks run.
Also see `doom-exit-buffer-hook'.")
(defvar doom-inhibit-switch-buffer-hooks nil
"Letvar for inhibiting `doom-enter-buffer-hook' and `doom-exit-buffer-hook'.")
(defvar doom-inhibit-switch-window-hooks nil
"Letvar for inhibiting `doom-enter-window-hook' and `doom-exit-window-hook'.")
(defun doom*switch-window-hooks (orig-fn window &optional norecord)
(if (or doom-inhibit-switch-window-hooks
(null window)
(eq window (selected-window))
(window-minibuffer-p)
(window-minibuffer-p window))
(funcall orig-fn window norecord)
(let ((doom-inhibit-switch-window-hooks t))
(run-hooks 'doom-exit-window-hook)
(prog1 (funcall orig-fn window norecord)
(with-selected-window window
(run-hooks 'doom-enter-window-hook))))))
(defun doom*switch-buffer-hooks (orig-fn buffer-or-name &rest args)
(if (or doom-inhibit-switch-buffer-hooks
(eq (get-buffer buffer-or-name) (current-buffer)))
(apply orig-fn buffer-or-name args)
(let ((doom-inhibit-switch-buffer-hooks t))
(run-hooks 'doom-exit-buffer-hook)
(prog1 (apply orig-fn buffer-or-name args)
(when (buffer-live-p (get-buffer buffer-or-name))
(with-current-buffer buffer-or-name
(run-hooks 'doom-enter-buffer-hook)))))))
(defun doom|init-switch-hooks (&optional disable)
"Set up enter/exit hooks for windows and buffers.
See `doom-enter-buffer-hook', `doom-enter-window-hook', `doom-exit-buffer-hook'
and `doom-exit-window-hook'."
(dolist (spec '((select-window . doom*switch-window-hooks)
(switch-to-buffer . doom*switch-buffer-hooks)
(display-buffer . doom*switch-buffer-hooks)
(pop-to-buffer . doom*switch-buffer-hooks)))
(if disable
(advice-remove (car spec) (cdr spec))
(advice-add (car spec) :around (cdr spec)))))
(add-hook 'emacs-startup-hook #'doom|init-switch-hooks)
(defun doom*load-theme-hooks (theme &rest _)
"Set up `doom-load-theme-hook' to run after `load-theme' is called."
(setq doom-theme theme)
(run-hooks 'doom-load-theme-hook))
(advice-add #'load-theme :after #'doom*load-theme-hooks)
;;
;; Bootstrap helpers
;;
@ -300,7 +379,9 @@ If RETURN-P, return the message as a string instead of displaying it."
-q or -Q, for example:
emacs -Q -l init.el -f doom|run-all-startup-hooks"
(dolist (hook (list 'after-init-hook 'delayed-warnings-hook
(run-hook-wrapped 'after-init-hook #'doom-try-run-hook)
(setq after-init-time (current-time))
(dolist (hook (list 'delayed-warnings-hook
'emacs-startup-hook 'term-setup-hook
'window-setup-hook))
(run-hook-wrapped hook #'doom-try-run-hook)))

View file

@ -11,7 +11,8 @@
(package! hide-mode-line)
(package! highlight-indentation)
(package! highlight-numbers)
(package! highlight-escape-sequences)
(package! highlight-escape-sequences
:recipe (:fetcher github :repo "hlissner/highlight-escape-sequences"))
(unless (boundp 'display-line-numbers)
(package! nlinum)
(package! nlinum-hl)

View file

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

View file

@ -58,75 +58,5 @@
(expect (kill-buffer (get-buffer-create "a"))))
(it "shouldn't kill the fallback buffer"
(expect (not (kill-buffer (doom-fallback-buffer))))))
(describe "switch hooks"
:var (before-hook after-hook a b)
(before-each
(setq a (switch-to-buffer (get-buffer-create "a"))
b (get-buffer-create "b"))
(spy-on 'before-hook)
(spy-on 'after-hook)
(doom|init-custom-hooks))
(after-each
(doom|init-custom-hooks 'disable)
(kill-buffer a)
(kill-buffer b))
(describe "switch-buffer"
:var (doom-exit-buffer-hook
doom-enter-buffer-hook)
(before-each
(setq doom-exit-buffer-hook '(before-hook)
doom-enter-buffer-hook '(after-hook)))
(after-each
(setq doom-exit-buffer-hook nil
doom-enter-buffer-hook nil))
(it "should trigger when switching buffers"
(switch-to-buffer b)
(switch-to-buffer a)
(switch-to-buffer b)
(expect 'before-hook :to-have-been-called-times 3)
(expect 'after-hook :to-have-been-called-times 3))
(it "should trigger only once on the same buffer"
(switch-to-buffer b)
(switch-to-buffer b)
(switch-to-buffer a)
(expect 'before-hook :to-have-been-called-times 2)
(expect 'after-hook :to-have-been-called-times 2)))
(describe "switch-window"
:var (doom-exit-window-hook
doom-enter-window-hook
x y)
(before-each
(delete-other-windows)
(setq x (get-buffer-window a)
y (save-selected-window (split-window)))
(with-selected-window y
(switch-to-buffer b))
(select-window x)
(spy-calls-reset 'before-hook)
(spy-calls-reset 'after-hook)
(setq doom-exit-window-hook '(before-hook)
doom-enter-window-hook '(after-hook)))
(it "should trigger when switching windows"
(select-window y)
(select-window x)
(select-window y)
(expect 'before-hook :to-have-been-called-times 3)
(expect 'after-hook :to-have-been-called-times 3))
(it "should trigger only once on the same window"
(select-window y)
(select-window y)
(select-window x)
(expect 'before-hook :to-have-been-called-times 2)
(expect 'after-hook :to-have-been-called-times 2)))))
(expect (not (kill-buffer (doom-fallback-buffer)))))))

View file

@ -1,8 +1,8 @@
;; -*- no-byte-compile: t; -*-
;;; core/test/test-core.el
(xdescribe "core"
(describe "initialize"
(describe "core"
(xdescribe "initialize"
:var (doom-init-p doom-init-modules-p doom-private-dir)
(before-each
(setq doom-init-p nil
@ -41,16 +41,85 @@
(it "does not load autoloads file if forced" )
(it "does not regenerate missing autoloads" )))
(describe "initialize-packages"
(xdescribe "initialize-packages"
(before-each (spy-on 'quelpa-setup-p))
(it "initializes package.el once, unless forced" )
(it "initializes quelpa once, unless forced" )
(it "initializes doom-packages once, unless forced" ))
(describe "initialize-modules"
(xdescribe "initialize-modules"
(it "loads private init.el once, unless forced" ))
(describe "initialize-autoloads"
(xdescribe "initialize-autoloads"
(it "loads autoloads file" )
(it "ignores autoloads file if cleared" )))
(it "ignores autoloads file if cleared" ))
(describe "custom hooks"
(describe "switch hooks"
:var (before-hook after-hook a b)
(before-each
(setq a (switch-to-buffer (get-buffer-create "a"))
b (get-buffer-create "b"))
(spy-on 'before-hook)
(spy-on 'after-hook)
(doom|init-switch-hooks))
(after-each
(doom|init-switch-hooks 'disable)
(kill-buffer a)
(kill-buffer b))
(describe "switch-buffer"
:var (doom-exit-buffer-hook
doom-enter-buffer-hook)
(before-each
(setq doom-exit-buffer-hook '(before-hook)
doom-enter-buffer-hook '(after-hook)))
(after-each
(setq doom-exit-buffer-hook nil
doom-enter-buffer-hook nil))
(it "should trigger when switching buffers"
(switch-to-buffer b)
(switch-to-buffer a)
(switch-to-buffer b)
(expect 'before-hook :to-have-been-called-times 3)
(expect 'after-hook :to-have-been-called-times 3))
(it "should trigger only once on the same buffer"
(switch-to-buffer b)
(switch-to-buffer b)
(switch-to-buffer a)
(expect 'before-hook :to-have-been-called-times 2)
(expect 'after-hook :to-have-been-called-times 2)))
(describe "switch-window"
:var (doom-exit-window-hook
doom-enter-window-hook
x y)
(before-each
(delete-other-windows)
(setq x (get-buffer-window a)
y (save-selected-window (split-window)))
(with-selected-window y
(switch-to-buffer b))
(select-window x)
(spy-calls-reset 'before-hook)
(spy-calls-reset 'after-hook)
(setq doom-exit-window-hook '(before-hook)
doom-enter-window-hook '(after-hook)))
(it "should trigger when switching windows"
(select-window y)
(select-window x)
(select-window y)
(expect 'before-hook :to-have-been-called-times 3)
(expect 'after-hook :to-have-been-called-times 3))
(it "should trigger only once on the same window"
(select-window y)
(select-window y)
(select-window x)
(expect 'before-hook :to-have-been-called-times 2)
(expect 'after-hook :to-have-been-called-times 2))))))

View file

@ -63,20 +63,20 @@
;; Use fancy icons
(setq mu4e-headers-has-child-prefix '("+" . "")
mu4e-headers-empty-parent-prefix '("-" . "")
mu4e-headers-first-child-prefix '("-" . "")
mu4e-headers-duplicate-prefix '("-" . "")
mu4e-headers-default-prefix '("-" . "")
mu4e-headers-draft-mark '("-" . "")
mu4e-headers-flagged-mark '("-" . "")
mu4e-headers-new-mark '("-" . "")
mu4e-headers-passed-mark '("-" . "")
mu4e-headers-replied-mark '("-" . "")
mu4e-headers-seen-mark '("-" . "")
mu4e-headers-trashed-mark '("-" . "")
mu4e-headers-attach-mark '("-" . "")
mu4e-headers-encrypted-mark '("-" . "")
mu4e-headers-signed-mark '("-" . "")
mu4e-headers-unread-mark '("-" . ""))
mu4e-headers-first-child-prefix '("\\" . "")
mu4e-headers-duplicate-prefix '("=" . "")
mu4e-headers-default-prefix '("|" . "")
mu4e-headers-draft-mark '("D" . "")
mu4e-headers-flagged-mark '("F" . "")
mu4e-headers-new-mark '("N" . "")
mu4e-headers-passed-mark '("P" . "")
mu4e-headers-replied-mark '("R" . "")
mu4e-headers-seen-mark '("S" . "")
mu4e-headers-trashed-mark '("T" . "")
mu4e-headers-attach-mark '("a" . "")
mu4e-headers-encrypted-mark '("x" . "")
mu4e-headers-signed-mark '("s" . "")
mu4e-headers-unread-mark '("u" . ""))
;; Add a column to display what email account the email belongs to.
(add-to-list 'mu4e-header-info-custom

View file

@ -19,17 +19,92 @@
#'helm-projectile-find-file)))
;;;###autoload
(defun +helm/persp-buffer-list ()
"A version of `helm-buffers-list', but with its buffer list restricted to the
(defun +helm/workspace-buffer-list ()
"A version of `helm-buffers-list' with its buffer list restricted to the
current workspace."
(interactive)
(with-persp-buffer-list nil (helm-buffers-list)))
(unless (featurep! :feature workspaces)
(user-error "This command requires the :feature workspaces module"))
(with-no-warnings
(with-persp-buffer-list nil (helm-buffers-list))))
;;;###autoload
(defun +helm/workspace-mini ()
"A version of `helm-mini' with its buffer list restricted to the current
workspace."
(interactive)
(unless (featurep! :feature workspaces)
(user-error "This command requires the :feature workspaces module"))
(with-no-warnings
(with-persp-buffer-list nil (helm-mini))))
;;
;; Project search
;;
(defun +helm-ag-search-args (all-files-p recursive-p)
(list (concat "ag " (if IS-WINDOWS "--vimgrep" "--nocolor --nogroup"))
"-S"
(if all-files-p "-z -a")
(unless recursive-p "--depth 1")))
(defun +helm-rg-search-args (all-files-p recursive-p)
(list "rg --no-heading --line-number --color never"
"-S"
(when all-files-p "-z -uu")
(unless recursive-p "--maxdepth 1")))
(defun +helm-pt-search-args (all-files-p recursive-p)
(list "pt --nocolor --nogroup -e"
"-S"
(if all-files-p "-z -a")
(unless recursive-p "--depth 1")))
;;
(defun +helm--grep-source ()
(helm-build-async-source (capitalize (helm-grep-command t))
:header-name (lambda (_name) "Helm Projectile Grep (C-c ? Help)")
:candidates-process #'helm-grep-collect-candidates
:filter-one-by-one #'helm-grep-filter-one-by-one
:candidate-number-limit 9999
:nohighlight t
:keymap helm-grep-map
:history 'helm-grep-history
:action (apply #'helm-make-actions helm-projectile-grep-or-ack-actions)
:persistent-action 'helm-grep-persistent-action
:persistent-help "Jump to line (`C-u' Record in mark ring)"
:requires-pattern 2))
(defun +helm--grep-search (directory query prompt &optional all-files-p recursive-p)
(let* ((default-directory directory)
(helm-ff-default-directory directory)
(helm-grep-in-recurse recursive-p)
(helm-grep-ignored-files
(unless all-files-p
(cl-union (projectile-ignored-files-rel) grep-find-ignored-files)))
(helm-grep-ignored-directories
(unless all-files-p
(cl-union (mapcar 'directory-file-name (projectile-ignored-directories-rel))
grep-find-ignored-directories)))
(helm-grep-default-command
(if (and nil (eq (projectile-project-vcs) 'git))
(format "git --no-pager grep --no-color -n%%c -e %%p %s -- %%f"
(if recursive-p "" "--max-depth 1 "))
(format "grep -si -a%s %%e -n%%cH -e %%p %%f %s"
(if recursive-p " -R" "")
(if recursive-p "." "./*"))))
(helm-grep-default-recurse-command helm-grep-default-command))
(setq helm-source-grep (+helm--grep-source))
(helm :sources 'helm-source-grep
:input query
:prompt prompt
:buffer "*helm grep*"
:default-directory directory
:keymap helm-grep-map
:history 'helm-grep-history
:truncate-lines helm-grep-truncate-lines)))
;;;###autoload
(cl-defun +helm-file-search (engine &key query in all-files (recursive t))
"Conduct a file search using ENGINE, which can be any of: rg, ag, pt, and
@ -52,13 +127,12 @@ order.
(helm-ag--default-directory directory)
(helm-ag--default-target (list directory))
(engine (or engine
(cl-loop for tool in +helm-project-search-engines
if (executable-find (symbol-name tool))
return tool)
(cl-find-if #'executable-find +helm-project-search-engines
:key #'symbol-name)
(and (or (executable-find "grep")
(executable-find "git"))
'grep)
(error "No search engine specified (is ag, rg, pt or git installed?)")))
(user-error "No search engine specified (is ag, rg, pt or git installed?)")))
(query (or query
(when (use-region-p)
(let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning)))
@ -66,144 +140,97 @@ order.
(when (> (abs (- end beg)) 1)
(rxt-quote-pcre (buffer-substring-no-properties beg end)))))
""))
(prompt (format "%s%%s %s"
(prompt (format "[%s %s] "
(symbol-name engine)
(cond ((equal directory default-directory)
"./")
((equal directory project-root)
(cond ((file-equal-p directory project-root)
(projectile-project-name))
(t
(file-relative-name directory project-root)))))
((file-equal-p directory default-directory)
"./")
((file-relative-name directory project-root)))))
(command
(pcase engine
('grep
(let* ((helm-ff-default-directory directory)
(helm-grep-in-recurse recursive)
(helm-grep-ignored-files
(unless all-files
(cl-union (projectile-ignored-files-rel) grep-find-ignored-files)))
(helm-grep-ignored-directories
(unless all-files
(cl-union (mapcar 'directory-file-name (projectile-ignored-directories-rel))
grep-find-ignored-directories)))
(helm-grep-default-command
(if (and nil (eq (projectile-project-vcs) 'git))
(format "git --no-pager grep --no-color -n%%c -e %%p %s -- %%f"
(if recursive "" "--max-depth 1 "))
(format "grep -si -a%s %%e -n%%cH -e %%p %%f %s"
(if recursive " -R" "")
(if recursive "." "./*"))))
(helm-grep-default-recurse-command helm-grep-default-command))
(setq helm-source-grep
(helm-build-async-source (capitalize (helm-grep-command t))
:header-name (lambda (_name) "Helm Projectile Grep (C-c ? Help)")
:candidates-process #'helm-grep-collect-candidates
:filter-one-by-one #'helm-grep-filter-one-by-one
:candidate-number-limit 9999
:nohighlight t
:keymap helm-grep-map
:history 'helm-grep-history
:action (apply #'helm-make-actions helm-projectile-grep-or-ack-actions)
:persistent-action 'helm-grep-persistent-action
:persistent-help "Jump to line (`C-u' Record in mark ring)"
:requires-pattern 2))
(helm :sources 'helm-source-grep
:input query
:prompt prompt
:buffer "*helm grep*"
:default-directory directory
:keymap helm-grep-map
:history 'helm-grep-history
:truncate-lines helm-grep-truncate-lines))
(cl-return t))
(`ag
(list "ag -zS"
(if IS-WINDOWS "--vimgrep" "--nocolor --nogroup")
(when all-files "-a")
(unless recursive "--depth 1")))
(`rg
(list "rg -zS --no-heading --line-number --color never"
(when all-files "-uu")
(unless recursive "--maxdepth 1")))
(`pt
(list "pt -zS --nocolor --nogroup -e"
(when all-files "-a")
(unless recursive "--depth 1")))))
(`ag (+helm-ag-search-args all-files recursive))
(`rg (+helm-rg-search-args all-files recursive))
(`pt (+helm-pt-search-args all-files recursive))
('grep (+helm--grep-search directory query prompt all-files recursive)
(cl-return t))))
(helm-ag-base-command (string-join command " ")))
(if (and (eq engine 'ag)
(equal query ""))
(helm-do-ag directory)
(setq helm-ag--last-query query)
(helm-attrset 'search-this-file nil helm-ag-source)
(helm-attrset 'name (helm-ag--helm-header helm-ag--default-directory) helm-ag-source)
(helm :sources '(helm-ag-source)
:input query
:prompt prompt
:buffer "*helm-ag*"
:keymap helm-ag-map
:history 'helm-ag--helm-history))))
;; TODO Define our own sources instead
(helm-attrset 'name (format "[%s %s] Searching %s"
engine
(string-join (delq nil (cdr command)) " ")
(abbreviate-file-name directory))
helm-source-do-ag)
(cl-letf ((+helm-global-prompt prompt)
((symbol-function 'helm-do-ag--helm)
(lambda () (helm :sources '(helm-source-do-ag)
:buffer "*helm-ag*"
:keymap helm-do-ag-map
:input query
:history 'helm-ag--helm-history))))
(helm-do-ag directory))))
(defun +helm--get-command (format)
(cl-loop for tool in (cl-remove-duplicates +helm-project-search-engines :from-end t)
if (executable-find (symbol-name tool))
return (intern (format format tool))))
;;;###autoload
(defun +helm/project-search (arg)
"Performs a project search using the first available search backend from a
list of: ripgrep, ag, pt, git-grep and grep. If ARG (universal argument),
preform search from current directory."
(defun +helm/project-search (&optional all-files-p)
"Performs a project search from the project root.
Uses the first available search backend from `+helm-project-search-engines'. If
ALL-FILES-P (universal argument), include all files, even hidden or compressed
ones, in the search."
(interactive "P")
(call-interactively
(or (cl-loop for tool in (cl-remove-duplicates +helm-project-search-engines :from-end t)
if (executable-find (symbol-name tool))
return (intern (format "+helm/%s%s" tool (if arg "-from-cwd" ""))))
(if arg
#'+helm/grep-from-cwd
#'+helm/grep))))
(or (+helm--get-command "+helm/%s")
#'+helm/grep)))
;;;###autoload
(defun +helm/project-search-from-cwd (&optional all-files-p)
"Performs a project search recursively from the current directory.
Uses the first available search backend from `+helm-project-search-engines'. If
ALL-FILES-P (universal argument), include all files, even hidden or compressed
ones."
(interactive "P")
(call-interactively
(or (+helm--get-command "+helm/%s-from-cwd")
#'+helm/grep-from-cwd)))
;; Relative to project root
;;;###autoload
(defun +helm/rg (all-files-p &optional query directory)
"TODO"
(interactive "P")
(+helm-file-search 'rg :query query :in directory :all-files all-files-p))
;;;###autoload (autoload '+helm/rg "completion/helm/autoload/helm")
;;;###autoload (autoload '+helm/rg-from-cwd "completion/helm/autoload/helm")
;;;###autoload (autoload '+helm/ag "completion/helm/autoload/helm")
;;;###autoload (autoload '+helm/ag-from-cwd "completion/helm/autoload/helm")
;;;###autoload (autoload '+helm/pt "completion/helm/autoload/helm")
;;;###autoload (autoload '+helm/pt-from-cwd "completion/helm/autoload/helm")
;;;###autoload (autoload '+helm/grep "completion/helm/autoload/helm")
;;;###autoload (autoload '+helm/grep-from-cwd "completion/helm/autoload/helm")
;;;###autoload
(defun +helm/ag (all-files-p &optional query directory)
"TODO"
(interactive "P")
(+helm-file-search 'ag :query query :in directory :all-files all-files-p))
(dolist (engine (cl-remove-duplicates +helm-project-search-engines :from-end t))
(defalias (intern (format "+helm/%s" engine))
(lambda (all-files-p &optional query directory)
(interactive "P")
(+helm-file-search engine :query query :in directory :all-files all-files-p))
(format "Perform a project file search using %s.
;;;###autoload
(defun +helm/pt (all-files-p &optional query directory)
"TODO"
(interactive "P")
(+helm-file-search 'pt :query query :in directory :all-files all-files-p))
QUERY is a regexp. If omitted, the current selection is used. If no selection is
active, the last known search is used.
;;;###autoload
(defun +helm/grep (all-files-p &optional query directory)
"TODO"
(interactive "P")
(+helm-file-search 'grep :query query :in directory :all-files all-files-p))
If ALL-FILES-P, search compressed and hidden files as well."
engine))
;; Relative to current directory
;;;###autoload
(defun +helm/rg-from-cwd (recurse-p &optional query)
"TODO"
(interactive "P")
(+helm-file-search 'rg :query query :in default-directory :recursive recurse-p))
(defalias (intern (format "+helm/%s-from-cwd" engine))
(lambda (all-files-p &optional query directory)
(interactive "P")
(+helm-file-search engine :query query :in default-directory :all-files all-files-p))
(format "Perform a project file search from the current directory using %s.
;;;###autoload
(defun +helm/ag-from-cwd (recurse-p &optional query)
"TODO"
(interactive "P")
(+helm-file-search 'ag :query query :in default-directory :recursive recurse-p))
;;;###autoload
(defun +helm/pt-from-cwd (recurse-p &optional query)
"TODO"
(interactive "P")
(+helm-file-search 'pt :query query :in default-directory :recursive recurse-p))
;;;###autoload
(defun +helm/grep-from-cwd (recurse-p &optional query)
"TODO"
(interactive "P")
(+helm-file-search 'grep :query query :in default-directory :recursive recurse-p))
QUERY is a regexp. If omitted, the current selection is used. If no selection is
active, the last known search is used.
If ALL-FILES-P, search compressed and hidden files as well."
engine)))

View file

@ -16,17 +16,40 @@ bottom, which is easier on the eyes on big displays."
;;;###autoload
(defun +helm-posframe-display (buffer &optional _resume)
"TODO"
(require 'posframe)
(setq helm--buffer-in-new-frame-p t)
(posframe-show
(setq +helm--posframe-buffer buffer)
:position (point)
:poshandler +helm-posframe-handler
:override-parameters +helm-posframe-parameters)
(unless (or (null +helm-posframe-text-scale)
(= +helm-posframe-text-scale 0))
(with-current-buffer buffer
(text-scale-set +helm-posframe-text-scale))))
(let ((solaire-p (bound-and-true-p solaire-mode))
(params (copy-sequence +helm-posframe-parameters)))
(let-alist params
(require 'posframe)
(posframe-show
(setq +helm--posframe-buffer buffer)
:position (point)
:poshandler +helm-posframe-handler
:width
(max (cl-typecase .width
(integer .width)
(float (truncate (* (frame-width) .width)))
(function (funcall .width))
(t 0))
.min-width)
:height
(max (cl-typecase .height
(integer .height)
(float (truncate (* (frame-height) .height)))
(function (funcall .height))
(t 0))
.min-height)
:override-parameters
(dolist (p '(width height min-width min-height) params)
(setq params (delq (assq p params) params)))))
;;
(unless (or (null +helm-posframe-text-scale)
(= +helm-posframe-text-scale 0))
(with-current-buffer buffer
(when (and (featurep 'solaire-mode)
(not solaire-p))
(solaire-mode +1))
(text-scale-set +helm-posframe-text-scale)))))
;;;###autoload
(defun +helm|posframe-cleanup ()

View file

@ -26,10 +26,10 @@ be negative.")
(defvar +helm-posframe-parameters
'((internal-border-width . 8)
(min-width . 80)
(min-height . 16)
(width . 0.5)
(height . 0.55))
(height . 0.35)
(min-width . 80)
(min-height . 16))
"TODO")
@ -49,7 +49,7 @@ be negative.")
[remap imenu-anywhere] #'helm-imenu-anywhere
[remap imenu] #'helm-semantic-or-imenu
[remap noop-show-kill-ring] #'helm-show-kill-ring
[remap persp-switch-to-buffer] #'+helm/persp-buffer-list
[remap persp-switch-to-buffer] #'+helm/workspace-mini
[remap switch-to-buffer] #'helm-buffers-list
[remap projectile-find-file] #'+helm/projectile-find-file
[remap projectile-recentf] #'helm-projectile-recentf
@ -81,8 +81,7 @@ be negative.")
helm-imenu-execute-action-at-once-if-one nil)
(when (and EMACS26+ (featurep! +childframe))
(setq helm-display-function #'+helm-posframe-display
helm-echo-input-in-header-line t)
(setq helm-display-function #'+helm-posframe-display)
;; Fix "Specified window is not displaying the current buffer" error
(advice-add #'posframe--get-font-height :around #'+helm*fix-get-font-height))
@ -90,6 +89,7 @@ be negative.")
(setq helm-mode-fuzzy-match fuzzy
helm-completion-in-region-fuzzy-match fuzzy
helm-M-x-fuzzy-match fuzzy
helm-ag-fuzzy-match fuzzy
helm-apropos-fuzzy-match fuzzy
helm-bookmark-show-location fuzzy
helm-buffers-fuzzy-matching fuzzy
@ -105,6 +105,8 @@ be negative.")
helm-semantic-fuzzy-match fuzzy))
:config
(set-popup-rule! "^\\*helm" :vslot -100 :size 0.22)
(defun +helm*replace-prompt (plist)
"Globally replace helm prompts with `+helm-global-prompt'."
(cond ((not +helm-global-prompt) plist)
@ -114,10 +116,14 @@ be negative.")
plist)))
(advice-add #'helm :filter-args #'+helm*replace-prompt)
(defun +helm*hide-mode-line (&rest _)
(unless helm-mode-line-string
(hide-mode-line-mode +1)))
(advice-add #'helm-display-mode-line :override #'+helm*hide-mode-line)
;; Hide the modeline
(defun +helm|hide-mode-line (&rest _)
(with-current-buffer (helm-buffer-get)
(unless helm-mode-line-string
(hide-mode-line-mode +1))))
(add-hook 'helm-after-initialize-hook #'+helm|hide-mode-line)
(advice-add #'helm-display-mode-line :override #'+helm|hide-mode-line)
(advice-add #'helm-ag-show-status-default-mode-line :override #'ignore)
(defun +helm*hide-minibuffer-maybe ()
"Hide minibuffer in Helm session if we use the header line as input field."
@ -151,7 +157,9 @@ be negative.")
(after! helm-ag
(map! :map helm-ag-edit-map :n "RET" #'compile-goto-error)
(define-key helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort)
(set-popup-rule! "^\\*helm-ag-edit" :size 0.35 :ttl 0 :quit nil))
(set-popup-rule! "^\\*helm-ag-edit" :size 0.35 :ttl 0 :quit nil)
;; Recenter after jumping to match
(advice-add #'helm-ag--find-file-action :after-while #'doom*recenter))
;; `helm-bookmark'

View file

@ -224,14 +224,10 @@ The point of this is to avoid Emacs locking up indexing massive file trees."
#'counsel-find-file)
((doom-project-p 'nocache)
#'projectile-find-file)
;; FIXME When counsel-projectile-find-file is fixed upstream
;; ((doom-project-p 'nocache)
;; (let ((files (projectile-current-project-files)))
;; (if (<= (length files) ivy-sort-max-size)
;; #'counsel-projectile-find-file
;; #'projectile-find-file)))
(let ((files (projectile-current-project-files)))
(if (<= (length files) ivy-sort-max-size)
#'counsel-projectile-find-file
#'projectile-find-file)))
(#'counsel-file-jump))))
@ -307,87 +303,67 @@ order.
(counsel-pt query)))
(_ (error "No search engine specified"))))))
(defun +ivy--get-command (format)
(cl-loop for tool in (cl-remove-duplicates +ivy-project-search-engines :from-end t)
if (executable-find (symbol-name tool))
return (intern (format format tool))))
;;;###autoload
(defun +ivy/project-search (arg)
"Performs a project search using the first available search backend from a
list of: ripgrep, ag, pt, git-grep and grep. If ARG (universal argument),
preform search from current directory."
(defun +ivy/project-search (&optional all-files-p)
"Performs a project search from the project root.
Uses the first available search backend from `+ivy-project-search-engines'. If
ALL-FILES-P (universal argument), include all files, even hidden or compressed
ones, in the search."
(interactive "P")
(call-interactively
(or (cl-loop for tool in (cl-remove-duplicates +ivy-project-search-engines :from-end t)
if (executable-find (symbol-name tool))
return (intern (format "+ivy/%s%s" tool (if arg "-from-cwd" ""))))
(if arg
#'+ivy/grep-from-cwd
#'+ivy/grep))))
(or (+ivy--get-command "+ivy/%s")
#'+ivy/grep)))
;;;###autoload
(defun +ivy/rg (all-files-p &optional query directory)
"Perform a project file search using ripgrep. QUERY is a regexp. If omitted,
the current selection is used. If no selection is active, the last known search
is used.
(defun +ivy/project-search-from-cwd (&optional all-files-p)
"Performs a project search recursively from the current directory.
If ALL-FILES-P, don't respect .gitignore files and search everything.
NOTE: ripgrep doesn't support multiline searches (yet)."
Uses the first available search backend from `+ivy-project-search-engines'. If
ALL-FILES-P (universal argument), include all files, even hidden or compressed
ones."
(interactive "P")
(+ivy-file-search 'rg :query query :in directory :all-files all-files-p))
(call-interactively
(or (+ivy--get-command "+ivy/%s-from-cwd")
#'+ivy/grep-from-cwd)))
;;;###autoload
(defun +ivy/ag (all-files-p &optional query directory)
"Perform a project file search using the silver searcher. QUERY is a pcre
regexp. If omitted, the current selection is used. If no selection is active,
the last known search is used.
If ALL-FILES-P, don't respect .gitignore files and search everything."
(interactive "P")
(+ivy-file-search 'ag :query query :in directory :all-files all-files-p))
;; Relative to project root
;;;###autoload (autoload '+ivy/rg "completion/ivy/autoload/ivy")
;;;###autoload (autoload '+ivy/rg-from-cwd "completion/ivy/autoload/ivy")
;;;###autoload (autoload '+ivy/ag "completion/ivy/autoload/ivy")
;;;###autoload (autoload '+ivy/ag-from-cwd "completion/ivy/autoload/ivy")
;;;###autoload (autoload '+ivy/pt "completion/ivy/autoload/ivy")
;;;###autoload (autoload '+ivy/pt-from-cwd "completion/ivy/autoload/ivy")
;;;###autoload (autoload '+ivy/grep "completion/ivy/autoload/ivy")
;;;###autoload (autoload '+ivy/grep-from-cwd "completion/ivy/autoload/ivy")
;;;###autoload
(defun +ivy/pt (all-files-p &optional query directory)
"Perform a project file search using the platinum searcher. QUERY is a grep
regexp. If omitted, the current selection is used. If no selection is active,
the last known search is used.
(dolist (engine (cl-remove-duplicates +ivy-project-search-engines :from-end t))
(defalias (intern (format "+ivy/%s" engine))
(lambda (all-files-p &optional query directory)
(interactive "P")
(+ivy-file-search engine :query query :in directory :all-files all-files-p))
(format "Perform a project file search using %s.
If ALL-FILES-P, don't respect .gitignore files and search everything."
(interactive "P")
(+ivy-file-search 'pt :query query :in directory :all-files all-files-p))
;;;###autoload
(defun +ivy/grep (all-files-p &optional query directory)
"Perform a project file search using grep (or git-grep in git repos). QUERY is
a grep regexp. If omitted, the current selection is used. If no selection is
QUERY is a regexp. If omitted, the current selection is used. If no selection is
active, the last known search is used.
If ALL-FILES-P, don't respect .gitignore files and search everything."
(interactive "P")
(+ivy-file-search 'grep :query query :in directory :all-files all-files-p))
If ALL-FILES-P, search compressed and hidden files as well."
engine))
;; Relative to current directory
;;;###autoload
(defun +ivy/rg-from-cwd (recursive-p &optional query)
"Like `+ivy/rg', but from the current directory (recursively if RECURSIVE-P is
non-nil)."
(interactive "P")
(+ivy-file-search 'rg :query query :in default-directory :recursive recursive-p))
(defalias (intern (format "+ivy/%s-from-cwd" engine))
(lambda (all-files-p &optional query directory)
(interactive "P")
(+ivy-file-search engine :query query :in default-directory :all-files all-files-p))
(format "Perform a project file search from the current directory using %s.
;;;###autoload
(defun +ivy/ag-from-cwd (recursive-p &optional query)
"Like `+ivy/ag', but from the current directory (recursively if RECURSIVE-P is
non-nil)."
(interactive "P")
(+ivy-file-search 'ag :query query :in default-directory :recursive recursive-p))
QUERY is a regexp. If omitted, the current selection is used. If no selection is
active, the last known search is used.
;;;###autoload
(defun +ivy/pt-from-cwd (recursive-p &optional query)
"Like `+ivy/pt', but from the current directory (recursively if RECURSIVE-P is
non-nil)."
(interactive "P")
(+ivy-file-search 'pt :query query :in default-directory :recursive recursive-p))
;;;###autoload
(defun +ivy/grep-from-cwd (recursive-p &optional query)
"Like `+ivy/grep', but from the current directory (recursively if RECURSIVE-P is
non-nil)."
(interactive "P")
(+ivy-file-search 'grep :query query :in default-directory :recursive recursive-p))
If ALL-FILES-P, search compressed and hidden files as well."
engine)))

View file

@ -103,6 +103,8 @@ immediately runs it on the current candidate (ending the ivy session)."
(set-popup-rule! "^\\*ivy-occur" :size 0.35 :ttl 0 :quit nil)
(setq counsel-find-file-ignore-regexp "\\(?:^[#.]\\)\\|\\(?:[#~]$\\)\\|\\(?:^Icon?\\)"
counsel-describe-function-function #'helpful-callable
counsel-describe-variable-function #'helpful-variable
;; Add smart-casing and compressed archive searching (-zS) to default
;; command arguments:
counsel-rg-base-command "rg -zS --no-heading --line-number --color never %s ."
@ -149,6 +151,7 @@ immediately runs it on the current candidate (ending the ivy session)."
(def-package! counsel-projectile
:disabled t
:commands (counsel-projectile-find-file counsel-projectile-find-dir counsel-projectile-switch-to-buffer
counsel-projectile-grep counsel-projectile-ag counsel-projectile-switch-project)
:init
@ -199,7 +202,7 @@ immediately runs it on the current candidate (ending the ivy session)."
(setf (alist-get t ivy-display-functions-alist) #'+ivy-display-at-frame-center-near-bottom)
;; posframe doesn't work well with async sources
(dolist (fn '(swiper counsel-rg counsel-ag counsel-pt counsel-grep counsel-git-grep))
(dolist (fn '(swiper counsel-ag counsel-grep counsel-git-grep))
(setf (alist-get fn ivy-display-functions-alist) #'ivy-display-function-fallback)))

View file

@ -481,7 +481,10 @@
:desc "Find file in project" :n "SPC" #'projectile-find-file
:desc "Browse files" :n "." #'find-file
:desc "Toggle last popup" :n "~" #'+popup/toggle
:desc "Eval expression" :n "`" #'eval-expression
(:when (featurep! :completion ivy)
:desc "Resume last search" :n "'" #'ivy-resume)
(:when (featurep! :completion helm)
:desc "Resume last search" :n "'" #'helm-resume)
:desc "Blink cursor line" :n "DEL" #'+nav-flash/blink-cursor
:desc "Jump to bookmark" :n "RET" #'bookmark-jump
@ -520,11 +523,11 @@
(:when (featurep! :completion ivy)
:desc "Buffer" :nv "b" #'swiper
:desc "Project" :nv "p" #'+ivy/project-search
:desc "Directory" :nv "d" (λ! (+ivy/project-search t)))
:desc "Directory" :nv "d" #'+ivy/project-search-from-cwd)
(:when (featurep! :completion helm)
:desc "Buffer" :nv "b" #'swiper-helm
:desc "Project" :nv "p" #'+helm/project-search
:desc "Directory" :nv "d" (λ! (+helm/project-search t)))
:desc "Directory" :nv "d" #'+helm/project-search-from-cwd)
:desc "Symbols" :nv "i" #'imenu
:desc "Symbols across buffers" :nv "I" #'imenu-anywhere
:desc "Online providers" :nv "o" #'+lookup/online-select)
@ -557,8 +560,11 @@
(:desc "buffer" :prefix "b"
:desc "New empty buffer" :n "n" #'evil-buffer-new
:desc "Switch workspace buffer" :n "b" #'persp-switch-to-buffer
:desc "Switch buffer" :n "B" #'switch-to-buffer
(:when (featurep! :feature workspaces)
:desc "Switch workspace buffer" :n "b" #'persp-switch-to-buffer
:desc "Switch buffer" :n "B" #'switch-to-buffer)
(:unless (featurep! :feature workspaces)
:desc "Switch buffer" :n "b" #'switch-to-buffer)
:desc "Kill buffer" :n "k" #'kill-this-buffer
:desc "Kill other buffers" :n "o" #'doom/kill-other-buffers
:desc "Save buffer" :n "s" #'save-buffer
@ -663,7 +669,7 @@
:desc "Org capture" :n "x" #'org-capture)
(:desc "open" :prefix "o"
:desc "Org agenda" :n "a" #'org-agenda-list
:desc "Org agenda" :n "a" #'org-agenda
:desc "Default browser" :n "b" #'browse-url-of-file
:desc "Debugger" :n "d" #'+debug/open
:desc "REPL" :n "r" #'+eval/open-repl

View file

@ -10,8 +10,13 @@
;;;###autodef
(defun set-repl-handler! (modes command)
"Define a REPL for MODES. MODES is either a single major mode symbol or a list
of them. COMMAND is a function that creates and returns the REPL buffer."
"Defines a REPL for MODES.
MODES is either a single major mode symbol or a list of them. COMMAND is a
function that creates and returns the REPL buffer.
COMMAND can either be a function that takes no arguments, or an interactive
command that will be called interactively."
(dolist (mode (doom-enlist modes))
(setf (alist-get mode +eval-repls) command)))

View file

@ -1,14 +1,11 @@
;;; feature/evil/+everywhere.el -*- lexical-binding: t; -*-
;; Here we *truly* lazy-load evil-collection's modules by ensuring its modules
;; do not load at startup (some of them, like buff-menu, help or elisp-mode are
;; loaded immediately, causing evil-collection to be pulled in).
;;
;; We load evil-collection ourselves for three reasons:
;; We load evil-collection ourselves for these reasons:
;;
;; 1. To truly lazy load it. Some of its modules, like the elisp-mode and
;; buff-menu ones are loaded immediately, because Emacs loads them
;; immediately.
;; immediately, pulling it all of evil-collection and sometimes other
;; packages.
;; 2. This ensures a predictable load order, versus lazy loading using :defer or
;; :after-call. This means users can use (after! org ...) and be sure that
;; their changes will override evil-collection's.

View file

@ -114,10 +114,13 @@
(advice-add #'evil-window-split :override #'+evil*window-split)
(advice-add #'evil-window-vsplit :override #'+evil*window-vsplit)
;; Ensure jump points are created
(defun +evil*set-jump (&rest _)
(evil-set-jump))
(advice-add #'counsel-git-grep-action :before #'+evil*set-jump)
(defun +evil*set-jump (orig-fn &rest args)
"Set a jump point and ensure ORIG-FN doesn't set any new jump points."
(evil-set-jump)
(let ((evil--jumps-jumping t))
(apply orig-fn args)))
(advice-add #'counsel-git-grep-action :around #'+evil*set-jump)
(advice-add #'helm-ag--find-file-action :around #'+evil*set-jump)
;; --- custom interactive codes -----------
;; These arg types will highlight matches in the current buffer

View file

@ -79,10 +79,10 @@ evil is loaded and enabled)."
(unless yas-minor-mode
(yas-minor-mode-on))
(when (and yas-minor-mode
(yas-expand-snippet
(yas--template-content
(cl-find trigger (yas--all-templates (yas--get-snippet-tables mode))
:key #'yas--template-key :test #'equal)))
(when-let*
((template (cl-find trigger (yas--all-templates (yas--get-snippet-tables mode))
:key #'yas--template-key :test #'equal)))
(yas-expand-snippet (yas--template-content template)))
(and (featurep 'evil) evil-mode)
(and yas--active-field-overlay
(overlay-buffer yas--active-field-overlay)

View file

@ -131,7 +131,9 @@ must be non-read-only, empty, and there must be a rule in
yas-prompt-functions (delq #'yas-dropdown-prompt yas-prompt-functions)
yas-snippet-dirs nil)
;; Exit snippets on ESC from normal mode
(add-hook 'doom-escape-hook #'yas-abort-snippet))
(add-hook 'doom-escape-hook #'yas-abort-snippet)
;;
(yas-reload-all))
(defun +file-templates|init ()

View file

@ -1,8 +1,20 @@
;;; feature/snippets/autoload/snippets.el -*- lexical-binding: t; -*-
;;
;; Commands
;;
;;;###autoload
(defun +snippets-prompt-private (prompt choices &optional fn)
"Prioritize private snippets (in `+snippets-dir') over built-in ones if there
are multiple choices."
(when-let*
((choices
(or (cl-loop for tpl in choices
if (file-in-directory-p (yas--template-get-file tpl)
+snippets-dir)
collect tpl)
choices)))
(if (cdr choices)
(let ((prompt-functions (remq '+snippets-prompt-private yas-prompt-functions)))
(run-hook-with-args-until-success 'prompt-functions prompt choices fn))
(car choices))))
;;;###autoload
(defun +snippets/goto-start-of-field ()

View file

@ -22,11 +22,17 @@
:config
(setq yas-verbosity (if doom-debug-mode 3 0)
yas-also-auto-indent-first-line t
yas-prompt-functions (delq #'yas-dropdown-prompt yas-prompt-functions)
yas-triggers-in-field t) ; Allow nested snippets
;; Allow private snippets in DOOMDIR/snippets
(add-to-list 'yas-snippet-dirs '+snippets-dir nil #'eq)
;; Remove GUI dropdown prompt (prefer ivy/helm)
(delq #'yas-dropdown-prompt yas-prompt-functions)
;; Prioritize private snippets in `+snippets-dir' over built-in ones if there
;; are multiple choices.
(add-to-list 'yas-prompt-functions #'+snippets-prompt-private nil #'eq)
;; Register `def-project-mode!' modes with yasnippet. This enables project
;; specific snippet libraries (e.g. for Laravel, React or Jekyll projects).
(add-hook 'doom-project-hook #'+snippets|enable-project-modes)

View file

@ -13,10 +13,8 @@ Since spellchecking can be slow in some buffers, this can be disabled with:
ispell-extr-args '("--dont-tex-check-comments"))
(after! ispell
(cond ((executable-find "hunspell")
(setq ispell-program-name "hunspell"))
((executable-find "aspell")
(add-to-list 'ispell-extra-args "--sug-mode=ultra"))))
(when (equal (file-name-base ispell-program-name) "aspell")
(add-to-list 'ispell-extra-args "--sug-mode=ultra")))
(def-package! flyspell ; built-in

View file

@ -66,7 +66,7 @@ compilation database is present in the project.")
;; Custom style, based off of linux
(unless (assoc "doom" c-style-alist)
(push '("doom"
(c-basic-offset . ,tab-width)
(c-basic-offset . tab-width)
(c-comment-only-line-offset . 0)
(c-hanging-braces-alist (brace-list-open)
(brace-entry-open)

View file

@ -1,42 +1,39 @@
;;; lang/clojure/config.el -*- lexical-binding: t; -*-
;; `clojure-mode'
(add-hook 'clojure-mode-hook #'rainbow-delimiters-mode)
(after! clojure-mode
(add-hook 'clojure-mode-hook #'rainbow-delimiters-mode)
(def-package! cider
;; NOTE: if you don't have an org directory set (the dir doesn't exist),
;; cider jack in won't work.
:commands (cider-jack-in cider-jack-in-clojurescript)
:hook (clojure-mode . cider-mode)
:init
(set-popup-rule! "^\\*cider-repl" :quit nil :select nil)
(set-repl-handler! 'clojure-mode #'+clojure/repl)
(set-eval-handler! 'clojure-mode #'cider-eval-region)
(set-lookup-handlers! 'clojure-mode
:definition #'cider-browse-ns-find-at-point
:documentation #'cider-browse-ns-doc-at-point)
:config
(setq nrepl-hide-special-buffers t
cider-stacktrace-default-filters '(tooling dup)
cider-prompt-save-file-on-load nil
cider-repl-use-clojure-font-lock t)
(map! :map cider-mode-map
:localleader
:n "'" #'cider-jack-in
:n "\"" #'cider-jack-in-clojurescript
:n "B" #'cider-switch-to-repl-buffer
:n "n" #'cider-repl-set-ns
:n "j" #'cider-find-var
:n "h" #'cider-doc
:n "c" #'cider-repl-clear-buffer
:n "p" #'cider-eval-sexp-at-point))
(def-package! clj-refactor
:after clojure-mode
:config
(map! :map clj-refactor-map
:localleader
:desc "Refactor hydra" :n "." #'hydra-cljr-help-menu/body))
(def-package! cider
;; NOTE: if you don't have an org directory set (the dir doesn't exist), cider
;; jack in won't work.
:commands (cider-jack-in cider-jack-in-clojurescript)
:hook (clojure-mode . cider-mode)
:config
(setq nrepl-hide-special-buffers t
cider-stacktrace-default-filters '(tooling dup)
cider-prompt-save-file-on-load nil
cider-repl-use-clojure-font-lock t)
(set-popup-rule! "^\\*cider-repl" :quit nil :select nil)
(set-repl-handler! 'clojure-mode #'+clojure/repl)
(set-eval-handler! 'clojure-mode #'cider-eval-region)
(set-lookup-handlers! 'clojure-mode
:definition #'cider-browse-ns-find-at-point
:documentation #'cider-browse-ns-doc-at-point)
(map! :map cider-mode-map
:localleader
:n "'" #'cider-jack-in
:n "\"" #'cider-jack-in-clojurescript
:n "B" #'cider-switch-to-repl-buffer
:n "b" #'cider-eval-buffer
:n "n" #'cider-repl-set-ns
:n "j" #'cider-find-var
:n "d" #'cider-doc
:n "c" #'cider-repl-clear-buffer
:n "p" #'cider-eval-sexp-at-point
:n "r" #'cider-eval-region))
(def-package! clj-refactor
:config
(map! :map clj-refactor-map
:localleader
:desc "Refactor hydra" :n "r" #'hydra-cljr-help-menu/body)))

View file

@ -0,0 +1,3 @@
#+TITLE: :lang coq
This module adds [[https://coq.inria.fr][coq]] support, powered by [[https://proofgeneral.github.io][Proof General]], with code completion via [[https://github.com/cpitclaudel/company-coq][company-coq]].

View file

@ -0,0 +1,4 @@
;;; lang/coq/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(add-hook 'coq-mode-hook #'company-coq-mode)

View file

@ -0,0 +1,6 @@
;; -*- no-byte-compile: t; -*-
;;; lang/coq/packages.el
(package! proof-general :recipe (:fetcher github :repo "ProofGeneral/PG" :files ("*")))
(package! company-coq)

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,5 @@
;;; lang/emacs-lisp/config.el -*- lexical-binding: t; -*-
(defvar +emacs-lisp-enable-extra-fontification t
"If non-nil, fontify built-in functions and variables especially (symbols
defined by Emacs, not Doom or packages). This can help make typos stand out.")
;;
;; elisp-mode deferral hack
;;
@ -36,7 +31,9 @@ defined by Emacs, not Doom or packages). This can help make typos stand out.")
(after! elisp-mode
(set-repl-handler! 'emacs-lisp-mode #'+emacs-lisp/repl)
(set-eval-handler! 'emacs-lisp-mode #'+emacs-lisp-eval)
(set-lookup-handlers! 'emacs-lisp-mode :documentation 'info-lookup-symbol)
(set-lookup-handlers! 'emacs-lisp-mode
:definition #'elisp-def
:documentation #'info-lookup-symbol)
(set-docset! 'emacs-lisp-mode "Emacs Lisp")
(set-pretty-symbols! 'emacs-lisp-mode :lambda "lambda")
(set-rotate-patterns! 'emacs-lisp-mode
@ -59,23 +56,44 @@ defined by Emacs, not Doom or packages). This can help make typos stand out.")
;; initialization
+emacs-lisp|init-imenu))
(defvar +emacs-lisp--face nil)
(defun +emacs-lisp-highlight-vars-and-faces (end)
"Match defined variables and functions.
Functions are differentiated into special forms, built-in functions and
library/userland functions"
(catch 'matcher
(while (re-search-forward "\\_<.+?\\_>" end t)
(let ((symbol (intern-soft (match-string-no-properties 0))))
(and (cond ((null symbol) nil)
((eq symbol t) nil)
((special-variable-p symbol)
(setq +emacs-lisp--face 'font-lock-variable-name-face))
((and (fboundp symbol)
(eq (char-before (match-beginning 0)) ?\())
(let ((unaliased (indirect-function symbol t)))
(unless (or (macrop unaliased)
(special-form-p unaliased))
(let (unadvised)
(while (not (eq (setq unadvised (ad-get-orig-definition unaliased))
(setq unaliased (indirect-function unadvised t)))))
unaliased)
(setq +emacs-lisp--face
(if (subrp unaliased)
'font-lock-constant-face
'font-lock-function-name-face))))))
(throw 'matcher t))))
nil))
(eval-when-compile
(byte-compile #'+emacs-lisp-highlight-vars-and-faces))
;; Special fontification for doom
(font-lock-add-keywords
'emacs-lisp-mode
`(;; custom Doom cookies
("^;;;###\\(autodef\\|if\\)[ \n]" (1 font-lock-warning-face t))
;; doom/module functions
("\\(^\\|\\s-\\|,\\)(\\(\\(doom\\|\\+\\)[^) ]+\\|[^) ]+!\\)[) \n]" (2 'font-lock-keyword-face))))
;; Highlight symbols in standard library
(when +emacs-lisp-enable-extra-fontification
(load! "+symbols")
(font-lock-add-keywords
'emacs-lisp-mode
`((,(concat "\\(?:(\\|#'\\)" (regexp-opt +emacs-lisp-function-list t) "\\_>") (1 'font-lock-function-name-face))
(,(concat "\\(?:(\\|#'\\)" (regexp-opt +emacs-lisp-command-list t) "\\_>") (1 'font-lock-function-name-face))
(,(regexp-opt +emacs-lisp-variable-list 'symbols) . font-lock-variable-name-face)
(,(regexp-opt +emacs-lisp-option-list 'symbols) . font-lock-variable-name-face))))
(append `(;; custom Doom cookies
("^;;;###\\(autodef\\|if\\)[ \n]" (1 font-lock-warning-face t))
;; highlight defined, special variables & functions
(+emacs-lisp-highlight-vars-and-faces . +emacs-lisp--face))))
(defun +emacs-lisp|init-imenu ()
"Improve imenu support with better expression regexps and Doom-specific forms."
@ -92,8 +110,7 @@ defined by Emacs, not Doom or packages). This can help make typos stand out.")
("Macros" "^\\s-*(\\(?:cl-\\)?def\\(?:ine-compile-macro\\|macro\\) +\\([^ )\n]+\\)" 1)
("Inline Functions" "\\s-*(\\(?:cl-\\)?defsubst +\\([^ )\n]+\\)" 1)
("Functions" "^\\s-*(\\(?:cl-\\)?def\\(?:un\\|un\\*\\|method\\|generic\\|-memoized!\\) +\\([^ ,)\n]+\\)" 1)
("Variables" "^\\s-*(\\(def\\(?:c\\(?:onst\\(?:ant\\)?\\|ustom\\)\\|ine-symbol-macro\\|parameter\\)\\)\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)" 2)
("Variables" "^\\s-*(defvar\\(?:-local\\)?\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)[[:space:]\n]+[^)]" 1)
("Variables" "^\\s-*(\\(def\\(?:c\\(?:onst\\(?:ant\\)?\\|ustom\\)\\|ine-symbol-macro\\|parameter\\|var\\(?:-local\\)?\\)\\)\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)" 2)
("Types" "^\\s-*(\\(cl-def\\(?:struct\\|type\\)\\|def\\(?:class\\|face\\|group\\|ine-\\(?:condition\\|error\\|widget\\)\\|package\\|struct\\|t\\(?:\\(?:hem\\|yp\\)e\\)\\)\\)\\s-+'?\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)" 2))))
(defun +emacs-lisp|disable-flycheck-maybe ()

View file

@ -5,6 +5,7 @@
(package! highlight-quoted)
(package! macrostep)
(package! overseer)
(package! elisp-def)
(when (featurep! :feature syntax-checker)
(package! flycheck-cask))

View file

@ -1,6 +1,6 @@
;;; lang/ess/config.el -*- lexical-binding: t; -*-
(def-package! ess-site
(def-package! ess-mode
:commands (R stata julia SAS)
:mode (("\\.sp\\'" . S-mode)
("/R/.*\\.q\\'" . R-mode)
@ -30,6 +30,7 @@
("\\.[Jj][Oo][Gg]\\'" . ess-jags-mode)
("\\.[Jj][Mm][Dd]\\'" . ess-jags-mode))
:init
(setq ess-smart-S-assign-key nil)
(unless (featurep! :lang julia)
(add-to-list 'auto-mode-alist '("\\.jl\\'" . ess-julia-mode)))
:config
@ -38,7 +39,6 @@
ess-expression-offset 2
ess-nuke-trailing-whitespace-p t
ess-default-style 'DEFAULT)
(ess-toggle-underscore t)
(set-repl-handler! 'ess-mode #'+ess/r-repl)
(set-lookup-handlers! 'ess-mode :documentation #'ess-display-help-on-object)
(define-key! ess-doc-map
@ -78,8 +78,3 @@
:n "cm" #'ess-noweb-mark-chunk
:n "cp" #'ess-noweb-previous-chunk
:n "cn" #'ess-noweb-next-chunk))
;; `ess-smart-equals-mode'
(add-hook! '(ess-mode-hook inferior-ess-hook)
#'ess-smart-equals-mode)

View file

@ -2,5 +2,4 @@
;;; lang/ess/packages.el
(package! ess)
(package! ess-smart-equals)
(package! ess-R-data-view)

View file

@ -86,19 +86,15 @@ Run this for any buffer you want to skewer."
;;;###autoload
(defun +javascript|add-node-modules-path ()
"Search the current buffer's parent directories for `node_modules/.bin`.
If it's found, then add it to the `exec-path'."
(if-let* ((root (locate-dominating-file
(or (buffer-file-name) default-directory)
"node_modules"))
(path (expand-file-name "node_modules/.bin/" root)))
(progn
(make-local-variable 'exec-path)
(cl-pushnew path exec-path :test #'string=)
(when doom-debug-mode
(message "Added %s to exec-path" path)))
(when doom-debug-mode
(message "node_modules not found in %s" root))))
"Add current project's `node_modules/.bin` to `exec-path', so js tools
prioritize project-local packages over global ones."
(make-local-variable 'exec-path)
(cl-pushnew (expand-file-name "node_modules/.bin/"
(or (locate-dominating-file
(or (buffer-file-name) default-directory)
"node_modules")
(doom-project-root)))
exec-path :test #'string=))
;;;###autoload
(defun +javascript|cleanup-tide-processes ()
@ -124,4 +120,4 @@ If it's found, then add it to the `exec-path'."
(or tide-project-root
(or (locate-dominating-file default-directory "tsconfig.json")
(locate-dominating-file default-directory "jsconfig.json"))
(doom-project-root 'nocache)))
(doom-project-root)))

View file

@ -23,6 +23,9 @@
(`pdf-tools
(when (featurep! :tools pdf)
(add-to-list 'TeX-view-program-selection '(output-pdf "PDF Tools"))
(when IS-MAC
;; PDF Tools isn't in `TeX-view-program-list-builtin' on macs
(add-to-list 'TeX-view-program-list '("PDF Tools" TeX-pdf-tools-sync-view)))
;; Update PDF buffers after successful LaTeX runs
(add-hook 'TeX-after-compilation-finished-function #'TeX-revert-document-buffer))))

View file

@ -1,8 +1,10 @@
;;; lang/nix/config.el -*- lexical-binding: t; -*-
(after! nix-mode
(def-package! nix-mode
:mode "\\.nix\\'"
:config
(set-company-backend! 'nix-mode 'company-nixos-options)
(map! :map nix-mode-map
:localleader
:n "f" #'nix-update-fetch
@ -14,8 +16,11 @@
(:when (featurep! :completion helm)
:n "o" #'helm-nixos-options)))
(def-package! nix-drv-mode
:mode "\\.drv\\'")
(def-package! nix-update
:commands (nix-update-fetch))
:commands nix-update-fetch)
(def-package! nix-repl
:commands (nix-repl-show))
:commands nix-repl-show)

View file

@ -2,7 +2,6 @@
;;; lang/nix/packages.el
(package! nix-mode)
(package! nix-update)
(when (featurep! :completion company)

View file

@ -12,22 +12,19 @@
path too.")
(define-obsolete-variable-alias 'org-export-directory '+org-export-dir "2.1.0")
(def-package! ox-pandoc
:defer t
:config
(add-to-list 'org-export-backends 'pandoc nil #'eq)
(setq org-pandoc-options
'((standalone . t)
(mathjax . t)
(variable . "revealjs-url=https://cdn.jsdelivr.net/npm/reveal.js@3/"))))
;;
(defun +org|init-export ()
(setq org-export-backends '(ascii html latex md)
org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/"))
(when (executable-find "pandoc")
(require 'ox-pandoc))
(when (and (executable-find "pandoc")
(require 'ox-pandoc nil t))
(add-to-list 'org-export-backends 'pandoc nil #'eq)
(setq org-pandoc-options
'((standalone . t)
(mathjax . t)
(variable . "revealjs-url=https://cdn.jsdelivr.net/npm/reveal.js@3/"))))
;; Export to a central location by default or if target isn't in
;; `org-directory'.

View file

@ -11,9 +11,6 @@
(width . 70)
(height . 25)
(transient . t)
(window-system . ,(cond (IS-MAC 'ns)
(IS-LINUX 'x)
(t 'w32)))
,(if IS-LINUX '(display . ":0")))
"TODO")

View file

@ -398,15 +398,16 @@ with `org-cycle')."
(unless (eq this-command 'org-shifttab)
(save-excursion
(org-beginning-of-line)
(when (and (org-at-heading-p)
(or org-cycle-open-archived-trees
(not (member org-archive-tag (org-get-tags))))
(or (not arg)
(outline-invisible-p (line-end-position))))
(outline-toggle-children)
(unless (outline-invisible-p (line-end-position))
(org-cycle-hide-drawers 'subtree))
t))))
(let (invisible-p)
(when (and (org-at-heading-p)
(or org-cycle-open-archived-trees
(not (member org-archive-tag (org-get-tags))))
(or (not arg)
(setq invisible-p (outline-invisible-p (line-end-position)))))
(unless invisible-p
(setq org-cycle-subtree-status 'subtree))
(org-cycle-internal-local)
t)))))
;;;###autoload
(defun +org|remove-occur-highlights ()

View file

@ -2,6 +2,17 @@
(defvar +php-composer-conf (make-hash-table :test 'equal))
;;;###autoload
(defun +php-company-backend (command &optional arg &rest _ignored)
"A delegating company-backend that uses `company-phpactor' if phpactor is
available and installed, or `php-extras-company' otherwise."
(cond ((and (require 'company-phpactor nil t)
(ignore-errors (phpactor-find-executable)))
(company-phpactor command arg))
((and (require 'php-extras nil t)
(file-exists-p (concat php-extras-eldoc-functions-file ".el")))
(php-extras-company command arg))))
;;;###autoload
(defun +php-composer-conf (&optional project-root refresh-p)
"Retrieve the contents of composer.json as an alist. If REFRESH-P is non-nil

View file

@ -1,7 +1,5 @@
;;; lang/php/config.el -*- lexical-binding: t; -*-
(defvar +php--company-backends nil)
(def-package! php-mode
:mode "\\.inc\\'"
:config
@ -12,13 +10,12 @@
(set-repl-handler! 'php-mode #'php-boris)
(set-lookup-handlers! 'php-mode :documentation #'php-search-documentation)
;; ac-php provides custom autocompletion, php-extras provides autocompletion
;; for built-in libraries
(when +php--company-backends
(set-company-backend! 'php-mode +php--company-backends))
;; `+php-company-backend' uses `company-phpactor', `php-extras-company' or
;; `company-dabbrev-code', in that order.
(set-company-backend! 'php-mode '+php-company-backend 'company-dabbrev-code)
;; Use the smallest `sp-max-pair-length' for optimum `smartparens' performance
(setq-hook! 'php-mode-hook sp-max-pair-length 6)
(setq-hook! 'php-mode-hook sp-max-pair-length 5)
(sp-with-modes '(php-mode)
(sp-local-pair "<?" "?>" :post-handlers '(("| " "SPC" "=") ("||\n[i]" "RET") ("[d2]" "p")))
@ -26,34 +23,63 @@
(map! :map php-mode-map
:localleader
(:prefix "r"
:n "cv" #'php-refactor--convert-local-to-instance-variable
:n "u" #'php-refactor--optimize-use
:v "xm" #'php-refactor--extract-method
:n "rv" #'php-refactor--rename-local-variable)
(:prefix "t"
:n "r" #'phpunit-current-project
:n "a" #'phpunit-current-class
:n "s" #'phpunit-current-test)))
:prefix "t"
:n "r" #'phpunit-current-project
:n "a" #'phpunit-current-class
:n "s" #'phpunit-current-test))
(def-package! hack-mode
:when (featurep! +hack)
:mode "\\.hh$")
(def-package! phpactor
:after php-mode
:config
(set-lookup-handlers! 'php-mode
:definition #'phpactor-goto-definition)
;; TODO PR these for phpactor.el?
;; company-phpactor breaks company if executable doesn't exist
(defun +php*company-phpactor-fail-silently (orig-fn &rest args)
(when (phpactor-find-executable)
(apply orig-fn args)))
(advice-add #'company-phpactor :around #'+php*company-phpactor-fail-silently)
;; `phpactor-get-working-dir' throws stringp errors if not in a project.
(defun +php*project-root (&rest _)
(setq phpactor-working-dir
(or phpactor-working-dir
(php-project-get-root-dir)
(doom-project-root))))
(advice-add #'phpactor-get-working-dir :before #'+php*project-root)
(map! :map php-mode-map
:localleader
:prefix "r"
:n "cc" #'phpactor-copy-class
:n "mc" #'phpactor-move-class
:v "oi" #'phpactor-offset-info
:n "t" #'phpactor-transform
:n "ic" #'phpactor-import-class))
(def-package! php-refactor-mode
:hook php-mode)
:hook php-mode
:config
(map! :map php-refactor-mode-map
:localleader
:prefix "r"
:n "cv" #'php-refactor--convert-local-to-instance-variable
:n "u" #'php-refactor--optimize-use
:v "xm" #'php-refactor--extract-method
:n "rv" #'php-refactor--rename-local-variable))
(def-package! php-extras
:after php-mode
:preface (advice-add #'php-extras-company-setup :override #'ignore)
:init (add-to-list '+php--company-backends 'php-extras-company nil #'eq)
:preface
;; We'll set up company support ourselves
(advice-add #'php-extras-company-setup :override #'ignore)
:config
(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"))
(message "Generating PHP eldoc files...")
@ -67,13 +93,9 @@
(message "PHP eldoc updated!")))))
(def-package! company-php
:when (featurep! :completion company)
:commands (ac-php-remake-tags ac-php-remake-tags-all)
:init
(add-to-list '+php--company-backends 'company-ac-php-backend nil #'eq)
(add-hook 'php-mode-hook #'+php|init-ac-php-core-eldoc)
(setq ac-php-tags-path (concat doom-cache-dir "ac-php/")))
(def-package! hack-mode
:when (featurep! +hack)
:mode "\\.hh$")
;;

View file

@ -5,11 +5,9 @@
(package! php-extras :recipe (:fetcher github :repo "arnested/php-extras"))
(package! php-mode)
(package! php-refactor-mode)
(package! phpactor :recipe (:fetcher github :repo "emacs-php/phpactor.el" :files ("*.el")))
(package! phpunit)
(when (featurep! :completion company)
(package! company-php))
(when (featurep! +hack)
(package! hack-mode :recipe (:fetcher github :repo "hhvm/hack-mode")))

View file

@ -130,7 +130,11 @@
(def-package! pipenv
:commands pipenv-project-p
:hook (python-mode . pipenv-mode))
:hook (python-mode . pipenv-mode)
:init (setq pipenv-with-projectile nil)
:config
(advice-add #'pipenv-activate :after-while #'+python|update-version)
(advice-add #'pipenv-deactivate :after-while #'+python|update-version))
(def-package! pyenv-mode
@ -152,7 +156,9 @@
(defun +python-current-pyvenv () pyvenv-virtual-env-name)
(add-hook 'pyvenv-post-activate-hooks #'+python|update-version)
(add-hook 'pyvenv-post-deactivate-hooks #'+python|update-version)
(add-to-list '+python-mode-line-indicator '(pyvenv-virtual-env-name (" venv:" pyvenv-virtual-env-name)) 'append))
(add-to-list '+python-mode-line-indicator
'(pyvenv-virtual-env-name (" venv:" pyvenv-virtual-env-name))
'append))
(def-package! conda
@ -186,6 +192,5 @@
(add-hook 'conda-postactivate-hook #'+python|update-version)
(add-hook 'conda-postdeactivate-hook #'+python|update-version)
(add-to-list '+python-mode-line-indicator
'(conda-env-current-name
(" conda:" conda-env-current-name))
'(conda-env-current-name (" conda:" conda-env-current-name))
'append))

View file

@ -1,15 +1,13 @@
;;; lang/racket/config.el -*- lexical-binding: t; -*-
(def-package! racket-mode
:hook ((racket-mode racket-repl-mode) . racket-unicode-input-method-enable)
:hook (racket-repl-mode . racket-unicode-input-method-enable)
:config
(set-popup-rule! "^\\*Racket REPL" :size 10 :select t)
(set-repl-handler! 'racket-mode #'+racket/repl)
(set-company-backend! 'racket-mode
'(company-abbrev company-dabbrev-code company-dabbrev company-files))
(set-lookup-handlers! 'racket-mode
:definition #'racket-describe
:documentation #'racket-doc)
:definition #'racket-visit-definition
:documentation #'racket-describe)
(set-docset! 'racket-mode "Racket")
(set-pretty-symbols! 'racket-mode
:lambda "lambda"
@ -29,39 +27,31 @@
(map! :map racket-mode-map
:localleader
:n "c" #'racket-run
:n "z" #'racket-repl
:n "C" #'racket-run-and-switch-to-repl
:n "x" #'racket-racket
:n "t" #'racket-test
:n "a" #'racket-align
:n "A" #'racket-unalign
:n "f" #'racket-fold-all-tests
:n "F" #'racket-unfold-all-tests
:n "h" #'racket-doc
:n "i" #'racket-unicode-input-method-enable
:n "l" #'racket-logger
:n "o" #'racket-profile
(:desc "eval" :prefix "s"
:n "d" #'racket-send-definition
:n "l" #'racket-send-last-sexp
:n "r" #'racket-send-region)
(:desc "macro expand" :prefix "e"
:n "p" #'racket-cycle-paren-shapes
:n "r" #'racket-run
:n "R" #'racket-run-and-switch-to-repl
:n "t" #'racket-test
:n "u" #'racket-backward-up-list
:n "y" #'racket-insert-lambda
(:prefix "e"
:n "d" #'racket-expand-definition
:n "l" #'racket-expand-last-sexp
:n "r" #'racket-expand-region
:n "a" #'racket-expand-again)
:n "r" #'racket-open-require-path
:n "TAB" #'indent-for-tab-command
:n "u" #'racket-backward-up-list
:n "[" #'racket-smart-open-bracket
:n ")" #'racket-insert-closing
:n "]" #'racket-insert-closing
:n "}" #'racket-insert-closing
:n "p" #'racket-cycle-paren-shapes
:n "y" #'racket-insert-lambda
:n "d" #'racket-doc
:n "." #'racket-describe
:n "M-." #'racket-visit-definition
:n "C-." #'racket-visit-module
:n "," #'racket-unvisit
:n "f" #'racket-fold-all-tests
:n "F" #'racket-unfold-all-tests
:n "a" #'racket-align
:n "A" #'racket-unalign
:nv ";" #'comment-dwim
:nv "\\" #'indent-region))
(:prefix "g"
:n "d" #'racket-visit-definition
:n "m" #'racket-visit-module
:n "r" #'racket-open-require-path
:n "b" #'racket-unvisit)
(:prefix "s"
:n "d" #'racket-send-definition
:n "l" #'racket-send-last-sexp
:n "r" #'racket-send-region)))

View file

@ -0,0 +1,28 @@
;;; lang/rest/autoload.el -*- lexical-binding: t; -*-
(defun +rest-request-at-point-p (&optional pos)
(save-excursion
(if pos (goto-char pos))
(beginning-of-line)
(and (re-search-forward restclient-method-url-regexp
(line-end-position) t)
(not (nth 4 (syntax-ppss))))))
;;;###autoload
(defun +rest/dwim-at-point ()
"TODO"
(interactive)
(when (+rest-request-at-point-p)
(restclient-http-send-current-stay-in-window)))
;;;###autoload
(defun +rest/fold-all ()
"TODO"
(interactive)
(save-excursion
(goto-char (point-min))
(let ((last (point)))
(while (and (restclient-jump-next)
(not (= last (setq last (point)))))
(unless (overlays-at (line-end-position))
(restclient-toggle-body-visibility))))))

View file

@ -4,12 +4,27 @@
:mode ("\\.http\\'" . restclient-mode)
:config
(set-popup-rule! "^\\*HTTP Response" :size 0.4 :quit 'other)
;; line numbers aren't enabled by default in fundamental-mode-derived modes
(add-hook 'restclient-mode-hook #'doom|enable-line-numbers)
;; Forces underlying SSL verification to prompt for self-signed or invalid
;; certs, rather than silently reject them.
(defun +rest*permit-self-signed-ssl (orig-fn &rest args)
(let (gnutls-verify-error tls-checktrust)
(apply orig-fn args)))
(advice-add #'restclient-http-do :around #'+rest*permit-self-signed-ssl)
(map! :mode restclient-mode
:n [M-return] 'restclient-http-send-current
:n [return] #'+rest/dwim-at-point
:n "za" #'restclient-toggle-body-visibility
:n "zm" #'+rest/fold-all
:n "zr" #'outline-show-all
:localleader
:desc "Execute HTTP request" :n "e" 'restclient-http-send-current
:desc "Execute raw HTTP request" :n "E" 'restclient-http-send-current-raw
:desc "Copy curl command" :n "c" 'restclient-copy-curl-command))
:desc "Execute HTTP request" :n "e" #'restclient-http-send-current
:desc "Execute raw HTTP request" :n "E" #'restclient-http-send-current-raw
:desc "Copy curl command" :n "c" #'restclient-copy-curl-command))
(def-package! company-restclient

View file

@ -78,8 +78,8 @@
(("task" "namespace") () "end")))
(unless (featurep! :feature evil)
(setq rspec-verifiable-mode-keymap (make-sparse-keymap) "TODO")
(setq rspec-mode-keymap (make-sparse-keymap) "TODO"))
(setq rspec-verifiable-mode-keymap (make-sparse-keymap)
rspec-mode-keymap (make-sparse-keymap)))
(defun +ruby*init-appropriate-rspec-mode ()
"TODO"

View file

@ -38,7 +38,11 @@
(cl-loop for pair in (cdr alist)
unless (string-match-p "^[a-z-]" (cdr pair))
collect (cons (car pair)
(string-trim-right (cdr pair) "\\(?:>\\|]\\|}\\)+")))))
;; TODO Replace with `string-trim-right' (Emacs 26+)
(let ((string (cdr pair)))
(if (string-match "\\(?:>\\|]\\|}\\)+\\'" string)
(replace-match "" t t string)
string))))))
(setf (alist-get nil web-mode-engines-auto-pairs) nil))
(map! :map web-mode-map

View file

@ -1,7 +1,7 @@
;;; tools/magit/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +magit-display-buffer-fullscreen (buffer)
(defun +magit-display-buffer (buffer)
"Like `magit-display-buffer-fullframe-status-v1' with two differences:
1. Magit sub-buffers that aren't spawned from a status screen are opened as
@ -11,41 +11,38 @@
(let ((buffer-mode (buffer-local-value 'major-mode buffer)))
(display-buffer
buffer (cond
;; If opened from an eshell window, use the same window.
((derived-mode-p 'eshell-mode)
;; If opened from an eshell window or popup, use the same window.
((or (derived-mode-p 'eshell-mode)
(eq (window-dedicated-p) 'side))
'(display-buffer-same-window))
;; If opened from a magit window from a popup, open the results
;; full screen. We want to see it all.
((eq (window-dedicated-p) 'side)
'(magit--display-buffer-fullframe))
;; From a commit or magit-log buffer, open detail buffers below
;; this one.
;; Open target buffers below the current one (we want previous
;; magit windows to be visible; especially magit-status).
((or (bound-and-true-p git-commit-mode)
(derived-mode-p 'magit-log-mode))
'(display-buffer-below-selected . ((window-height . 0.7))))
;; From a magit buffer, set aside the magit-status window if it
;; exists (we want it always to be visible), then display the
;; target buffer in the current window.
((derived-mode-p 'magit-mode)
(when (eq major-mode 'magit-status-mode)
(display-buffer-in-side-window
(current-buffer) '((side . left)
(window-width . 0.35)
(window-parameters (quit)))))
'(display-buffer-same-window))
;; If the target buffer opening is a commit, revision or diff, we
;; want to see the whole thing.
((or (buffer-local-value 'git-commit-mode buffer)
(memq buffer-mode '(magit-revision-mode magit-diff-mode)))
'(magit--display-buffer-fullframe))
(derived-mode-p 'magit-mode))
(let ((size (cond ((eq buffer-mode 'magit-process-mode) 0.35)
((bound-and-true-p git-commit-mode) 0.7)
(0.9))))
`(display-buffer-below-selected
. ((window-height . ,(truncate (* (window-height) size)))))))
;; log/stash/process buffers, unless opened from a magit-status
;; window, should be opened in popups.
((memq buffer-mode '(magit-process-mode
magit-log-mode
magit-stash-mode))
'(display-buffer-in-side-window))
;; Last resort: plain old fullscreen.
('(magit--display-buffer-fullframe))))))
'(display-buffer-below-selected))
;; Last resort: use current window
('(display-buffer-same-window))))))
;;;###autoload
(defun +magit-display-popup-buffer (buffer &optional alist)
"TODO"
(cond ((eq (window-dedicated-p) 'side)
(if (fboundp '+popup-display-buffer-stacked-side-window)
(+popup-display-buffer-stacked-side-window buffer alist)
(display-buffer-in-side-window buffer alist)))
((derived-mode-p 'magit-mode)
(display-buffer-below-selected buffer alist))
((display-buffer-in-side-window buffer alist))))
;;
@ -56,9 +53,7 @@
(defun +magit/quit (&optional _kill-buffer)
"Clean up magit buffers after quitting `magit-status'."
(interactive)
(let ((buffers (magit-mode-get-buffers)))
(magit-restore-window-configuration)
(mapc #'+magit--kill-buffer buffers)))
(mapc #'+magit--kill-buffer (magit-mode-get-buffers)))
(defun +magit--kill-buffer (buf)
"TODO"

View file

@ -26,8 +26,8 @@ available.")
#'magit-builtin-completing-read)
magit-revision-show-gravatars '("^Author: " . "^Commit: ")
magit-diff-refine-hunk t ; show word-granularity on selected hunk
magit-display-buffer-function #'+magit-display-buffer-fullscreen
magit-popup-display-buffer-action '((display-buffer-in-side-window)))
magit-display-buffer-function #'+magit-display-buffer
magit-popup-display-buffer-action '((+magit-display-popup-buffer)))
(set-popup-rule! "^\\(?:\\*magit\\|magit:\\)" :ignore t)
;; so magit buffers can be switched to
@ -50,6 +50,7 @@ available.")
(def-package! magithub
:after magit
:preface
;; Magithub is not well-behaved, so this needs to be set early
(setq magithub-dir (concat doom-etc-dir "magithub/"))
:init
(setq magithub-clone-default-directory "~/"

View file

@ -12,13 +12,15 @@
dashboard. These functions take no arguments and the dashboard buffer is current
while they run.")
;; (defvar +doom-dashboard-banner-file "e.png"
;; "The path to the image file to be used in on the dashboard. The path is
;; relative to modules/ui/doom-dashboard/banners/. If nil, always use the ASCII
;; banner.")
(defvar +doom-dashboard-banner-file "default.png"
"The path to the image file to be used in on the dashboard. The path is
relative to `+doom-dashboard-banner-dir'. If nil, always use the ASCII banner.")
;; (defvar +doom-dashboard-banner-dir (concat (DIR!) "banners/")
;; "Where to look for `+doom-dashboard-banner-file'.")
(defvar +doom-dashboard-banner-dir (concat (DIR!) "banners/")
"Where to look for `+doom-dashboard-banner-file'.")
(defvar +doom-dashboard-banner-padding '(4 . 4)
"Number of newlines to pad the banner with, above and below, respectively.")
(defvar +doom-dashboard-inhibit-refresh nil
"If non-nil, the doom buffer won't be refreshed.")
@ -47,10 +49,10 @@ Possible values:
persp-save-dir)))
:face (:inherit (font-lock-keyword-face bold))
:action +workspace/load-last-session)
("See agenda for this week"
("Open org-agenda"
:icon (all-the-icons-octicon "calendar" :face 'font-lock-keyword-face)
:when (fboundp 'org-agenda-list)
:action org-agenda-list)
:when (fboundp 'org-agenda)
:action org-agenda)
("Recently opened files"
:icon (all-the-icons-octicon "file-text" :face 'font-lock-keyword-face)
:action recentf-open-files)
@ -88,7 +90,6 @@ PLIST can have the following properties:
;;
(defvar +doom-dashboard--last-cwd nil)
(defvar +doom-dashboard--width 80)
(defvar +doom-dashboard--hoffset 2)
(defvar +doom-dashboard--old-fringe-indicator fringe-indicator-alist)
(defvar +doom-dashboard--pwd-alist ())
@ -235,11 +236,10 @@ whose dimensions may not be fully initialized by the time this is run."
(point)))
(insert (make-string
(max 0 (- (/ (window-height (get-buffer-window)) 2)
(truncate (/ (+ (count-lines (point-min) (point-max))
+doom-dashboard--hoffset)
2))))
?\n)
"\n")))))))
(round (/ (+ (count-lines (point-min) (point-max))
(car +doom-dashboard-banner-padding))
2))))
?\n))))))))
(defun +doom-dashboard|detect-project (&rest _)
"Check for a `last-project-root' parameter in the perspective, and set the
@ -300,7 +300,6 @@ controlled by `+doom-dashboard-pwd-policy'."
(unless (eq major-mode '+doom-dashboard-mode)
(+doom-dashboard-mode))
(erase-buffer)
(insert "\n")
(run-hooks '+doom-dashboard-functions)))
(+doom-dashboard|resize)
(+doom-dashboard|detect-project)
@ -365,22 +364,21 @@ controlled by `+doom-dashboard-pwd-policy'."
"==' _-' E M A C S \\/ `=="
"\\ _-' `-_ /"
" `'' ``'"))
;; TODO Add Doom logo
;; (when (and +doom-dashboard-banner-file (display-graphic-p))
;; (let* ((image (create-image (expand-file-name +doom-dashboard-banner-file
;; +doom-dashboard-banner-dir)
;; 'png nil))
;; (size (image-size image))
;; (margin (+ 1 (/ (- +doom-dashboard--width (car size)) 2))))
;; (setq +doom-dashboard--hoffset (- (cdr size) 2))
;; (add-text-properties
;; point (point) `(display ,image rear-nonsticky (display)))
;; (when (> margin 0)
;; (save-excursion
;; (goto-char point)
;; (insert (make-string (truncate margin) ? )))))
;; (insert "\n\n\n\n"))
))
(when (and (stringp +doom-dashboard-banner-file)
(display-graphic-p)
(file-exists-p! +doom-dashboard-banner-file +doom-dashboard-banner-dir))
(let* ((image (create-image (expand-file-name +doom-dashboard-banner-file
+doom-dashboard-banner-dir)
'png nil))
(size (image-size image nil))
(margin (+ 1 (/ (- +doom-dashboard--width (car size)) 2))))
(add-text-properties
point (point) `(display ,image rear-nonsticky (display)))
(when (> margin 0)
(save-excursion
(goto-char point)
(insert (make-string (truncate margin) ? )))))
(insert (make-string (or (cdr +doom-dashboard-banner-padding) 0) ?\n)))))
(defun doom-dashboard-widget-loaded ()
(insert

View file

@ -16,7 +16,7 @@
(defvar +modeline-width 3
"How wide the mode-line bar should be (only respected in GUI emacs).")
(defvar +modeline-height 21
(defvar +modeline-height 23
"How tall the mode-line should be (only respected in GUI emacs).")
(defvar +modeline-bar-at-end nil
@ -180,26 +180,29 @@ buffers.")
(defvar +modeline-remap-face-cookies nil)
(defun +modeline|focus-all-windows (&rest _)
(dolist (window +modeline-remap-face-cookies)
(with-selected-window (car window)
(face-remap-remove-relative (cdr window)))))
(cl-loop for (buffer . cookie) in +modeline-remap-face-cookies
if (buffer-live-p buffer)
do (with-current-buffer buffer
(face-remap-remove-relative cookie))))
(defun +modeline|unfocus-all-windows (&rest _)
(setq +modeline-remap-face-cookies
(mapcar (lambda (window)
(with-selected-window window
(cons window
(face-remap-add-relative 'mode-line
'mode-line-inactive))))
(window-list))))
(cl-loop for window in (window-list)
for buffer = (window-buffer window)
if (buffer-live-p buffer)
collect
(with-current-buffer buffer
(cons buffer
(face-remap-add-relative 'mode-line
'mode-line-inactive))))))
(add-hook 'focus-in-hook #'+modeline|focus-all-windows)
(add-hook 'focus-out-hook #'+modeline|unfocus-all-windows)
(advice-add #'posframe-hide :after #'+modeline|focus-all-windows)
(advice-add #'posframe-delete :after #'+modeline|focus-all-windows)
(when (featurep! :completion helm)
(add-hook 'helm-before-initialize-hook #'+modeline|unfocus-all-windows)
(add-hook 'helm-cleanup-hook #'+modeline|focus-all-windows)
(advice-add #'posframe-hide :after #'+modeline|focus-all-windows)
(advice-add #'posframe-delete :after #'+modeline|focus-all-windows))
(add-hook 'helm-cleanup-hook #'+modeline|focus-all-windows))
;;

View file

@ -169,9 +169,7 @@ the command buffer."
;; `helm'
(after! helm
(set-popup-rule! "^\\*helm" :ignore t)
(setq helm-default-display-buffer-functions '(+popup-display-buffer-stacked-side-window)
helm-display-buffer-default-height 0.22)
(setq helm-default-display-buffer-functions '(+popup-display-buffer-stacked-side-window))
;; Fix left-over popup window when closing persistent help for `helm-M-x'
(defun +popup*helm-elisp--persistent-help (candidate _fun &optional _name)

View file

@ -3,20 +3,23 @@
;;;###autoload
(defun +treemacs/toggle ()
"Initialize or toggle treemacs.
* If the treemacs window is visible hide it.
* If a treemacs buffer exists, but is not visible show it.
* If no treemacs buffer exists for the current frame create and show it.
* If the workspace is empty additionally ask for the root path of the first
project to add."
* If the workspace is empty, add the current project to it automatically."
(interactive)
(require 'treemacs)
(pcase (treemacs-current-visibility)
(`visible (delete-window (treemacs-get-local-window)))
(`exists (treemacs-select-window))
(`none
(let ((project-root (doom-project-root 'nocache)))
(when project-root
(unless (treemacs--find-project-for-path project-root)
(treemacs-add-project-at (treemacs--canonical-path project-root)
(doom-project-name 'nocache))))
(treemacs--init project-root)))))
(let ((origin-buffer (current-buffer)))
(cl-letf (((symbol-function 'treemacs-workspace->is-empty?)
(symbol-function 'ignore)))
(treemacs--init))
;;
(treemacs-do-add-project-to-workspace
(treemacs--canonical-path (doom-project-root 'nocache))
(doom-project-name 'nocache))
;;
(setq treemacs--ready-to-follow t)
(when (or treemacs-follow-after-init treemacs-follow-mode)
(with-current-buffer origin-buffer
(treemacs--follow)))))