From 5d8461854dfda360d758adf38e46574740e19ccd Mon Sep 17 00:00:00 2001 From: Andrew Whatson Date: Thu, 20 Aug 2020 10:10:45 +1000 Subject: [PATCH 01/25] Use separate geiser REPLs per project --- modules/lang/scheme/config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lang/scheme/config.el b/modules/lang/scheme/config.el index 343812458..41249b72c 100644 --- a/modules/lang/scheme/config.el +++ b/modules/lang/scheme/config.el @@ -10,7 +10,7 @@ :init (setq geiser-active-implementations '(guile chicken mit chibi chez) geiser-autodoc-identifier-format "%s → %s" - geiser-smart-tab-p t) + geiser-repl-current-project-function 'doom-project-root) (unless (featurep! :lang racket) (push 'racket geiser-active-implementations)) (after! scheme ; built-in From 7c69c7b7b57afa399bee8434ddd1f38319d20fa7 Mon Sep 17 00:00:00 2001 From: Jason Axelson Date: Wed, 19 Aug 2020 15:37:58 -1000 Subject: [PATCH 02/25] ArchLinux packages now have 27.1 as default https://www.archlinux.org/packages/extra/x86_64/emacs/ We could point to emacs-git AUR package for emacs 28: https://aur.archlinux.org/packages/emacs-git/ But I think the reference to emacs 27 was there simply because emacs 27 is the recommended version so I didn't include a replacement AUR link in this PR. --- docs/getting_started.org | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/getting_started.org b/docs/getting_started.org index 492c40216..f870d6b99 100644 --- a/docs/getting_started.org +++ b/docs/getting_started.org @@ -155,8 +155,7 @@ pacman -S git emacs ripgrep pacman -S fd #+END_SRC -The above installs Emacs 26.3 (at the time of writing). To acquire Emacs 27 -[[https://aur.archlinux.org/packages/emacs27-git/][emacs27-git]] is available on the AUR. +The above installs Emacs 27 (at the time of writing). **** NixOS On NixOS Emacs 26.3 can be installed via ~nix-env -Ai nixos.emacs~, or From 924a161ba68ec764531284851781b2aaa96a4a82 Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Thu, 20 Aug 2020 10:32:46 -0500 Subject: [PATCH 03/25] Pull lsp-pyright from melpa --- modules/lang/python/packages.el | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/lang/python/packages.el b/modules/lang/python/packages.el index 21a0759e4..8ec454b88 100644 --- a/modules/lang/python/packages.el +++ b/modules/lang/python/packages.el @@ -12,10 +12,7 @@ (when (featurep! +lsp) (unless (featurep! :tools lsp +eglot) (if (featurep! +pyright) - (package! lsp-pyright - ;; REVIEW Remove this when added to melpa - :recipe (:host github :repo "emacs-lsp/lsp-pyright") - :pin "9603dda12afaae9c82608c7d3762f98b24b8563f") + (package! lsp-pyright :pin "9603dda12afaae9c82608c7d3762f98b24b8563f") (package! lsp-python-ms :pin "a884a9a4eb1a3acd3d70c776aec5e968bbdc1731")))) ;; Programming environment From 0f1ff5f411f65cf670fff76893eb9bff8edcef08 Mon Sep 17 00:00:00 2001 From: Krzysztof Baranowski Date: Thu, 20 Aug 2020 09:07:50 -0700 Subject: [PATCH 04/25] Update +evil-bindings.el --- modules/config/default/+evil-bindings.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/config/default/+evil-bindings.el b/modules/config/default/+evil-bindings.el index b9ab54bfc..4e5e09dc1 100644 --- a/modules/config/default/+evil-bindings.el +++ b/modules/config/default/+evil-bindings.el @@ -541,7 +541,7 @@ (:when (featurep! :term eshell) :desc "Toggle eshell popup" "e" #'+eshell/toggle :desc "Open eshell here" "E" #'+eshell/here) - (:when (featurep! :tools macos) + (:when (featurep! :os macos) :desc "Reveal in Finder" "o" #'+macos/reveal-in-finder :desc "Reveal project in Finder" "O" #'+macos/reveal-project-in-finder :desc "Send to Transmit" "u" #'+macos/send-to-transmit From 8916f442f13ca3721b691fa87e268e7beadc8f80 Mon Sep 17 00:00:00 2001 From: Krzysztof Baranowski Date: Thu, 20 Aug 2020 09:12:45 -0700 Subject: [PATCH 05/25] Update +emacs-bindings.el --- modules/config/default/+emacs-bindings.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/config/default/+emacs-bindings.el b/modules/config/default/+emacs-bindings.el index d239d67e4..b66c29df1 100644 --- a/modules/config/default/+emacs-bindings.el +++ b/modules/config/default/+emacs-bindings.el @@ -204,7 +204,7 @@ (:when (featurep! :term eshell) :desc "Toggle eshell popup" "e" #'+eshell/toggle :desc "Open eshell here" "E" #'+eshell/here) - (:when (featurep! :tools macos) + (:when (featurep! :os macos) :desc "Reveal in Finder" "o" #'+macos/reveal-in-finder :desc "Reveal project in Finder" "O" #'+macos/reveal-project-in-finder :desc "Send to Transmit" "u" #'+macos/send-to-transmit From fb4f5efb0166b96a640295506c8f42c1fededb2a Mon Sep 17 00:00:00 2001 From: mcbloch Date: Thu, 20 Aug 2020 18:44:27 +0200 Subject: [PATCH 06/25] Add definition and documentation keybindings --- modules/lang/nim/config.el | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/lang/nim/config.el b/modules/lang/nim/config.el index fbf169299..5f5126d0d 100644 --- a/modules/lang/nim/config.el +++ b/modules/lang/nim/config.el @@ -1,6 +1,7 @@ ;;; lang/nim/config.el -*- lexical-binding: t; -*- (after! nim-mode + :init (add-hook! 'nim-mode-hook (defun +nim-init-nimsuggest-mode-h () "Conditionally load `nimsuggest-mode', instead of clumsily erroring out if @@ -19,9 +20,16 @@ windows." :filter-return #'nimsuggest--get-temp-file-name (replace-regexp-in-string "[꞉* |<>\"?*]" "" path))) + :config + (set-lookup-handlers! '(nim-mode nimsuggest-mode) + :definition #'+nimsuggest-find-definition + :documentation #'nimsuggest-show-doc) + (map! :localleader :map nim-mode-map - "b" #'nim-compile)) + "b" #'nim-compile + "h" #'nimsuggest-show-doc + "d" #'nimsuggest-find-definition)) (use-package! flycheck-nim From 9e9b95f49c5154dacd01b7d53896c349acc39cb0 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 20 Aug 2020 14:07:47 -0400 Subject: [PATCH 07/25] Fix #3789: fix eglot lookup-documentation handler Eglot replaced `eglot-help-at-point' in joaotavora/eglot@a044dec, breaking our documentation lookup handler. --- modules/tools/lsp/+eglot.el | 4 ++-- modules/tools/lsp/autoload/eglot.el | 34 +++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/modules/tools/lsp/+eglot.el b/modules/tools/lsp/+eglot.el index 8e9ccb329..469be56c0 100644 --- a/modules/tools/lsp/+eglot.el +++ b/modules/tools/lsp/+eglot.el @@ -16,11 +16,11 @@ eglot-auto-display-help-buffer nil) :config - (set-popup-rule! "^\\*eglot-help" :size 0.35 :quit t :select t) + (set-popup-rule! "^\\*eglot-help" :size 0.15 :quit t :select t) (set-lookup-handlers! 'eglot--managed-mode :implementations #'eglot-find-implementation :type-definition #'eglot-find-typeDefinition - :documentation #'+eglot/documentation-lookup-handler) + :documentation #'+eglot-lookup-documentation) (when (featurep! :checkers syntax) (after! flycheck (load! "autoload/flycheck-eglot")))) diff --git a/modules/tools/lsp/autoload/eglot.el b/modules/tools/lsp/autoload/eglot.el index f9b647d5e..6f7fd029e 100644 --- a/modules/tools/lsp/autoload/eglot.el +++ b/modules/tools/lsp/autoload/eglot.el @@ -9,11 +9,31 @@ Example : (set-eglot-client! 'python-mode `(,(concat doom-etc-dir \"lsp/mspyls/M (after! eglot (add-to-list 'eglot-server-programs `(,mode . ,server-call)))) +;; HACK Eglot removed `eglot-help-at-point' in joaotavora/eglot@a044dec for a +;; more problematic approach of deferred to eldoc. Here, I've restored it. +;; Doom's lookup handlers try to open documentation in a separate window +;; (so they can be copied or kept open), but doing so with an eldoc buffer +;; is difficult because a) its contents are generated asynchronously, +;; making them tough to scrape, and b) their contents change frequently +;; (every time you move your cursor). +(defvar +eglot--help-buffer nil) ;;;###autoload -(defun +eglot/documentation-lookup-handler () - "Documentation lookup handler using eglot :document/hover handler. - -Mostly a rewrite of `eglot-help-at-point', which should be used interactively." - (interactive) - (eglot-help-at-point) - (display-buffer eglot--help-buffer)) +(defun +eglot-lookup-documentation (_identifier) + "Request documentation for the thing at point." + (eglot--dbind ((Hover) contents range) + (jsonrpc-request (eglot--current-server-or-lose) :textDocument/hover + (eglot--TextDocumentPositionParams)) + (let ((blurb (and (not (seq-empty-p contents)) + (eglot--hover-info contents range))) + (hint (thing-at-point 'symbol))) + (if blurb + (with-current-buffer + (or (and (buffer-live-p +eglot--help-buffer) + +eglot--help-buffer) + (setq +eglot--help-buffer (generate-new-buffer "*eglot-help*"))) + (with-help-window (current-buffer) + (rename-buffer (format "*eglot-help for %s*" hint)) + (with-current-buffer standard-output (insert blurb)) + (setq-local nobreak-char-display nil))) + (display-local-help)))) + 'deferred) From bf4929f4df73beebcb7924a59f6c758f85775245 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 20 Aug 2020 17:23:45 -0400 Subject: [PATCH 08/25] Fix #3760: bind SPC m d only when debugger is active --- modules/tools/debugger/config.el | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/modules/tools/debugger/config.el b/modules/tools/debugger/config.el index c9e870584..b23a322d6 100644 --- a/modules/tools/debugger/config.el +++ b/modules/tools/debugger/config.el @@ -120,8 +120,31 @@ (dap-mode 1) + (define-minor-mode +dap-running-session-mode + "A mode for adding keybindings to running sessions" + nil nil (make-sparse-keymap) + (when (bound-and-true-p evil-mode) + (evil-normalize-keymaps)) ; if you use evil, this is necessary to update the keymaps + ;; The following code adds to the dap-terminated-hook so that this minor + ;; mode will be deactivated when the debugger finishes + (when +dap-running-session-mode + (let ((session-at-creation (dap--cur-active-session-or-die))) + (add-hook 'dap-terminated-hook + (lambda (session) + (when (eq session session-at-creation) + (+dap-running-session-mode -1))))))) + + ;; Activate this minor mode when dap is initialized + (add-hook 'dap-session-created-hook #'+dap-running-session-mode) + ;; Activate this minor mode when hitting a breakpoint in another file + (add-hook 'dap-stopped-hook #'+dap-running-session-mode) + ;; Activate this minor mode when stepping into code in another file + (add-hook 'dap-stack-frame-changed-hook (lambda (session) + (when (dap--session-running session) + (+dap-running-session-mode 1)))) + (map! :localleader - :map dap-mode-map + :map +dap-running-session-mode "d" #'dap-hydra)) From 677b17bd914e58f793a92d089ce43d2690aac733 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 21 Aug 2020 00:35:52 +0200 Subject: [PATCH 09/25] Use use-package instead of after --- modules/lang/nim/config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lang/nim/config.el b/modules/lang/nim/config.el index 5f5126d0d..23487e682 100644 --- a/modules/lang/nim/config.el +++ b/modules/lang/nim/config.el @@ -1,6 +1,6 @@ ;;; lang/nim/config.el -*- lexical-binding: t; -*- -(after! nim-mode +(use-package! nim-mode :init (add-hook! 'nim-mode-hook (defun +nim-init-nimsuggest-mode-h () From 56f4b05dca7be8a8b97ebf6d8301f2a714185e3e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 20 Aug 2020 21:38:49 -0400 Subject: [PATCH 10/25] lang/nim: lazy load nim-mode --- modules/lang/nim/config.el | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/lang/nim/config.el b/modules/lang/nim/config.el index 23487e682..1c2fd9899 100644 --- a/modules/lang/nim/config.el +++ b/modules/lang/nim/config.el @@ -1,6 +1,7 @@ ;;; lang/nim/config.el -*- lexical-binding: t; -*- (use-package! nim-mode + :defer t :init (add-hook! 'nim-mode-hook (defun +nim-init-nimsuggest-mode-h () From f454d5fac43c0e9fa15525308d84a779d090be58 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 20 Aug 2020 21:40:06 -0400 Subject: [PATCH 11/25] os/macos: add packages.el --- modules/os/macos/packages.el | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 modules/os/macos/packages.el diff --git a/modules/os/macos/packages.el b/modules/os/macos/packages.el new file mode 100644 index 000000000..61544d465 --- /dev/null +++ b/modules/os/macos/packages.el @@ -0,0 +1,5 @@ +;; -*- no-byte-compile: t; -*- +;;; os/macos/packages.el + +(package! osx-trash :pin "0f1dc052d0a750b8c75f14530a4897f5d4324b4e") +(package! ns-auto-titlebar :pin "60273e764bf8d95abc40dd2fdc23af87ea9ee33b") From 06c69467421fbccd5f904c5ffa232a5af93e8ca6 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 20 Aug 2020 22:00:53 -0400 Subject: [PATCH 12/25] tools/lsp: defer auto-shutdown of eglot server --- modules/tools/lsp/+eglot.el | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/modules/tools/lsp/+eglot.el b/modules/tools/lsp/+eglot.el index 469be56c0..778f96681 100644 --- a/modules/tools/lsp/+eglot.el +++ b/modules/tools/lsp/+eglot.el @@ -1,7 +1,6 @@ ;;; tools/lsp/+eglot.el -*- lexical-binding: t; -*- ;; TODO set eglot-events-buffer-size to nil in doom-debug-mode -;; TODO Implement `+lsp-defer-shutdown' (use-package! eglot :commands eglot eglot-ensure @@ -23,4 +22,22 @@ :documentation #'+eglot-lookup-documentation) (when (featurep! :checkers syntax) (after! flycheck - (load! "autoload/flycheck-eglot")))) + (load! "autoload/flycheck-eglot"))) + + (defadvice! +lsp--defer-server-shutdown-a (orig-fn &optional server) + "Defer server shutdown for a few seconds. +This gives the user a chance to open other project files before the server is +auto-killed (which is a potentially expensive process). It also prevents the +server getting expensively restarted when reverting buffers." + :around #'eglot--managed-mode + (letf! (defun eglot-shutdown (server) + (if (or (null +lsp-defer-shutdown) + (eq +lsp-defer-shutdown 0)) + (funcall eglot-shutdown server) + (run-at-time + (if (numberp +lsp-defer-shutdown) +lsp-defer-shutdown 3) + nil (lambda (server) + (unless (eglot--managed-buffers server) + (funcall eglot-shutdown server))) + server))) + (funcall orig-fn server)))) From 70148bbfc8b4a72d77f71775725ceb8c7ac9c11d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 20 Aug 2020 22:01:21 -0400 Subject: [PATCH 13/25] Inhibit local-vars hooks when reverting Possibly addresses #3691 --- core/core.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core.el b/core/core.el index 6b51efa84..9a6583481 100644 --- a/core/core.el +++ b/core/core.el @@ -369,7 +369,7 @@ config.el instead." (defun doom-run-local-var-hooks-h () "Run MODE-local-vars-hook after local variables are initialized." - (unless doom-inhibit-local-var-hooks + (unless (or doom-inhibit-local-var-hooks revert-buffer-in-progress-p) (set (make-local-variable 'doom-inhibit-local-var-hooks) t) (run-hook-wrapped (intern-soft (format "%s-local-vars-hook" major-mode)) #'doom-try-run-hook))) From 4e82ee4397c699c41c4ba8dbbc955d84c6f86a29 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 00:09:59 -0400 Subject: [PATCH 14/25] Refactor doom-debug-mode + Add explain-pause-mode + Now reloads itself if doom-debug-variables is changed or when one of its variables becomes available. + doom-debug-variables now supports a cons cell entry where its CAR is the name of the variable and CDR is the value it should be set to when doom-debug-mode is active. --- core/autoload/debug.el | 60 ++++++++++++++++++++++++------- core/packages.el | 4 +++ modules/editor/snippets/config.el | 2 ++ modules/tools/lsp/+eglot.el | 5 +-- modules/tools/lsp/+lsp.el | 2 ++ modules/tools/magit/config.el | 2 ++ 6 files changed, 61 insertions(+), 14 deletions(-) diff --git a/core/autoload/debug.el b/core/autoload/debug.el index 1d74faaa5..fabe6ed80 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -5,26 +5,62 @@ ;;;###autoload (defvar doom-debug-variables - '(doom-debug-p - init-file-debug - debug-on-error + '(debug-on-error + doom-debug-p garbage-collection-messages - use-package-verbose - jka-compr-verbose - lsp-log-io gcmh-verbose - magit-refresh-verbose - url-debug) - "A list of variable to toggle on `doom-debug-mode'.") + init-file-debug + jka-compr-verbose + url-debug + use-package-verbose) + "A list of variable to toggle on `doom-debug-mode'. + +Each entry can be a variable symbol or a cons cell whose CAR is the variable +symbol and CDR is the value to set it to when `doom-debug-mode' is activated.") + +(defvar doom--debug-vars-old-values nil) +(defvar doom--debug-vars-undefined nil) + +(defun doom--watch-debug-vars-h (&rest _) + (when-let (bound-vars (cl-remove-if-not #'boundp doom--debug-vars-undefined)) + (doom-log "New variables available: %s" bound-vars) + (let ((message-log-max nil)) + (doom-debug-mode -1) + (doom-debug-mode +1)))) ;;;###autoload (define-minor-mode doom-debug-mode "Toggle `debug-on-error' and `doom-debug-p' for verbose logging." :init-value nil :global t - (let ((value doom-debug-mode)) - (mapc (doom-rpartial #'set value) doom-debug-variables) - (message "Debug mode %s" (if value "on" "off")))) + (let ((enabled doom-debug-mode)) + (setq doom--debug-vars-undefined nil) + (dolist (var doom-debug-variables) + (cond ((listp var) + (cl-destructuring-bind (var . val) var + (if (not (boundp var)) + (add-to-list 'doom--debug-vars-undefined var) + (set-default + var (if (not enabled) + (alist-get var doom--debug-vars-old-values) + (setf (alist-get var doom--debug-vars-old-values) + (symbol-value var)) + val))))) + ((if (boundp var) + (set-default var enabled) + (add-to-list 'doom--debug-vars-undefined var))))) + (when (fboundp 'explain-pause-mode) + (explain-pause-mode enabled)) + ;; Watch for changes in `doom-debug-variables', or when packages load (and + ;; potentially define one of `doom-debug-variables'), in case some of them + ;; aren't defined when `doom-debug-mode' is first loaded. + (cond (enabled + (add-variable-watcher 'doom-debug-variables #'doom--watch-debug-vars-h) + (add-hook 'after-load-functions #'doom--watch-debug-vars-h)) + (t + (remove-variable-watcher 'doom-debug-variables #'doom--watch-debug-vars-h) + (remove-hook 'after-load-functions #'doom--watch-debug-vars-h))) + (message "Debug mode %s" (if enabled "on" "off")))) ;; diff --git a/core/packages.el b/core/packages.el index fbfa46c80..55f99d2a8 100644 --- a/core/packages.el +++ b/core/packages.el @@ -4,6 +4,10 @@ ;; core.el (package! auto-minor-mode :pin "17cfa1b54800fdef2975c0c0531dad34846a5065") (package! gcmh :pin "b1bde5089169a74f62033d027e06e98cbeedd43f") +(package! explain-pause-mode + :recipe (:host github + :repo "lastquestion/explain-pause-mode") + :pin "2356c8c3639cbeeb9751744dbe737267849b4b51") ;; core-packages.el (package! straight diff --git a/modules/editor/snippets/config.el b/modules/editor/snippets/config.el index f0d81073e..c16f73f75 100644 --- a/modules/editor/snippets/config.el +++ b/modules/editor/snippets/config.el @@ -33,6 +33,8 @@ #'yas-minor-mode-on) :config + (add-to-list 'doom-debug-variables '(yas-verbosity . 3)) + ;; Allow private snippets in DOOMDIR/snippets (add-to-list 'yas-snippet-dirs '+snippets-dir) diff --git a/modules/tools/lsp/+eglot.el b/modules/tools/lsp/+eglot.el index 778f96681..8e3fdcaac 100644 --- a/modules/tools/lsp/+eglot.el +++ b/modules/tools/lsp/+eglot.el @@ -1,7 +1,5 @@ ;;; tools/lsp/+eglot.el -*- lexical-binding: t; -*- -;; TODO set eglot-events-buffer-size to nil in doom-debug-mode - (use-package! eglot :commands eglot eglot-ensure :hook (eglot-managed-mode . +lsp-init-optimizations-h) @@ -20,6 +18,9 @@ :implementations #'eglot-find-implementation :type-definition #'eglot-find-typeDefinition :documentation #'+eglot-lookup-documentation) + + (add-to-list 'doom-debug-variables '(eglot-events-buffer-size . 0)) + (when (featurep! :checkers syntax) (after! flycheck (load! "autoload/flycheck-eglot"))) diff --git a/modules/tools/lsp/+lsp.el b/modules/tools/lsp/+lsp.el index 014d19463..c54e0f2d2 100644 --- a/modules/tools/lsp/+lsp.el +++ b/modules/tools/lsp/+lsp.el @@ -44,6 +44,8 @@ should be a deliberate act (as is flipping this variable).") lsp-enable-on-type-formatting nil) :config + (pushnew! doom-debug-variables 'lsp-log-io 'lsp-print-performance) + (setq lsp-intelephense-storage-path (concat doom-cache-dir "lsp-intelephense/") lsp-vetur-global-snippets-dir (expand-file-name "vetur" (or (bound-and-true-p +snippets-dir) diff --git a/modules/tools/magit/config.el b/modules/tools/magit/config.el index d3b971b68..fac4acf1d 100644 --- a/modules/tools/magit/config.el +++ b/modules/tools/magit/config.el @@ -18,6 +18,8 @@ For example, diffs and log buffers. Accepts `left', `right', `up', and `down'.") transient-values-file (concat doom-etc-dir "transient/values") transient-history-file (concat doom-etc-dir "transient/history")) :config + (add-to-list 'doom-debug-variables 'magit-refresh-verbose) + (setq transient-default-level 5 magit-diff-refine-hunk t ; show granular diffs in selected hunk ;; Don't autosave repo buffers. This is too magical, and saving can From e54bb170c30c8d6d0e961d195e037c43612c23db Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 01:25:44 -0400 Subject: [PATCH 15/25] docs/modules: fix os/macos & ui/ligatures links --- docs/modules.org | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules.org b/docs/modules.org index 0e14b5de1..4822e3c4f 100644 --- a/docs/modules.org +++ b/docs/modules.org @@ -154,7 +154,7 @@ Modules that bring support for a language or group of languages to Emacs. * :os Modules to improve integration into your OS, system, or devices. -+ [[file:/mnt/projects/conf/doom-emacs/modules/os/macos/README.org][macos]] - Improve Emacs' compatibility with macOS ++ [[file:../modules/os/macos/README.org][macos]] - Improve Emacs' compatibility with macOS + tty =+osc= - Improves the terminal Emacs experience. * :term @@ -201,7 +201,7 @@ Aesthetic modules that affect the Emacs interface or user experience. + [[file:../modules/ui/hl-todo/README.org][hl-todo]] - TODO + [[file:../modules/ui/hydra/README.org][hydra]] - TODO + indent-guides - TODO -+ [[file:/mnt/projects/conf/doom-emacs/modules/ui/ligatures/README.org][ligatures]] =+extra +fira +hasklig +iosevka +pragmata-pro= - Ligature support for Emacs ++ [[file:../modules/ui/ligatures/README.org][ligatures]] =+extra +fira +hasklig +iosevka +pragmata-pro= - Ligature support for Emacs + [[file:../modules/ui/minimap/README.org][minimap]] - TODO + [[file:../modules/ui/modeline/README.org][modeline]] =+light= - TODO + [[file:../modules/ui/nav-flash/README.org][nav-flash]] - TODO From 06c404ecb129fecf155ac71b21e4a84d4e24ee5d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 02:34:07 -0400 Subject: [PATCH 16/25] tools/direnv: replace direnv package with envrc wbolster/emacs-direnv uses an approach that mutates global state, allowing a direnv to bleed into unrelated buffers and contexts. For this to work it must rereads the direnv every time you switch buffers, which can be very slow. purcell/envrc, on the other hand, makes env state buffer-local, so the direnv only needs to be read once, when a is first initialized. This is faster and less error prone. However, it's necessary to manually reload the direnv if you've changed your .envrc outside of Emacs (with `M-x envrc-reload` or `M-x envrc-reload-all`). --- modules/tools/direnv/README.org | 2 +- modules/tools/direnv/config.el | 35 ++++++++++++++++++++------------ modules/tools/direnv/packages.el | 2 +- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/modules/tools/direnv/README.org b/modules/tools/direnv/README.org index 75e5e6ae4..53b1a792e 100644 --- a/modules/tools/direnv/README.org +++ b/modules/tools/direnv/README.org @@ -34,7 +34,7 @@ direnv and then made available to the current shell. This module provides no flags. ** Plugins -+ [[https://github.com/wbolster/emacs-direnv][direnv]] ++ [[https://github.com/purcell/envrc][envrc]] ** Hacks + Normally, the direnv environment is updated on ~post-command-hook~. We've diff --git a/modules/tools/direnv/config.el b/modules/tools/direnv/config.el index 04abdab15..d393d8d59 100644 --- a/modules/tools/direnv/config.el +++ b/modules/tools/direnv/config.el @@ -5,30 +5,39 @@ "join_args" "expand_path" "dotenv" "user_rel_path" "find_up" "source_env" "watch_file" "source_up" "direnv_load" "MANPATH_add" "load_prefix" "layout" "use" "rvm" "use_nix" "use_guix") - "TODO") + "A list of direnv keywords, which are fontified when in `+direnv-rc-mode'.") ;; ;;; Packages -(use-package! direnv - :hook (before-hack-local-variables . direnv--maybe-update-environment) - :hook (flycheck-before-syntax-check . direnv--maybe-update-environment) - :hook (direnv-envrc-mode . +direnv-envrc-fontify-keywords-h) +(use-package! envrc + :when (executable-find "direnv") + :after-call doom-first-file + :mode ("\\.envrc\\'" . +direnv-rc-mode) :config - (add-to-list 'direnv-non-file-modes 'vterm-mode) + (add-to-list 'doom-debug-variables 'envrc-debug) - (defun +direnv-envrc-fontify-keywords-h () - "Fontify special .envrc keywords; it's a good indication of whether or not -we've typed them correctly." + ;; I'm avoiding `global-envrc-mode' intentionally, because it has the + ;; potential to run too late in the mode startup process (and after, say, + ;; server hooks that may rely on that local direnv environment). + (add-hook! 'change-major-mode-after-body-hook + (defun +direnv-init-h () + (unless (or envrc-mode + (minibufferp) + (file-remote-p default-directory)) + (envrc-mode 1)))) + + (define-derived-mode +direnv-rc-mode sh-mode "envrc" + "Major mode for .envrc files." + ;; Fontify .envrc keywords; it's a good indication of whether or not we've + ;; typed them correctly, and that we're in the correct major mode. (font-lock-add-keywords nil `((,(regexp-opt +direnv-keywords 'symbols) (0 font-lock-keyword-face))))) (defadvice! +direnv--fail-gracefully-a (&rest _) "Don't try to use direnv if the executable isn't present." - :before-while #'direnv-update-directory-environment + :before-while #'envrc-mode (or (executable-find "direnv") - (ignore (doom-log "Couldn't find direnv executable")))) - - (direnv-mode +1)) + (ignore (doom-log "Couldn't find direnv executable"))))) diff --git a/modules/tools/direnv/packages.el b/modules/tools/direnv/packages.el index 7d43b9c0c..ea30e395d 100644 --- a/modules/tools/direnv/packages.el +++ b/modules/tools/direnv/packages.el @@ -1,4 +1,4 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/direnv/packages.el -(package! direnv :pin "f5484b0fc33d4e5116612626294efb362ff9ecd4") +(package! envrc :pin "1dc5aad14d2c27211c7c288d2d9dffeb2e27cb2d") From 10d25be4edc7f2ec54a4ff0374213d574aac6fad Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 03:04:14 -0400 Subject: [PATCH 17/25] bin/org-capture: TERM=xterm-256color in alacritty --- bin/org-capture | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/org-capture b/bin/org-capture index 1f338c6b6..573ed6212 100755 --- a/bin/org-capture +++ b/bin/org-capture @@ -30,6 +30,9 @@ shift $((OPTIND-1)) [ -t 0 ] && str="$*" || str=$(cat) +# Fix incompatible terminals that cause odd 'not a valid terminal' errors +[ $TERM -eq "alacritty" ] && export TERM=xterm-256color + if [ $daemon ]; then emacsclient -a "" \ -c -F '((name . "doom-capture") (width . 70) (height . 25) (transient . t))' \ From 6fef21c3d69b61999fa711bdc7fd444341e0afe9 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 03:12:11 -0400 Subject: [PATCH 18/25] Git ignore nix build result symlinks --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 55f8289ef..be918ec8a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ modules/private cask/ elpa/ test/.local*/ +test/result +result # emacs tempfiles that shouldn't be there .mc-lists.el From 801cfd63d49e8f961de5063a4b222b748f1729ec Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 03:14:25 -0400 Subject: [PATCH 19/25] Don't recenter window after better-jumper jump On C-o or C-i; this can be more disorienting than helpful. --- core/core-editor.el | 1 - 1 file changed, 1 deletion(-) diff --git a/core/core-editor.el b/core/core-editor.el index 9c924ec27..740d6f970 100644 --- a/core/core-editor.el +++ b/core/core-editor.el @@ -321,7 +321,6 @@ files, so we replace calls to `pp' with the much faster `prin1'." (use-package! better-jumper :hook (doom-first-input . better-jumper-mode) - :hook (better-jumper-post-jump . recenter) :commands doom-set-jump-a doom-set-jump-maybe-a doom-set-jump-h :preface ;; REVIEW Suppress byte-compiler warning spawning a *Compile-Log* buffer at From 95c6c83a76ac50da9ae1b6f0d6422a474e1b6d44 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 14:58:07 -0400 Subject: [PATCH 20/25] Fix #3798: fix keymap typo for +dap-running-session-mode --- modules/tools/debugger/config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tools/debugger/config.el b/modules/tools/debugger/config.el index b23a322d6..e745e08af 100644 --- a/modules/tools/debugger/config.el +++ b/modules/tools/debugger/config.el @@ -144,7 +144,7 @@ (+dap-running-session-mode 1)))) (map! :localleader - :map +dap-running-session-mode + :map +dap-running-session-mode-map "d" #'dap-hydra)) From a1da1fa82f0eee5e1789c4033b96a63413229b64 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 15:01:13 -0400 Subject: [PATCH 21/25] Bump :completion ivy tumashu/ivy-posframe@82a63ae -> tumashu/ivy-posframe@4474956 tumashu/ivy-posframe@82a63ae seems to have been removed or force pushed out of master. Fixes #3799 --- modules/completion/ivy/packages.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/completion/ivy/packages.el b/modules/completion/ivy/packages.el index 38307ff68..ec4a388db 100644 --- a/modules/completion/ivy/packages.el +++ b/modules/completion/ivy/packages.el @@ -17,7 +17,7 @@ (package! flx :pin "17f5c9cb2af18aa6f52910ff4a5a63591261ced5"))) (when (featurep! +childframe) - (package! ivy-posframe :pin "82a63ae0fe1976d042ae41e6400c037193cfed8e")) + (package! ivy-posframe :pin "44749562a9e68bd43ccaa225b31311476fab1251")) (when (featurep! +icons) (package! all-the-icons-ivy :pin "a70cbfa1effe36efc946a823a580cec686d5e88d")) From ff9c1ace22f821af4b18189b5db6b0a3ca1fb778 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 02:41:41 -0400 Subject: [PATCH 22/25] checkers/spell: replace flyspell with spell-fu Spell-fu is significantly faster, but does produce more false positives (more faces must be added to spell-fu-faces-exclude to reduce these). Unfortunately, there is no fancy "correction" interface for spell-fu yet, so we'll have to resort to ispell-word (on z=) for now. --- modules/checkers/spell/README.org | 89 ++++++++-------- modules/checkers/spell/autoload.el | 116 ++++++++++++++++---- modules/checkers/spell/config.el | 124 ++++++++++------------ modules/checkers/spell/packages.el | 9 +- modules/config/default/+emacs-bindings.el | 2 +- modules/config/default/+evil-bindings.el | 2 +- modules/lang/markdown/config.el | 2 - 7 files changed, 202 insertions(+), 142 deletions(-) diff --git a/modules/checkers/spell/README.org b/modules/checkers/spell/README.org index ae8b7e0e0..528e03586 100644 --- a/modules/checkers/spell/README.org +++ b/modules/checkers/spell/README.org @@ -11,76 +11,79 @@ - [[#prerequisites][Prerequisites]] - [[#features][Features]] - [[#configuration][Configuration]] + - [[#changing-how-quickly-spell-fu-spellchecks-after-changes][Changing how quickly spell-fu spellchecks after changes]] + - [[#reducing-false-positives-by-disabling-spelling-on-certain-faces][Reducing false positives by disabling spelling on certain faces]] + - [[#adding-or-removing-words-to-your-personal-dictionary][Adding or removing words to your personal dictionary]] - [[#troubleshooting][Troubleshooting]] * Description This modules provides spellchecking powered by =aspell= or =hunspell=. -Spellcheck is automatically loaded on the following modes: -+ org -+ markdown -+ TeX -+ rst -+ mu4e-compose -+ message -+ git-commit +Spellcheck is automatically loaded in all ~text-mode~ derivatives, which +includes ~org-mode~, ~markdown-mode~, the Git Commit buffer (from magit), +~mu4e-compose-mode~, and others. ** Maintainers This module has no dedicated maintainers. ** Module Flags -+ =+aspell= Use =aspell= as a backend for spellchecking. -+ =+hunspell= Use =hunspell= as a backend for spellchecking. -+ =+everywhere= Use spellcheck in every mode. ++ =+aspell= Use =aspell= as a backend for correcting words. ++ =+hunspell= Use =hunspell= as a backend for correcting words. ++ =+everywhere= Use spellcheck in prog-mode and conf-mode derivatives as well as + text-mode. Basically, enable =spell-fu-mode= everywhere. ** Plugins -+ [[https://github.com/d12frosted/flyspell-correct][flyspell-correct]] -+ [[https://github.com/d12frosted/flyspell-correct#flyspell-correct-ivy-interface][flyspell-correct-ivy]] (=completion/ivy=) -+ [[https://github.com/d12frosted/flyspell-correct#flyspell-correct-helm-interface][flyspell-correct-helm]] (=completion/helm=) -+ [[https://github.com/d12frosted/flyspell-correct#flyspell-correct-popup-interface][flyspell-correct-popup]] (if *neither* =completion/ivy= or =completion/helm=) -+ [[https://github.com/rolandwalker/flyspell-lazy][flyspell-lazy]] ++ [[https://gitlab.com/ideasman42/emacs-spell-fu][spell-fu]] * Prerequisites -This module requires either =aspell= or =hunspell= as backend. It will -automatically pick =aspell= if both are installed. +This module requires =aspell= to be installed, whether or not you intend to use +=hunspell= as the word correction backend. =spell-fu= does not yet support +generating the word list with a custom command or =hunspell=, but =hunspell= can +still be used to provide correction suggestions when invoking ~ispell-word~. -You can specify the backend with the =+aspell= or =+hunspell= flag. +You will need =hunspell= installed (via your OS package manager) to use it as a +correction backend. * Features -+ Spellchecking and suggestions based on =aspell= or =hunspell=. -+ Choosing suggestions using completion interfaces (=ivy= or =helm=). -+ Lazily spellchecking recent changes only when idle. -+ Ignores source code inside org documents. ++ Spellchecking based on =aspell=. ++ Spell correction using =aspell= or =hunspell= (through ~M-x ispell-word~). ++ Ignores source code inside org or markdown files. -When using =+everywhere=, =flyspell-prog-mode= will be automatically loaded for -the following modes: -+ yaml-mode-hook -+ conf-mode-hook -+ prog-mode-hook - -=flyspell-prog-mode= will only spellcheck comments. +When using =+everywhere=, ~spell-fu-mode~ is activated for as many major modes +as possible, and not only ~text-mode~ derivatives. =spell-fu= will only spell +check comments in programming major modes. * Configuration Dictionary is set by =ispell-dictionary= variable. Can be changed locally with the function =ispell-change-dictionary=. -Lazy spellcheck is provided by =flyspell-lazy= package. - -=flyspell-lazy-idle-seconds= sets how many idle seconds until spellchecking -recent changes (default as 1), while =flyspell-lazy-window-idle-seconds= sets -how many seconds until the whole window is spellchecked (default as 3). - -If you want to add =flyspell-mode= or =flyspell-prog-mode= to a specific mode, -use =add-hook!=. To remove from a mode, use =remove-hook!=: +** Changing how quickly spell-fu spellchecks after changes +Adjust ~spell-fu-idle-delay~ to change how long spell-fu waits to spellcheck +after recent changes (its default value as ~0.25~). #+BEGIN_SRC elisp -(add-hook! '(org-mode-hook markdown-mode-hook - git-commit-mode-hook) #'flyspell-mode) +(after! spell-fu + (setq spell-fu-idle-delay 0.5)) #+END_SRC +** Reducing false positives by disabling spelling on certain faces +Exclude what faces to not preform spellchecking on by setting +~spell-fu-faces-exclude~ in a buffer-local hook: + #+BEGIN_SRC elisp -(remove-hook! '(markdown-mode-hook git-commit-mode-hook) -#'flyspell-mode) +(setq-hook! 'markdown-mode-hook + spell-fu-faces-exclude '(markdown-code-face + markdown-reference-face + markdown-link-face + markdown-url-face + markdown-markup-face + markdown-html-attr-value-face + markdown-html-attr-name-face + markdown-html-tag-name-face)) #+END_SRC -* Troubleshooting +** Adding or removing words to your personal dictionary +Use ~M-x spell-fu-word-add~ and ~M-x spell-fu-word-remove~ to whitelist words +that you know are not misspellings. + +* TODO Troubleshooting diff --git a/modules/checkers/spell/autoload.el b/modules/checkers/spell/autoload.el index 0674dc5c1..d34f8624a 100644 --- a/modules/checkers/spell/autoload.el +++ b/modules/checkers/spell/autoload.el @@ -1,27 +1,99 @@ -;;; checkers/spell/autoload.el -*- lexical-binding: t; -*- +;;; checkers/spell/autoload/ivy.el -*- lexical-binding: t; -*- -;;;###autodef -(defalias 'flyspell-mode! #'flyspell-mode) +(defun +spell--correct (replace poss word orig-pt start end) + (cond ((eq replace 'ignore) + (goto-char orig-pt) + nil) + ((eq replace 'save) + (goto-char orig-pt) + (ispell-send-string (concat "*" word "\n")) + (ispell-send-string "#\n") + (setq ispell-pdict-modified-p '(t))) + ((or (eq replace 'buffer) (eq replace 'session)) + (ispell-send-string (concat "@" word "\n")) + (add-to-list 'ispell-buffer-session-localwords word) + (or ispell-buffer-local-name ; session localwords might conflict + (setq ispell-buffer-local-name (buffer-name))) + (if (null ispell-pdict-modified-p) + (setq ispell-pdict-modified-p + (list ispell-pdict-modified-p))) + (goto-char orig-pt) + (if (eq replace 'buffer) + (ispell-add-per-file-word-list word))) + (replace + (let ((new-word (if (atom replace) + replace + (car replace))) + (orig-pt (+ (- (length word) (- end start)) + orig-pt))) + (unless (equal new-word (car poss)) + (delete-region start end) + (goto-char start) + (insert new-word)))) + ((goto-char orig-pt) + nil))) -(defvar +spell--flyspell-predicate-alist nil - "TODO") +(defun +spell-correct-ivy-fn (candidates word) + (ivy-read (format "Corrections for %S: " word) candidates)) -;;;###autodef -(defun set-flyspell-predicate! (modes predicate) - "TODO" - (declare (indent defun)) - (dolist (mode (doom-enlist modes) +spell--flyspell-predicate-alist) - (add-to-list '+spell--flyspell-predicate-alist (cons mode predicate)))) +(defun +spell-correct-helm-fn (candidates word) + (helm :sources (helm-build-sync-source + "Ispell" + :candidates candidates) + :prompt (format "Corrections for %S: " word))) + +(defun +spell-correct-generic-fn (candidates word) + (completing-read (format "Corrections for %S: " word) candidates)) ;;;###autoload -(defun +spell-init-flyspell-predicate-h () - "TODO" - (when-let (pred (assq major-mode +spell--flyspell-predicate-alist)) - (setq-local flyspell-generic-check-word-predicate (cdr pred)))) - -;;;###autoload -(defun +spell-correction-at-point-p (&optional point) - "TODO" - (cl-loop for ov in (overlays-at (or point (point))) - if (overlay-get ov 'flyspell-overlay) - return t)) +(defun +spell/correct () + "Correct spelling of word at point." + (interactive) + (if (not (or (featurep! :completion ivy) + (featurep! :completion helm))) + (call-interactively #'ispell-word) + (cl-destructuring-bind (start . end) + (bounds-of-thing-at-point 'word) + (let ((word (thing-at-point 'word t)) + (orig-pt (point)) + poss ispell-filter) + (save-current-buffer + (ispell-accept-buffer-local-defs)) + (ispell-send-string "%\n") + (ispell-send-string (concat "^" word "\n")) + (while (progn (accept-process-output ispell-process) + (not (string= "" (car ispell-filter))))) + ;; Remove leading empty element + (setq ispell-filter (cdr ispell-filter)) + ;; ispell process should return something after word is sent. Tag word as + ;; valid (i.e., skip) otherwise + (unless ispell-filter + (setq ispell-filter '(*))) + (when (consp ispell-filter) + (setq poss (ispell-parse-output (car ispell-filter)))) + (cond + ((or (eq poss t) (stringp poss)) + ;; don't correct word + (message "%s is correct" (funcall ispell-format-word-function word)) + t) + ((null poss) + ;; ispell error + (error "Ispell: error in Ispell process")) + (t + ;; The word is incorrect, we have to propose a replacement. + (setq res (funcall +spell-correct-interface (nth 2 poss) word)) + ;; Some interfaces actually eat 'C-g' so it's impossible to stop rapid + ;; mode. So when interface returns nil we treat it as a stop. + (unless res (setq res (cons 'break word))) + (cond + ((stringp res) + (+spell--correct res poss word orig-pt start end)) + ((let ((cmd (car res)) + (wrd (cdr res))) + (unless (or (eq cmd 'skip) + (eq cmd 'break) + (eq cmd 'stop)) + (+spell--correct cmd poss wrd orig-pt start end) + (unless (string-equal wrd word) + (+spell--correct wrd poss word orig-pt start end)))))) + (ispell-pdict-save t))))))) diff --git a/modules/checkers/spell/config.el b/modules/checkers/spell/config.el index ba00281b8..4578a3f5e 100644 --- a/modules/checkers/spell/config.el +++ b/modules/checkers/spell/config.el @@ -1,7 +1,54 @@ ;;; checkers/spell/config.el -*- lexical-binding: t; -*- -(defvar ispell-dictionary "en_US") +(defvar +spell-correct-interface + (cond ((featurep! :completion ivy) + #'+spell-correct-ivy-fn) + ((featurep! :completion helm) + #'+spell-correct-helm-fn) + (#'+spell-correct-generic-fn)) + "Function to use to display corrections.") +(defvar +spell-excluded-faces-alist + '((markdown-mode + . (markdown-code-face + markdown-html-attr-name-face + markdown-html-attr-value-face + markdown-html-tag-name-face + markdown-link-face + markdown-markup-face + markdown-reference-face + markdown-url-face)) + (org-mode + . (org-block + org-block-begin-line + org-block-end-line + org-code + org-date + org-formula + org-latex-and-related + org-link + org-meta-line + org-property-value + org-ref-cite-face + org-special-keyword + org-tag + org-todo + org-todo-keyword-done + org-todo-keyword-habt + org-todo-keyword-kill + org-todo-keyword-outd + org-todo-keyword-todo + org-todo-keyword-wait + org-verbatim))) + "Faces in certain major modes that spell-fu will not spellcheck.") + + +;; +;;; Packages + +(global-set-key [remap ispell-word] #'+spell/correct) + +(defvar ispell-dictionary "en_US") (after! ispell ;; Don't spellcheck org blocks (pushnew! ispell-skip-region-alist @@ -39,74 +86,21 @@ (_ (doom-log "Spell checker not found. Either install `aspell' or `hunspell'")))) -(use-package! flyspell ; built-in - :defer t - :preface - ;; `flyspell' is loaded at startup. In order to lazy load its config we need - ;; to pretend it isn't loaded. - (defer-feature! flyspell flyspell-mode flyspell-prog-mode) +(use-package! spell-fu + :hook (text-mode . spell-fu-mode) :init - (add-hook! '(org-mode-hook - markdown-mode-hook - TeX-mode-hook - rst-mode-hook - mu4e-compose-mode-hook - message-mode-hook - git-commit-mode-hook) - #'flyspell-mode) - + (setq spell-fu-directory (concat doom-etc-dir "spell-fu")) (when (featurep! +everywhere) (add-hook! '(yaml-mode-hook conf-mode-hook prog-mode-hook) - #'flyspell-prog-mode)) - + #'spell-fu-mode)) :config - (setq flyspell-issue-welcome-flag nil - ;; Significantly speeds up flyspell, which would otherwise print - ;; messages for every word when checking the entire buffer - flyspell-issue-message-flag nil) + (add-hook! 'spell-fu-mode-hook + (defun +spell-init-excluded-faces-h () + (when-let (excluded (alist-get major-mode +spell-excluded-faces-alist)) + (setq-local spell-fu-faces-exclude excluded)))) - (add-hook! 'flyspell-mode-hook - (defun +spell-inhibit-duplicate-detection-maybe-h () - "Don't mark duplicates when style/grammar linters are present. -e.g. proselint and langtool." - (and (or (and (bound-and-true-p flycheck-mode) - (executable-find "proselint")) - (featurep 'langtool)) - (setq-local flyspell-mark-duplications-flag nil)))) - - ;; Ensure mode-local predicates declared with `set-flyspell-predicate!' are - ;; used in their respective major modes. - (add-hook 'flyspell-mode-hook #'+spell-init-flyspell-predicate-h) - - (let ((flyspell-correct - (general-predicate-dispatch nil - (and (not (or mark-active (ignore-errors (evil-insert-state-p)))) - (memq 'flyspell-incorrect (face-at-point nil t))) - #'flyspell-correct-at-point))) - (map! :map flyspell-mouse-map - "RET" flyspell-correct - [return] flyspell-correct - [mouse-1] #'flyspell-correct-at-point))) - - -(use-package! flyspell-correct - :commands flyspell-correct-previous - :general ([remap ispell-word] #'flyspell-correct-at-point) - :config - (cond ((and (featurep! :completion helm) - (require 'flyspell-correct-helm nil t))) - ((and (featurep! :completion ivy) - (require 'flyspell-correct-ivy nil t))) - ((require 'flyspell-correct-popup nil t) - (setq flyspell-popup-correct-delay 0.8) - (define-key popup-menu-keymap [escape] #'keyboard-quit)))) - - -(use-package! flyspell-lazy - :after flyspell - :config - (setq flyspell-lazy-idle-seconds 1 - flyspell-lazy-window-idle-seconds 3) - (flyspell-lazy-mode +1)) + ;; TODO custom `spell-fu-check-range' function to exclude URLs from links or + ;; org-src blocks more intelligently. + ) diff --git a/modules/checkers/spell/packages.el b/modules/checkers/spell/packages.el index 121a8ec08..595724a29 100644 --- a/modules/checkers/spell/packages.el +++ b/modules/checkers/spell/packages.el @@ -1,11 +1,4 @@ ;; -*- no-byte-compile: t; -*- ;;; checkers/spell/packages.el -(package! flyspell-correct :pin "dea1290a371c540dde7b8d0eef7a12d92f7a0b83") -(cond ((featurep! :completion ivy) - (package! flyspell-correct-ivy)) - ((featurep! :completion helm) - (package! flyspell-correct-helm)) - ((package! flyspell-correct-popup))) - -(package! flyspell-lazy :pin "3ebf68cc9eb10c972a2de8d7861cbabbbce69570") +(package! spell-fu :pin "e94d01cdc822e02968971cde09276047a5d55772") diff --git a/modules/config/default/+emacs-bindings.el b/modules/config/default/+emacs-bindings.el index b66c29df1..c9579e258 100644 --- a/modules/config/default/+emacs-bindings.el +++ b/modules/config/default/+emacs-bindings.el @@ -280,7 +280,7 @@ :desc "org-tree-slide mode" "p" #'org-tree-slide-mode) :desc "Read-only mode" "r" #'read-only-mode (:when (featurep! :checkers spell) - :desc "Flyspell" "s" #'flyspell-mode) + :desc "Spell checker" "s" #'spell-fu-mode) (:when (featurep! :lang org +pomodoro) :desc "Pomodoro timer" "t" #'org-pomodoro) (:when (featurep! :ui zen) diff --git a/modules/config/default/+evil-bindings.el b/modules/config/default/+evil-bindings.el index 4e5e09dc1..35adb0e4a 100644 --- a/modules/config/default/+evil-bindings.el +++ b/modules/config/default/+evil-bindings.el @@ -662,7 +662,7 @@ :desc "org-tree-slide mode" "p" #'org-tree-slide-mode) :desc "Read-only mode" "r" #'read-only-mode (:when (featurep! :checkers spell) - :desc "Flyspell" "s" #'flyspell-mode) + :desc "Spell checker" "s" #'spell-fu-mode) (:when (featurep! :lang org +pomodoro) :desc "Pomodoro timer" "t" #'org-pomodoro) :desc "Soft line wrapping" "w" #'visual-line-mode diff --git a/modules/lang/markdown/config.el b/modules/lang/markdown/config.el index d82e396db..9f50dcd80 100644 --- a/modules/lang/markdown/config.el +++ b/modules/lang/markdown/config.el @@ -53,8 +53,6 @@ capture, the end position, and the output buffer.") (add-to-list 'org-src-lang-modes '("md" . markdown))) :config - (set-flyspell-predicate! '(markdown-mode gfm-mode) - #'+markdown-flyspell-word-p) (set-lookup-handlers! '(markdown-mode gfm-mode) ;; `markdown-follow-thing-at-point' may open an external program or a ;; buffer. No good way to tell, so pretend it's async. From d5e64d0586f52475654856038a12dc07f91e0cbb Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 03:01:15 -0400 Subject: [PATCH 23/25] Add zq, zw, ]s and [s keybinds for spell-fu These are canonical vim keybinds for interacting with the dictionary and navigating spelling errors. --- modules/editor/evil/config.el | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/editor/evil/config.el b/modules/editor/evil/config.el index 229801bee..9e676e2c5 100644 --- a/modules/editor/evil/config.el +++ b/modules/editor/evil/config.el @@ -376,16 +376,17 @@ directives. By default, this only recognizes C directives.") ;;; Keybinds ;; Keybinds that have no Emacs+evil analogues (i.e. don't exist): -;; zq - mark word at point as good word -;; zw - mark word at point as bad ;; zu{q,w} - undo last marking -;; Keybinds that evil define: -;; z= - correct flyspell word at point -;; ]s - jump to previous spelling error -;; [s - jump to next spelling error (map! :v "@" #'+evil:apply-macro + ;; implement dictionary keybinds + ;; evil already defines 'z=' to `ispell-word' = correct word at point + :n "zq" #'spell-fu-word-add + :n "zw" #'spell-fu-word-remove + :n "[s" #'spell-fu-goto-previous-error + :n "]s" #'spell-fu-goto-next-error + ;; ported from vim-unimpaired :n "] SPC" #'+evil/insert-newline-below :n "[ SPC" #'+evil/insert-newline-above From e86ecf60c98e2461305c129af9aa3139e9d81635 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 19:08:46 -0400 Subject: [PATCH 24/25] lang/org: optimize org-agenda (part 2) #2672 --- modules/lang/org/config.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index ec98b0f82..e933357b6 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -598,7 +598,9 @@ buffers." (defadvice! +org--exclude-agenda-buffers-from-recentf-a (orig-fn file) "Prevent temporarily opened agenda buffers from polluting recentf." :around #'org-get-agenda-file-buffer - (let ((recentf-exclude (list (lambda (_file) t)))) + (let ((recentf-exclude (list (lambda (_file) t))) + (doom-large-file-p t) + find-file-hook) (funcall orig-fn file))) ;; HACK With https://code.orgmode.org/bzg/org-mode/commit/48da60f4, inline From 4209454df36e5e0864bbb14110f0ac3dac86f441 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 21 Aug 2020 19:16:56 -0400 Subject: [PATCH 25/25] lang/org: optimize org-agenda (part 3) #2672 --- modules/lang/org/config.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index e933357b6..2f5202050 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -600,7 +600,8 @@ buffers." :around #'org-get-agenda-file-buffer (let ((recentf-exclude (list (lambda (_file) t))) (doom-large-file-p t) - find-file-hook) + find-file-hook + org-mode-hook) (funcall orig-fn file))) ;; HACK With https://code.orgmode.org/bzg/org-mode/commit/48da60f4, inline