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 #!/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; } ":"; command -v $EMACS >/dev/null || { >&2 echo "Emacs isn't installed"; exit 1; }
":"; VERSION=$($EMACS --version | head -n1) ":"; 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; } ":"; [[ $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 (setq argv nil
noninteractive 'doom) noninteractive 'doom)
(condition-case e (doom-dispatch args) (condition-case e (doom-dispatch args)
(user-error
(signal (car e) (cdr e)))
((debug error) ((debug error)
(message "--------------------------------------------------\n") (message "--------------------------------------------------\n")
(message "There was an unexpected error:") (message "There was an unexpected error:")

View file

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

View file

@ -103,3 +103,24 @@ presentations."
(mapc #'disable-theme custom-enabled-themes)) (mapc #'disable-theme custom-enabled-themes))
(doom|init-theme) (doom|init-theme)
(doom|init-fonts))) (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. 3. Add or remove autoloaded functions in module autoloaded files.
4. Update Doom outside of Doom (e.g. with git)") 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 ;; Quality of Life Commands
@ -281,12 +295,14 @@ problems with doom."
This deploys a barebones config to `doom-private-dir', installs all missing This deploys a barebones config to `doom-private-dir', installs all missing
packages and regenerates the autoloads file." packages and regenerates the autoloads file."
;; Create `doom-private-dir'
(let ((short-private-dir (abbreviate-file-name doom-private-dir))) (let ((short-private-dir (abbreviate-file-name doom-private-dir)))
(if (file-directory-p doom-private-dir) (if (file-directory-p doom-private-dir)
(print! (yellow "%s directory already exists. Skipping." short-private-dir)) (print! (yellow "%s directory already exists. Skipping." short-private-dir))
(print! "Creating %s" short-private-dir) (print! "Creating %s" short-private-dir)
(make-directory doom-private-dir t) (make-directory doom-private-dir t)
(print! (green "Done!"))) (print! (green "Done!")))
;; Create init.el
(let ((init-file (expand-file-name "init.el" doom-private-dir))) (let ((init-file (expand-file-name "init.el" doom-private-dir)))
(if (file-exists-p init-file) (if (file-exists-p init-file)
(print! (yellow "%sinit.el already exists. Skipping." short-private-dir)) (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) (copy-file (expand-file-name "init.example.el" doom-emacs-dir)
init-file) init-file)
(print! (green "Done!")))) (print! (green "Done!"))))
;; Create config.el
(let ((config-file (expand-file-name "config.el" doom-private-dir))) (let ((config-file (expand-file-name "config.el" doom-private-dir)))
(if (file-exists-p config-file) (if (file-exists-p config-file)
(print! "%sconfig.el already exists. Skipping." short-private-dir) (print! "%sconfig.el already exists. Skipping." short-private-dir)
@ -309,6 +326,49 @@ packages and regenerates the autoloads file."
(doom-template-insert "QUICKSTART_INTRO") (doom-template-insert "QUICKSTART_INTRO")
(print! (buffer-string)))) (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 ;; Autoload file generation

View file

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

View file

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

View file

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

View file

@ -130,8 +130,9 @@ Relevant: `doom-project-hook'."
,on-load ,on-load
(setq ,init-var t))) (setq ,init-var t)))
,on-enter)) ,on-enter))
,(when add-hooks ,@(cl-loop for hook in add-hooks
`(setq ,(intern (format "%s-hook" name)) ',add-hooks)) collect `(add-hook ',(intern (format "%s-hook" name))
#',hook))
,(when (or modes match files when) ,(when (or modes match files when)
`(associate! ,name `(associate! ,name
:modes ,modes :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 (defvar doom-init-ui-hook nil
"List of hooks to run when the UI has been initialized.") "List of hooks to run when the UI has been initialized.")
(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 (setq-default
ansi-color-for-comint-mode t ansi-color-for-comint-mode t
bidi-display-reordering nil ; disable bidirectional text for tiny performance boost 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 'completion-list-mode-hook #'hide-mode-line-mode)
(add-hook 'Man-mode-hook #'hide-mode-line-mode) (add-hook 'Man-mode-hook #'hide-mode-line-mode)
;; `highlight-numbers-mode' -- better number literal fontification in code ;; `highlight-numbers' -- better number literal fontification in code
(setq highlight-numbers-generic-regexp "\\_<[[:digit:]]+.*\\_>") (def-package! highlight-numbers
(add-hook 'prog-mode-hook #'highlight-numbers-mode) :hook (prog-mode . highlight-numbers-mode)
:config (setq highlight-numbers-generic-regexp "\\_<[[:digit:]]+.*\\_>"))
;; `highlight-escape-sequences' ;; `highlight-escape-sequences'
(def-package! highlight-escape-sequences (def-package! highlight-escape-sequences
:after-call after-find-file :hook ((prog-mode conf-mode) . highlight-escape-sequences-mode))
: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))
;; `rainbow-delimiters' Helps us distinguish stacked delimiter pairs. Especially ;; `rainbow-delimiters' Helps us distinguish stacked delimiter pairs. Especially
;; in parentheses-drunk languages like Lisp. ;; in parentheses-drunk languages like Lisp.
@ -289,51 +247,6 @@ from the default."
(add-hook 'after-change-major-mode-hook #'doom|show-whitespace-maybe) (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 ;; 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")) (setq frame-title-format '("%b Doom Emacs"))
;; draw me like one of your French editors ;; draw me like one of your French editors
(tooltip-mode -1) ; relegate tooltips to echo area only (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 ;; a good indicator that Emacs isn't frozen
(add-hook 'doom-init-ui-hook #'blink-cursor-mode) (add-hook 'doom-init-ui-hook #'blink-cursor-mode)
;; line numbers in most modes ;; line numbers in most modes
(add-hook! (prog-mode text-mode conf-mode) #'doom|enable-line-numbers) (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) (defun doom*fix-whitespace-mode-in-childframes (orig-fn &rest args)
(let ((frame (apply orig-fn args))) (let ((frame (apply orig-fn args)))
(with-selected-frame frame (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)) (eval-when-compile (file-truename user-emacs-directory))
"The path to this emacs.d directory. Must end in a slash.") "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.") "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.") "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 "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 that are safe to share across systems (if this config is symlinked across
several computers).") 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. "Directory for non-volatile storage.
Use this for files that don't change much, like servers binaries, external Use this for files that don't change much, like servers binaries, external
dependencies or long-term shared data.") 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. "Directory for volatile storage.
Use this for files that change often, like cache files.") 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.") "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.") "Where the Doom manual is stored.")
(defconst doom-private-dir (defvar doom-private-dir
(eval-when-compile (eval-when-compile
(or (getenv "DOOMDIR") (or (getenv "DOOMDIR")
(let ((xdg-path (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 "Where your private customizations are placed. Must end in a slash. Respects
XDG directory conventions if ~/.config/doom exists.") XDG directory conventions if ~/.config/doom exists.")
(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.") "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 "Where `doom-reload-package-autoloads' will generate its package.el autoloads
file.") file.")
@ -97,18 +97,6 @@ Doom was setup, which can cause problems.")
(defvar doom-site-load-path load-path (defvar doom-site-load-path load-path
"The starting load-path, before it is altered by `doom-initialize'.") "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-file (concat doom-local-dir "emacs-version.el"))
(defvar doom--last-emacs-version nil) (defvar doom--last-emacs-version nil)
(defvar doom--refreshed-p nil) (defvar doom--refreshed-p nil)
@ -236,6 +224,97 @@ original value of `symbol-file'."
(fset #'display-startup-echo-area-message #'ignore) (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 ;; Bootstrap helpers
;; ;;
@ -300,7 +379,9 @@ If RETURN-P, return the message as a string instead of displaying it."
-q or -Q, for example: -q or -Q, for example:
emacs -Q -l init.el -f doom|run-all-startup-hooks" 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 'emacs-startup-hook 'term-setup-hook
'window-setup-hook)) 'window-setup-hook))
(run-hook-wrapped hook #'doom-try-run-hook))) (run-hook-wrapped hook #'doom-try-run-hook)))

View file

@ -11,7 +11,8 @@
(package! hide-mode-line) (package! hide-mode-line)
(package! highlight-indentation) (package! highlight-indentation)
(package! highlight-numbers) (package! highlight-numbers)
(package! highlight-escape-sequences) (package! highlight-escape-sequences
:recipe (:fetcher github :repo "hlissner/highlight-escape-sequences"))
(unless (boundp 'display-line-numbers) (unless (boundp 'display-line-numbers)
(package! nlinum) (package! nlinum)
(package! nlinum-hl) (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 ;; This is a test bed for running Emacs Lisp in either a vanilla Emacs session
;; (free of Doom's clutches). This is equivalent to using emacs -Q with ;; free of Doom's clutches (C-c C-c), or in a vanilla Doom session free of your
;; package.el initialized and nothing else (so you have access to installed ;; private config (C-c C-d).
;; plugins).

View file

@ -58,75 +58,5 @@
(expect (kill-buffer (get-buffer-create "a")))) (expect (kill-buffer (get-buffer-create "a"))))
(it "shouldn't kill the fallback buffer" (it "shouldn't kill the fallback buffer"
(expect (not (kill-buffer (doom-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)))))

View file

@ -1,8 +1,8 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; core/test/test-core.el ;;; core/test/test-core.el
(xdescribe "core" (describe "core"
(describe "initialize" (xdescribe "initialize"
:var (doom-init-p doom-init-modules-p doom-private-dir) :var (doom-init-p doom-init-modules-p doom-private-dir)
(before-each (before-each
(setq doom-init-p nil (setq doom-init-p nil
@ -41,16 +41,85 @@
(it "does not load autoloads file if forced" ) (it "does not load autoloads file if forced" )
(it "does not regenerate missing autoloads" ))) (it "does not regenerate missing autoloads" )))
(describe "initialize-packages" (xdescribe "initialize-packages"
(before-each (spy-on 'quelpa-setup-p)) (before-each (spy-on 'quelpa-setup-p))
(it "initializes package.el once, unless forced" ) (it "initializes package.el once, unless forced" )
(it "initializes quelpa once, unless forced" ) (it "initializes quelpa once, unless forced" )
(it "initializes doom-packages once, unless forced" )) (it "initializes doom-packages once, unless forced" ))
(describe "initialize-modules" (xdescribe "initialize-modules"
(it "loads private init.el once, unless forced" )) (it "loads private init.el once, unless forced" ))
(describe "initialize-autoloads" (xdescribe "initialize-autoloads"
(it "loads autoloads file" ) (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 ;; Use fancy icons
(setq mu4e-headers-has-child-prefix '("+" . "") (setq mu4e-headers-has-child-prefix '("+" . "")
mu4e-headers-empty-parent-prefix '("-" . "") mu4e-headers-empty-parent-prefix '("-" . "")
mu4e-headers-first-child-prefix '("-" . "") mu4e-headers-first-child-prefix '("\\" . "")
mu4e-headers-duplicate-prefix '("-" . "") mu4e-headers-duplicate-prefix '("=" . "")
mu4e-headers-default-prefix '("-" . "") mu4e-headers-default-prefix '("|" . "")
mu4e-headers-draft-mark '("-" . "") mu4e-headers-draft-mark '("D" . "")
mu4e-headers-flagged-mark '("-" . "") mu4e-headers-flagged-mark '("F" . "")
mu4e-headers-new-mark '("-" . "") mu4e-headers-new-mark '("N" . "")
mu4e-headers-passed-mark '("-" . "") mu4e-headers-passed-mark '("P" . "")
mu4e-headers-replied-mark '("-" . "") mu4e-headers-replied-mark '("R" . "")
mu4e-headers-seen-mark '("-" . "") mu4e-headers-seen-mark '("S" . "")
mu4e-headers-trashed-mark '("-" . "") mu4e-headers-trashed-mark '("T" . "")
mu4e-headers-attach-mark '("-" . "") mu4e-headers-attach-mark '("a" . "")
mu4e-headers-encrypted-mark '("-" . "") mu4e-headers-encrypted-mark '("x" . "")
mu4e-headers-signed-mark '("-" . "") mu4e-headers-signed-mark '("s" . "")
mu4e-headers-unread-mark '("-" . "")) mu4e-headers-unread-mark '("u" . ""))
;; Add a column to display what email account the email belongs to. ;; Add a column to display what email account the email belongs to.
(add-to-list 'mu4e-header-info-custom (add-to-list 'mu4e-header-info-custom

View file

@ -19,17 +19,92 @@
#'helm-projectile-find-file))) #'helm-projectile-find-file)))
;;;###autoload ;;;###autoload
(defun +helm/persp-buffer-list () (defun +helm/workspace-buffer-list ()
"A version of `helm-buffers-list', but with its buffer list restricted to the "A version of `helm-buffers-list' with its buffer list restricted to the
current workspace." current workspace."
(interactive) (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 ;; 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 ;;;###autoload
(cl-defun +helm-file-search (engine &key query in all-files (recursive t)) (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 "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-directory directory)
(helm-ag--default-target (list directory)) (helm-ag--default-target (list directory))
(engine (or engine (engine (or engine
(cl-loop for tool in +helm-project-search-engines (cl-find-if #'executable-find +helm-project-search-engines
if (executable-find (symbol-name tool)) :key #'symbol-name)
return tool)
(and (or (executable-find "grep") (and (or (executable-find "grep")
(executable-find "git")) (executable-find "git"))
'grep) '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 (query (or query
(when (use-region-p) (when (use-region-p)
(let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning))) (let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning)))
@ -66,144 +140,97 @@ order.
(when (> (abs (- end beg)) 1) (when (> (abs (- end beg)) 1)
(rxt-quote-pcre (buffer-substring-no-properties beg end))))) (rxt-quote-pcre (buffer-substring-no-properties beg end)))))
"")) ""))
(prompt (format "%s%%s %s" (prompt (format "[%s %s] "
(symbol-name engine) (symbol-name engine)
(cond ((equal directory default-directory) (cond ((file-equal-p directory project-root)
"./")
((equal directory project-root)
(projectile-project-name)) (projectile-project-name))
(t ((file-equal-p directory default-directory)
(file-relative-name directory project-root))))) "./")
((file-relative-name directory project-root)))))
(command (command
(pcase engine (pcase engine
('grep (`ag (+helm-ag-search-args all-files recursive))
(let* ((helm-ff-default-directory directory) (`rg (+helm-rg-search-args all-files recursive))
(helm-grep-in-recurse recursive) (`pt (+helm-pt-search-args all-files recursive))
(helm-grep-ignored-files ('grep (+helm--grep-search directory query prompt all-files recursive)
(unless all-files (cl-return t))))
(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")))))
(helm-ag-base-command (string-join command " "))) (helm-ag-base-command (string-join command " ")))
(if (and (eq engine 'ag) ;; TODO Define our own sources instead
(equal query "")) (helm-attrset 'name (format "[%s %s] Searching %s"
(helm-do-ag directory) engine
(setq helm-ag--last-query query) (string-join (delq nil (cdr command)) " ")
(helm-attrset 'search-this-file nil helm-ag-source) (abbreviate-file-name directory))
(helm-attrset 'name (helm-ag--helm-header helm-ag--default-directory) helm-ag-source) helm-source-do-ag)
(helm :sources '(helm-ag-source) (cl-letf ((+helm-global-prompt prompt)
:input query ((symbol-function 'helm-do-ag--helm)
:prompt prompt (lambda () (helm :sources '(helm-source-do-ag)
:buffer "*helm-ag*" :buffer "*helm-ag*"
:keymap helm-ag-map :keymap helm-do-ag-map
:history 'helm-ag--helm-history)))) :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 ;;;###autoload
(defun +helm/project-search (arg) (defun +helm/project-search (&optional all-files-p)
"Performs a project search using the first available search backend from a "Performs a project search from the project root.
list of: ripgrep, ag, pt, git-grep and grep. If ARG (universal argument),
preform search from 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, in the search."
(interactive "P") (interactive "P")
(call-interactively (call-interactively
(or (cl-loop for tool in (cl-remove-duplicates +helm-project-search-engines :from-end t) (or (+helm--get-command "+helm/%s")
if (executable-find (symbol-name tool)) #'+helm/grep)))
return (intern (format "+helm/%s%s" tool (if arg "-from-cwd" ""))))
(if arg ;;;###autoload
#'+helm/grep-from-cwd (defun +helm/project-search-from-cwd (&optional all-files-p)
#'+helm/grep)))) "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 ;; Relative to project root
;;;###autoload ;;;###autoload (autoload '+helm/rg "completion/helm/autoload/helm")
(defun +helm/rg (all-files-p &optional query directory) ;;;###autoload (autoload '+helm/rg-from-cwd "completion/helm/autoload/helm")
"TODO" ;;;###autoload (autoload '+helm/ag "completion/helm/autoload/helm")
(interactive "P") ;;;###autoload (autoload '+helm/ag-from-cwd "completion/helm/autoload/helm")
(+helm-file-search 'rg :query query :in directory :all-files all-files-p)) ;;;###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 (dolist (engine (cl-remove-duplicates +helm-project-search-engines :from-end t))
(defun +helm/ag (all-files-p &optional query directory) (defalias (intern (format "+helm/%s" engine))
"TODO" (lambda (all-files-p &optional query directory)
(interactive "P") (interactive "P")
(+helm-file-search 'ag :query query :in directory :all-files all-files-p)) (+helm-file-search engine :query query :in directory :all-files all-files-p))
(format "Perform a project file search using %s.
;;;###autoload QUERY is a regexp. If omitted, the current selection is used. If no selection is
(defun +helm/pt (all-files-p &optional query directory) active, the last known search is used.
"TODO"
(interactive "P")
(+helm-file-search 'pt :query query :in directory :all-files all-files-p))
;;;###autoload If ALL-FILES-P, search compressed and hidden files as well."
(defun +helm/grep (all-files-p &optional query directory) engine))
"TODO"
(interactive "P")
(+helm-file-search 'grep :query query :in directory :all-files all-files-p))
;; Relative to current directory (defalias (intern (format "+helm/%s-from-cwd" engine))
;;;###autoload (lambda (all-files-p &optional query directory)
(defun +helm/rg-from-cwd (recurse-p &optional query) (interactive "P")
"TODO" (+helm-file-search engine :query query :in default-directory :all-files all-files-p))
(interactive "P") (format "Perform a project file search from the current directory using %s.
(+helm-file-search 'rg :query query :in default-directory :recursive recurse-p))
;;;###autoload QUERY is a regexp. If omitted, the current selection is used. If no selection is
(defun +helm/ag-from-cwd (recurse-p &optional query) active, the last known search is used.
"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))
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 ;;;###autoload
(defun +helm-posframe-display (buffer &optional _resume) (defun +helm-posframe-display (buffer &optional _resume)
"TODO" "TODO"
(require 'posframe)
(setq helm--buffer-in-new-frame-p t) (setq helm--buffer-in-new-frame-p t)
(posframe-show (let ((solaire-p (bound-and-true-p solaire-mode))
(setq +helm--posframe-buffer buffer) (params (copy-sequence +helm-posframe-parameters)))
:position (point) (let-alist params
:poshandler +helm-posframe-handler (require 'posframe)
:override-parameters +helm-posframe-parameters) (posframe-show
(unless (or (null +helm-posframe-text-scale) (setq +helm--posframe-buffer buffer)
(= +helm-posframe-text-scale 0)) :position (point)
(with-current-buffer buffer :poshandler +helm-posframe-handler
(text-scale-set +helm-posframe-text-scale)))) :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 ;;;###autoload
(defun +helm|posframe-cleanup () (defun +helm|posframe-cleanup ()

View file

@ -26,10 +26,10 @@ be negative.")
(defvar +helm-posframe-parameters (defvar +helm-posframe-parameters
'((internal-border-width . 8) '((internal-border-width . 8)
(min-width . 80)
(min-height . 16)
(width . 0.5) (width . 0.5)
(height . 0.55)) (height . 0.35)
(min-width . 80)
(min-height . 16))
"TODO") "TODO")
@ -49,7 +49,7 @@ be negative.")
[remap imenu-anywhere] #'helm-imenu-anywhere [remap imenu-anywhere] #'helm-imenu-anywhere
[remap imenu] #'helm-semantic-or-imenu [remap imenu] #'helm-semantic-or-imenu
[remap noop-show-kill-ring] #'helm-show-kill-ring [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 switch-to-buffer] #'helm-buffers-list
[remap projectile-find-file] #'+helm/projectile-find-file [remap projectile-find-file] #'+helm/projectile-find-file
[remap projectile-recentf] #'helm-projectile-recentf [remap projectile-recentf] #'helm-projectile-recentf
@ -81,8 +81,7 @@ be negative.")
helm-imenu-execute-action-at-once-if-one nil) helm-imenu-execute-action-at-once-if-one nil)
(when (and EMACS26+ (featurep! +childframe)) (when (and EMACS26+ (featurep! +childframe))
(setq helm-display-function #'+helm-posframe-display (setq helm-display-function #'+helm-posframe-display)
helm-echo-input-in-header-line t)
;; Fix "Specified window is not displaying the current buffer" error ;; Fix "Specified window is not displaying the current buffer" error
(advice-add #'posframe--get-font-height :around #'+helm*fix-get-font-height)) (advice-add #'posframe--get-font-height :around #'+helm*fix-get-font-height))
@ -90,6 +89,7 @@ be negative.")
(setq helm-mode-fuzzy-match fuzzy (setq helm-mode-fuzzy-match fuzzy
helm-completion-in-region-fuzzy-match fuzzy helm-completion-in-region-fuzzy-match fuzzy
helm-M-x-fuzzy-match fuzzy helm-M-x-fuzzy-match fuzzy
helm-ag-fuzzy-match fuzzy
helm-apropos-fuzzy-match fuzzy helm-apropos-fuzzy-match fuzzy
helm-bookmark-show-location fuzzy helm-bookmark-show-location fuzzy
helm-buffers-fuzzy-matching fuzzy helm-buffers-fuzzy-matching fuzzy
@ -105,6 +105,8 @@ be negative.")
helm-semantic-fuzzy-match fuzzy)) helm-semantic-fuzzy-match fuzzy))
:config :config
(set-popup-rule! "^\\*helm" :vslot -100 :size 0.22)
(defun +helm*replace-prompt (plist) (defun +helm*replace-prompt (plist)
"Globally replace helm prompts with `+helm-global-prompt'." "Globally replace helm prompts with `+helm-global-prompt'."
(cond ((not +helm-global-prompt) plist) (cond ((not +helm-global-prompt) plist)
@ -114,10 +116,14 @@ be negative.")
plist))) plist)))
(advice-add #'helm :filter-args #'+helm*replace-prompt) (advice-add #'helm :filter-args #'+helm*replace-prompt)
(defun +helm*hide-mode-line (&rest _) ;; Hide the modeline
(unless helm-mode-line-string (defun +helm|hide-mode-line (&rest _)
(hide-mode-line-mode +1))) (with-current-buffer (helm-buffer-get)
(advice-add #'helm-display-mode-line :override #'+helm*hide-mode-line) (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 () (defun +helm*hide-minibuffer-maybe ()
"Hide minibuffer in Helm session if we use the header line as input field." "Hide minibuffer in Helm session if we use the header line as input field."
@ -151,7 +157,9 @@ be negative.")
(after! helm-ag (after! helm-ag
(map! :map helm-ag-edit-map :n "RET" #'compile-goto-error) (map! :map helm-ag-edit-map :n "RET" #'compile-goto-error)
(define-key helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort) (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' ;; `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) #'counsel-find-file)
((doom-project-p 'nocache) ((doom-project-p 'nocache)
#'projectile-find-file) (let ((files (projectile-current-project-files)))
(if (<= (length files) ivy-sort-max-size)
;; FIXME When counsel-projectile-find-file is fixed upstream #'counsel-projectile-find-file
;; ((doom-project-p 'nocache) #'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)))) (#'counsel-file-jump))))
@ -307,87 +303,67 @@ order.
(counsel-pt query))) (counsel-pt query)))
(_ (error "No search engine specified")))))) (_ (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 ;;;###autoload
(defun +ivy/project-search (arg) (defun +ivy/project-search (&optional all-files-p)
"Performs a project search using the first available search backend from a "Performs a project search from the project root.
list of: ripgrep, ag, pt, git-grep and grep. If ARG (universal argument),
preform search from current directory." 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") (interactive "P")
(call-interactively (call-interactively
(or (cl-loop for tool in (cl-remove-duplicates +ivy-project-search-engines :from-end t) (or (+ivy--get-command "+ivy/%s")
if (executable-find (symbol-name tool)) #'+ivy/grep)))
return (intern (format "+ivy/%s%s" tool (if arg "-from-cwd" ""))))
(if arg
#'+ivy/grep-from-cwd
#'+ivy/grep))))
;;;###autoload ;;;###autoload
(defun +ivy/rg (all-files-p &optional query directory) (defun +ivy/project-search-from-cwd (&optional all-files-p)
"Perform a project file search using ripgrep. QUERY is a regexp. If omitted, "Performs a project search recursively from the current directory.
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. Uses the first available search backend from `+ivy-project-search-engines'. If
ALL-FILES-P (universal argument), include all files, even hidden or compressed
NOTE: ripgrep doesn't support multiline searches (yet)." ones."
(interactive "P") (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." ;; Relative to project root
(interactive "P") ;;;###autoload (autoload '+ivy/rg "completion/ivy/autoload/ivy")
(+ivy-file-search 'ag :query query :in directory :all-files all-files-p)) ;;;###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 (dolist (engine (cl-remove-duplicates +ivy-project-search-engines :from-end t))
(defun +ivy/pt (all-files-p &optional query directory) (defalias (intern (format "+ivy/%s" engine))
"Perform a project file search using the platinum searcher. QUERY is a grep (lambda (all-files-p &optional query directory)
regexp. If omitted, the current selection is used. If no selection is active, (interactive "P")
the last known search is used. (+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." QUERY is a regexp. If omitted, the current selection is used. If no selection is
(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
active, the last known search is used. active, the last known search is used.
If ALL-FILES-P, don't respect .gitignore files and search everything." If ALL-FILES-P, search compressed and hidden files as well."
(interactive "P") engine))
(+ivy-file-search 'grep :query query :in directory :all-files all-files-p))
;; Relative to current directory (defalias (intern (format "+ivy/%s-from-cwd" engine))
;;;###autoload (lambda (all-files-p &optional query directory)
(defun +ivy/rg-from-cwd (recursive-p &optional query) (interactive "P")
"Like `+ivy/rg', but from the current directory (recursively if RECURSIVE-P is (+ivy-file-search engine :query query :in default-directory :all-files all-files-p))
non-nil)." (format "Perform a project file search from the current directory using %s.
(interactive "P")
(+ivy-file-search 'rg :query query :in default-directory :recursive recursive-p))
;;;###autoload QUERY is a regexp. If omitted, the current selection is used. If no selection is
(defun +ivy/ag-from-cwd (recursive-p &optional query) active, the last known search is used.
"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))
;;;###autoload If ALL-FILES-P, search compressed and hidden files as well."
(defun +ivy/pt-from-cwd (recursive-p &optional query) engine)))
"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))

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) (set-popup-rule! "^\\*ivy-occur" :size 0.35 :ttl 0 :quit nil)
(setq counsel-find-file-ignore-regexp "\\(?:^[#.]\\)\\|\\(?:[#~]$\\)\\|\\(?:^Icon?\\)" (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 ;; Add smart-casing and compressed archive searching (-zS) to default
;; command arguments: ;; command arguments:
counsel-rg-base-command "rg -zS --no-heading --line-number --color never %s ." 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 (def-package! counsel-projectile
:disabled t
:commands (counsel-projectile-find-file counsel-projectile-find-dir counsel-projectile-switch-to-buffer :commands (counsel-projectile-find-file counsel-projectile-find-dir counsel-projectile-switch-to-buffer
counsel-projectile-grep counsel-projectile-ag counsel-projectile-switch-project) counsel-projectile-grep counsel-projectile-ag counsel-projectile-switch-project)
:init :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) (setf (alist-get t ivy-display-functions-alist) #'+ivy-display-at-frame-center-near-bottom)
;; posframe doesn't work well with async sources ;; 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))) (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 "Find file in project" :n "SPC" #'projectile-find-file
:desc "Browse files" :n "." #'find-file :desc "Browse files" :n "." #'find-file
:desc "Toggle last popup" :n "~" #'+popup/toggle :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 "Blink cursor line" :n "DEL" #'+nav-flash/blink-cursor
:desc "Jump to bookmark" :n "RET" #'bookmark-jump :desc "Jump to bookmark" :n "RET" #'bookmark-jump
@ -520,11 +523,11 @@
(:when (featurep! :completion ivy) (:when (featurep! :completion ivy)
:desc "Buffer" :nv "b" #'swiper :desc "Buffer" :nv "b" #'swiper
:desc "Project" :nv "p" #'+ivy/project-search :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) (:when (featurep! :completion helm)
:desc "Buffer" :nv "b" #'swiper-helm :desc "Buffer" :nv "b" #'swiper-helm
:desc "Project" :nv "p" #'+helm/project-search :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" :nv "i" #'imenu
:desc "Symbols across buffers" :nv "I" #'imenu-anywhere :desc "Symbols across buffers" :nv "I" #'imenu-anywhere
:desc "Online providers" :nv "o" #'+lookup/online-select) :desc "Online providers" :nv "o" #'+lookup/online-select)
@ -557,8 +560,11 @@
(:desc "buffer" :prefix "b" (:desc "buffer" :prefix "b"
:desc "New empty buffer" :n "n" #'evil-buffer-new :desc "New empty buffer" :n "n" #'evil-buffer-new
:desc "Switch workspace buffer" :n "b" #'persp-switch-to-buffer (:when (featurep! :feature workspaces)
:desc "Switch buffer" :n "B" #'switch-to-buffer :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 buffer" :n "k" #'kill-this-buffer
:desc "Kill other buffers" :n "o" #'doom/kill-other-buffers :desc "Kill other buffers" :n "o" #'doom/kill-other-buffers
:desc "Save buffer" :n "s" #'save-buffer :desc "Save buffer" :n "s" #'save-buffer
@ -663,7 +669,7 @@
:desc "Org capture" :n "x" #'org-capture) :desc "Org capture" :n "x" #'org-capture)
(:desc "open" :prefix "o" (: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 "Default browser" :n "b" #'browse-url-of-file
:desc "Debugger" :n "d" #'+debug/open :desc "Debugger" :n "d" #'+debug/open
:desc "REPL" :n "r" #'+eval/open-repl :desc "REPL" :n "r" #'+eval/open-repl

View file

@ -10,8 +10,13 @@
;;;###autodef ;;;###autodef
(defun set-repl-handler! (modes command) (defun set-repl-handler! (modes command)
"Define a REPL for MODES. MODES is either a single major mode symbol or a list "Defines a REPL for MODES.
of them. COMMAND is a function that creates and returns the REPL buffer."
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)) (dolist (mode (doom-enlist modes))
(setf (alist-get mode +eval-repls) command))) (setf (alist-get mode +eval-repls) command)))

View file

@ -1,14 +1,11 @@
;;; feature/evil/+everywhere.el -*- lexical-binding: t; -*- ;;; feature/evil/+everywhere.el -*- lexical-binding: t; -*-
;; Here we *truly* lazy-load evil-collection's modules by ensuring its modules ;; We load evil-collection ourselves for these reasons:
;; 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:
;; ;;
;; 1. To truly lazy load it. Some of its modules, like the elisp-mode and ;; 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 ;; 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 ;; 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 ;; :after-call. This means users can use (after! org ...) and be sure that
;; their changes will override evil-collection's. ;; 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-split :override #'+evil*window-split)
(advice-add #'evil-window-vsplit :override #'+evil*window-vsplit) (advice-add #'evil-window-vsplit :override #'+evil*window-vsplit)
;; Ensure jump points are created (defun +evil*set-jump (orig-fn &rest args)
(defun +evil*set-jump (&rest _) "Set a jump point and ensure ORIG-FN doesn't set any new jump points."
(evil-set-jump)) (evil-set-jump)
(advice-add #'counsel-git-grep-action :before #'+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 ----------- ;; --- custom interactive codes -----------
;; These arg types will highlight matches in the current buffer ;; 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 (unless yas-minor-mode
(yas-minor-mode-on)) (yas-minor-mode-on))
(when (and yas-minor-mode (when (and yas-minor-mode
(yas-expand-snippet (when-let*
(yas--template-content ((template (cl-find trigger (yas--all-templates (yas--get-snippet-tables mode))
(cl-find trigger (yas--all-templates (yas--get-snippet-tables mode)) :key #'yas--template-key :test #'equal)))
:key #'yas--template-key :test #'equal))) (yas-expand-snippet (yas--template-content template)))
(and (featurep 'evil) evil-mode) (and (featurep 'evil) evil-mode)
(and yas--active-field-overlay (and yas--active-field-overlay
(overlay-buffer 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-prompt-functions (delq #'yas-dropdown-prompt yas-prompt-functions)
yas-snippet-dirs nil) yas-snippet-dirs nil)
;; Exit snippets on ESC from normal mode ;; Exit snippets on ESC from normal mode
(add-hook 'doom-escape-hook #'yas-abort-snippet)) (add-hook 'doom-escape-hook #'yas-abort-snippet)
;;
(yas-reload-all))
(defun +file-templates|init () (defun +file-templates|init ()

View file

@ -1,8 +1,20 @@
;;; feature/snippets/autoload/snippets.el -*- lexical-binding: t; -*- ;;; feature/snippets/autoload/snippets.el -*- lexical-binding: t; -*-
;; ;;;###autoload
;; Commands (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 ;;;###autoload
(defun +snippets/goto-start-of-field () (defun +snippets/goto-start-of-field ()

View file

@ -22,11 +22,17 @@
:config :config
(setq yas-verbosity (if doom-debug-mode 3 0) (setq yas-verbosity (if doom-debug-mode 3 0)
yas-also-auto-indent-first-line t yas-also-auto-indent-first-line t
yas-prompt-functions (delq #'yas-dropdown-prompt yas-prompt-functions)
yas-triggers-in-field t) ; Allow nested snippets yas-triggers-in-field t) ; Allow nested snippets
;; Allow private snippets in DOOMDIR/snippets
(add-to-list 'yas-snippet-dirs '+snippets-dir nil #'eq) (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 ;; Register `def-project-mode!' modes with yasnippet. This enables project
;; specific snippet libraries (e.g. for Laravel, React or Jekyll projects). ;; specific snippet libraries (e.g. for Laravel, React or Jekyll projects).
(add-hook 'doom-project-hook #'+snippets|enable-project-modes) (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")) ispell-extr-args '("--dont-tex-check-comments"))
(after! ispell (after! ispell
(cond ((executable-find "hunspell") (when (equal (file-name-base ispell-program-name) "aspell")
(setq ispell-program-name "hunspell")) (add-to-list 'ispell-extra-args "--sug-mode=ultra")))
((executable-find "aspell")
(add-to-list 'ispell-extra-args "--sug-mode=ultra"))))
(def-package! flyspell ; built-in (def-package! flyspell ; built-in

View file

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

View file

@ -1,42 +1,39 @@
;;; lang/clojure/config.el -*- lexical-binding: t; -*- ;;; lang/clojure/config.el -*- lexical-binding: t; -*-
;; `clojure-mode' ;; `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 (def-package! clj-refactor
:after clojure-mode :config
:config (map! :map clj-refactor-map
(map! :map clj-refactor-map :localleader
:localleader :desc "Refactor hydra" :n "r" #'hydra-cljr-help-menu/body)))
: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))

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; -*- ;;; 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 ;; 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 (after! elisp-mode
(set-repl-handler! 'emacs-lisp-mode #'+emacs-lisp/repl) (set-repl-handler! 'emacs-lisp-mode #'+emacs-lisp/repl)
(set-eval-handler! 'emacs-lisp-mode #'+emacs-lisp-eval) (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-docset! 'emacs-lisp-mode "Emacs Lisp")
(set-pretty-symbols! 'emacs-lisp-mode :lambda "lambda") (set-pretty-symbols! 'emacs-lisp-mode :lambda "lambda")
(set-rotate-patterns! 'emacs-lisp-mode (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 ;; initialization
+emacs-lisp|init-imenu)) +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 ;; Special fontification for doom
(font-lock-add-keywords (font-lock-add-keywords
'emacs-lisp-mode 'emacs-lisp-mode
`(;; custom Doom cookies (append `(;; custom Doom cookies
("^;;;###\\(autodef\\|if\\)[ \n]" (1 font-lock-warning-face t)) ("^;;;###\\(autodef\\|if\\)[ \n]" (1 font-lock-warning-face t))
;; doom/module functions ;; highlight defined, special variables & functions
("\\(^\\|\\s-\\|,\\)(\\(\\(doom\\|\\+\\)[^) ]+\\|[^) ]+!\\)[) \n]" (2 'font-lock-keyword-face)))) (+emacs-lisp-highlight-vars-and-faces . +emacs-lisp--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))))
(defun +emacs-lisp|init-imenu () (defun +emacs-lisp|init-imenu ()
"Improve imenu support with better expression regexps and Doom-specific forms." "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) ("Macros" "^\\s-*(\\(?:cl-\\)?def\\(?:ine-compile-macro\\|macro\\) +\\([^ )\n]+\\)" 1)
("Inline Functions" "\\s-*(\\(?:cl-\\)?defsubst +\\([^ )\n]+\\)" 1) ("Inline Functions" "\\s-*(\\(?:cl-\\)?defsubst +\\([^ )\n]+\\)" 1)
("Functions" "^\\s-*(\\(?:cl-\\)?def\\(?:un\\|un\\*\\|method\\|generic\\|-memoized!\\) +\\([^ ,)\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-*(\\(def\\(?:c\\(?:onst\\(?:ant\\)?\\|ustom\\)\\|ine-symbol-macro\\|parameter\\|var\\(?:-local\\)?\\)\\)\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)" 2)
("Variables" "^\\s-*(defvar\\(?:-local\\)?\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)[[:space:]\n]+[^)]" 1)
("Types" "^\\s-*(\\(cl-def\\(?:struct\\|type\\)\\|def\\(?:class\\|face\\|group\\|ine-\\(?:condition\\|error\\|widget\\)\\|package\\|struct\\|t\\(?:\\(?:hem\\|yp\\)e\\)\\)\\)\\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 () (defun +emacs-lisp|disable-flycheck-maybe ()

View file

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

View file

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

View file

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

View file

@ -23,6 +23,9 @@
(`pdf-tools (`pdf-tools
(when (featurep! :tools pdf) (when (featurep! :tools pdf)
(add-to-list 'TeX-view-program-selection '(output-pdf "PDF Tools")) (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 ;; Update PDF buffers after successful LaTeX runs
(add-hook 'TeX-after-compilation-finished-function #'TeX-revert-document-buffer)))) (add-hook 'TeX-after-compilation-finished-function #'TeX-revert-document-buffer))))

View file

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

View file

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

View file

@ -12,22 +12,19 @@
path too.") path too.")
(define-obsolete-variable-alias 'org-export-directory '+org-export-dir "2.1.0") (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 () (defun +org|init-export ()
(setq org-export-backends '(ascii html latex md) (setq org-export-backends '(ascii html latex md)
org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/")) org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/"))
(when (executable-find "pandoc") (when (and (executable-find "pandoc")
(require 'ox-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 ;; Export to a central location by default or if target isn't in
;; `org-directory'. ;; `org-directory'.

View file

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

View file

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

View file

@ -2,6 +2,17 @@
(defvar +php-composer-conf (make-hash-table :test 'equal)) (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 ;;;###autoload
(defun +php-composer-conf (&optional project-root refresh-p) (defun +php-composer-conf (&optional project-root refresh-p)
"Retrieve the contents of composer.json as an alist. If REFRESH-P is non-nil "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; -*- ;;; lang/php/config.el -*- lexical-binding: t; -*-
(defvar +php--company-backends nil)
(def-package! php-mode (def-package! php-mode
:mode "\\.inc\\'" :mode "\\.inc\\'"
:config :config
@ -12,13 +10,12 @@
(set-repl-handler! 'php-mode #'php-boris) (set-repl-handler! 'php-mode #'php-boris)
(set-lookup-handlers! 'php-mode :documentation #'php-search-documentation) (set-lookup-handlers! 'php-mode :documentation #'php-search-documentation)
;; ac-php provides custom autocompletion, php-extras provides autocompletion ;; `+php-company-backend' uses `company-phpactor', `php-extras-company' or
;; for built-in libraries ;; `company-dabbrev-code', in that order.
(when +php--company-backends (set-company-backend! 'php-mode '+php-company-backend 'company-dabbrev-code)
(set-company-backend! 'php-mode +php--company-backends))
;; Use the smallest `sp-max-pair-length' for optimum `smartparens' performance ;; 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-with-modes '(php-mode)
(sp-local-pair "<?" "?>" :post-handlers '(("| " "SPC" "=") ("||\n[i]" "RET") ("[d2]" "p"))) (sp-local-pair "<?" "?>" :post-handlers '(("| " "SPC" "=") ("||\n[i]" "RET") ("[d2]" "p")))
@ -26,34 +23,63 @@
(map! :map php-mode-map (map! :map php-mode-map
:localleader :localleader
(:prefix "r" :prefix "t"
:n "cv" #'php-refactor--convert-local-to-instance-variable :n "r" #'phpunit-current-project
:n "u" #'php-refactor--optimize-use :n "a" #'phpunit-current-class
:v "xm" #'php-refactor--extract-method :n "s" #'phpunit-current-test))
:n "rv" #'php-refactor--rename-local-variable)
(:prefix "t"
:n "r" #'phpunit-current-project
:n "a" #'phpunit-current-class
:n "s" #'phpunit-current-test)))
(def-package! hack-mode (def-package! phpactor
:when (featurep! +hack) :after php-mode
:mode "\\.hh$") :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 (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 (def-package! php-extras
:after php-mode :after php-mode
:preface (advice-add #'php-extras-company-setup :override #'ignore) :preface
:init (add-to-list '+php--company-backends 'php-extras-company nil #'eq) ;; We'll set up company support ourselves
(advice-add #'php-extras-company-setup :override #'ignore)
:config :config
(setq php-extras-eldoc-functions-file (setq php-extras-eldoc-functions-file
(concat doom-etc-dir "php-extras-eldoc-functions")) (concat doom-etc-dir "php-extras-eldoc-functions"))
;; Make expensive php-extras generation async ;; Make expensive php-extras generation async
(unless (file-exists-p (concat php-extras-eldoc-functions-file ".el")) (unless (file-exists-p (concat php-extras-eldoc-functions-file ".el"))
(message "Generating PHP eldoc files...") (message "Generating PHP eldoc files...")
@ -67,13 +93,9 @@
(message "PHP eldoc updated!"))))) (message "PHP eldoc updated!")))))
(def-package! company-php (def-package! hack-mode
:when (featurep! :completion company) :when (featurep! +hack)
:commands (ac-php-remake-tags ac-php-remake-tags-all) :mode "\\.hh$")
: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/")))
;; ;;

View file

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

View file

@ -130,7 +130,11 @@
(def-package! pipenv (def-package! pipenv
:commands pipenv-project-p :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 (def-package! pyenv-mode
@ -152,7 +156,9 @@
(defun +python-current-pyvenv () pyvenv-virtual-env-name) (defun +python-current-pyvenv () pyvenv-virtual-env-name)
(add-hook 'pyvenv-post-activate-hooks #'+python|update-version) (add-hook 'pyvenv-post-activate-hooks #'+python|update-version)
(add-hook 'pyvenv-post-deactivate-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 (def-package! conda
@ -186,6 +192,5 @@
(add-hook 'conda-postactivate-hook #'+python|update-version) (add-hook 'conda-postactivate-hook #'+python|update-version)
(add-hook 'conda-postdeactivate-hook #'+python|update-version) (add-hook 'conda-postdeactivate-hook #'+python|update-version)
(add-to-list '+python-mode-line-indicator (add-to-list '+python-mode-line-indicator
'(conda-env-current-name '(conda-env-current-name (" conda:" conda-env-current-name))
(" conda:" conda-env-current-name))
'append)) 'append))

View file

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

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) :mode ("\\.http\\'" . restclient-mode)
:config :config
(set-popup-rule! "^\\*HTTP Response" :size 0.4 :quit 'other) (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 (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 :localleader
:desc "Execute HTTP request" :n "e" 'restclient-http-send-current :desc "Execute HTTP request" :n "e" #'restclient-http-send-current
:desc "Execute raw HTTP request" :n "E" 'restclient-http-send-current-raw :desc "Execute raw HTTP request" :n "E" #'restclient-http-send-current-raw
:desc "Copy curl command" :n "c" 'restclient-copy-curl-command)) :desc "Copy curl command" :n "c" #'restclient-copy-curl-command))
(def-package! company-restclient (def-package! company-restclient

View file

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

View file

@ -38,7 +38,11 @@
(cl-loop for pair in (cdr alist) (cl-loop for pair in (cdr alist)
unless (string-match-p "^[a-z-]" (cdr pair)) unless (string-match-p "^[a-z-]" (cdr pair))
collect (cons (car 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)) (setf (alist-get nil web-mode-engines-auto-pairs) nil))
(map! :map web-mode-map (map! :map web-mode-map

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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