diff --git a/lisp/doom-editor.el b/lisp/doom-editor.el index a6c23f051..98acb5b62 100644 --- a/lisp/doom-editor.el +++ b/lisp/doom-editor.el @@ -604,8 +604,6 @@ current buffer." :hook (doom-first-buffer . smartparens-global-mode) :commands sp-pair sp-local-pair sp-with-modes sp-point-in-comment sp-point-in-string :config - (add-to-list 'doom-point-in-string-functions 'sp-point-in-string) - (add-to-list 'doom-point-in-comment-functions 'sp-point-in-comment) ;; smartparens recognizes `slime-mrepl-mode', but not `sly-mrepl-mode', so... (add-to-list 'sp-lisp-modes 'sly-mrepl-mode) ;; Load default smartparens rules for various languages diff --git a/lisp/doom-start.el b/lisp/doom-start.el index 20eec39b5..64f3146e0 100644 --- a/lisp/doom-start.el +++ b/lisp/doom-start.el @@ -163,7 +163,12 @@ (defun doom-run-local-var-hooks-h () "Run MODE-local-vars-hook after local variables are initialized." - (unless (or doom-inhibit-local-var-hooks delay-mode-hooks) + (unless (or doom-inhibit-local-var-hooks + delay-mode-hooks + ;; Don't trigger local-vars hooks in temporary (internal) buffers + (string-prefix-p + " " (buffer-name (or (buffer-base-buffer) + (current-buffer))))) (setq-local doom-inhibit-local-var-hooks t) (doom-run-hooks (intern-soft (format "%s-local-vars-hook" major-mode))))) diff --git a/lisp/doom-ui.el b/lisp/doom-ui.el index 7ef918cfa..6f4aa5eee 100644 --- a/lisp/doom-ui.el +++ b/lisp/doom-ui.el @@ -302,6 +302,10 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original (setq use-short-answers t) ;; DEPRECATED: Remove when we drop 27.x support (advice-add #'yes-or-no-p :override #'y-or-n-p)) +;; HACK: By default, SPC = yes when `y-or-n-p' prompts you (and +;; `y-or-n-p-use-read-key' is off). This seems too easy to hit by accident, +;; especially with SPC as our default leader key. +(define-key y-or-n-p-map " " nil) ;; Try to keep the cursor out of the read-only portions of the minibuffer. (setq minibuffer-prompt-properties '(read-only t intangible t cursor-intangible t face minibuffer-prompt)) diff --git a/lisp/lib/help.el b/lisp/lib/help.el index b25962f09..b61a5f29b 100644 --- a/lisp/lib/help.el +++ b/lisp/lib/help.el @@ -355,9 +355,8 @@ without needing to check if they are available." (defun doom--help-current-module-str () (cond ((save-excursion - (require 'smartparens) (ignore-errors - (sp-beginning-of-sexp) + (thing-at-point--beginning-of-sexp) (unless (eq (char-after) ?\() (backward-char)) (let ((sexp (sexp-at-point))) diff --git a/lisp/lib/plist.el b/lisp/lib/plist.el index d50c01423..15c4133cd 100644 --- a/lisp/lib/plist.el +++ b/lisp/lib/plist.el @@ -29,9 +29,10 @@ ;;;###autoload (defun doom-plist-merge (from-plist to-plist) "Non-destructively merge FROM-PLIST onto TO-PLIST" - (let ((plist (copy-sequence from-plist))) - (while plist - (cl-callf plist-put to-plist (pop plist) (pop plist))) + (let ((from-plist (copy-sequence from-plist)) + (to-plist (copy-sequence to-plist))) + (while from-plist + (cl-callf plist-put to-plist (pop from-plist) (pop from-plist))) to-plist)) ;;;###autoload diff --git a/lisp/lib/text.el b/lisp/lib/text.el index cef1a098b..dc00d2e45 100644 --- a/lisp/lib/text.el +++ b/lisp/lib/text.el @@ -1,18 +1,32 @@ ;;; lisp/lib/text.el -*- lexical-binding: t; -*- -;;;###autoload -(defvar doom-point-in-comment-functions () - "List of functions to run to determine if point is in a comment. +(defvar-local doom--sppss-memo-last-point nil) +(defvar-local doom--sppss-memo-last-result nil) -Each function takes one argument: the position of the point. Stops on the first -function to return non-nil. Used by `doom-point-in-comment-p'.") +(defun doom--sppss-memo-reset-h (&rest _ignored) + "Reset memoization as a safety precaution. + +IGNORED is a dummy argument used to eat up arguments passed from +the hook where this is executed." + (setq doom--sppss-memo-last-point nil + doom--sppss-memo-last-result nil)) ;;;###autoload -(defvar doom-point-in-string-functions () - "List of functions to run to determine if point is in a string. +(defun doom-syntax-ppss (&optional p) + "Memoize the last result of `syntax-ppss'. -Each function takes one argument: the position of the point. Stops on the first -function to return non-nil. Used by `doom-point-in-string-p'.") +P is the point at which we run `syntax-ppss'" + (let ((p (or p (point))) + (mem-p doom--sppss-memo-last-point)) + (if (and (eq p (nth 0 mem-p)) + (eq (point-min) (nth 1 mem-p)) + (eq (point-max) (nth 2 mem-p))) + doom--sppss-memo-last-result + ;; Add hook to reset memoization if necessary + (unless doom--sppss-memo-last-point + (add-hook 'before-change-functions #'doom--sppss-memo-reset-h t t)) + (setq doom--sppss-memo-last-point (list p (point-min) (point-max)) + doom--sppss-memo-last-result (syntax-ppss p))))) ;;;###autoload (defun doom-surrounded-p (pair &optional inline balanced) @@ -40,22 +54,49 @@ lines, above and below, with only whitespace in between." (= (- pt nbeg) (- nend pt)))))))))))) ;;;###autoload -(defun doom-point-in-comment-p (&optional pos) - "Return non-nil if POS is in a comment. -POS defaults to the current position." - (let ((pos (or pos (point)))) - (if doom-point-in-comment-functions - (run-hook-with-args-until-success 'doom-point-in-comment-functions pos) - (nth 4 (syntax-ppss pos))))) +(defun doom-point-in-comment-p (&optional pt) + "Return non-nil if point is in a comment. +PT defaults to the current position." + (let ((pt (or pt (point)))) + (ignore-errors + (save-excursion + ;; We cannot be in a comment if we are inside a string + (unless (nth 3 (doom-syntax-ppss pt)) + (or (nth 4 (doom-syntax-ppss pt)) + ;; this also test opening and closing comment delimiters... we + ;; need to chack that it is not newline, which is in "comment + ;; ender" class in elisp-mode, but we just want it to be treated + ;; as whitespace + (and (< pt (point-max)) + (memq (char-syntax (char-after pt)) '(?< ?>)) + (not (eq (char-after pt) ?\n))) + ;; we also need to test the special syntax flag for comment + ;; starters and enders, because `syntax-ppss' does not yet know if + ;; we are inside a comment or not (e.g. / can be a division or + ;; comment starter...). + (when-let ((s (car (syntax-after pt)))) + (or (and (/= 0 (logand (ash 1 16) s)) + (nth 4 (syntax-ppss (+ pt 2)))) + (and (/= 0 (logand (ash 1 17) s)) + (nth 4 (syntax-ppss (+ pt 1)))) + (and (/= 0 (logand (ash 1 18) s)) + (nth 4 (syntax-ppss (- pt 1)))) + (and (/= 0 (logand (ash 1 19) s)) + (nth 4 (syntax-ppss (- pt 2)))))))))))) ;;;###autoload -(defun doom-point-in-string-p (&optional pos) - "Return non-nil if POS is in a string." - ;; REVIEW Should we cache `syntax-ppss'? - (let ((pos (or pos (point)))) - (if doom-point-in-string-functions - (run-hook-with-args-until-success 'doom-point-in-string-functions pos) - (nth 3 (syntax-ppss pos))))) +(defun doom-point-in-string-p (&optional pt) + "Return non-nil if point is inside string. + +This function actually returns the 3rd element of `syntax-ppss' +which can be a number if the string is delimited by that +character or t if the string is delimited by general string +fences. + +If optional argument PT is present test this instead of point." + (ignore-errors + (save-excursion + (nth 3 (doom-syntax-ppss pt))))) ;;;###autoload (defun doom-point-in-string-or-comment-p (&optional pos) diff --git a/lisp/lib/themes.el b/lisp/lib/themes.el index 9af956e65..262db832f 100644 --- a/lisp/lib/themes.el +++ b/lisp/lib/themes.el @@ -6,13 +6,17 @@ (add-hook! 'doom-load-theme-hook (defun doom-apply-customized-faces-h () "Run `doom-customize-theme-hook'." - (run-hooks 'doom-customize-theme-hook))) + (letf! ((#'custom--should-apply-setting #'ignore) + (defun custom-push-theme (prop symbol theme mode &optional value) + (funcall custom-push-theme prop symbol theme mode value) + (if (facep symbol) (face-spec-set symbol value t)))) + (run-hooks 'doom-customize-theme-hook)))) -(defun doom--custom-theme-set-face (spec) +(defun doom--normalize-face-spec (spec) (cond ((listp (car spec)) (cl-loop for face in (car spec) collect - (car (doom--custom-theme-set-face (cons face (cdr spec)))))) + (car (doom--normalize-face-spec (cons face (cdr spec)))))) ((keywordp (cadr spec)) `((,(car spec) ((t ,(cdr spec)))))) (`((,(car spec) ,(cdr spec)))))) @@ -27,13 +31,12 @@ all themes. It will apply to all themes once they are loaded." (let ((fn (gensym "doom--customize-themes-h-"))) `(progn (defun ,fn () - (let (custom--inhibit-theme-enable) - (dolist (theme (ensure-list (or ,theme 'user))) - (when (or (eq theme 'user) - (custom-theme-enabled-p theme)) + (dolist (theme (ensure-list (or ,theme 'user))) + (if (or (eq theme 'user) + (custom-theme-enabled-p theme)) (apply #'custom-theme-set-faces theme - (mapcan #'doom--custom-theme-set-face - (list ,@specs))))))) + (mapcan #'doom--normalize-face-spec + (list ,@specs)))))) ;; Apply the changes immediately if the user is using the default theme ;; or the theme has already loaded. This allows you to evaluate these ;; macros on the fly and customize your faces iteratively. diff --git a/modules/completion/ivy/config.el b/modules/completion/ivy/config.el index e537abf81..308e29708 100644 --- a/modules/completion/ivy/config.el +++ b/modules/completion/ivy/config.el @@ -211,6 +211,21 @@ results buffer.") (when (stringp counsel-rg-base-command) (setq counsel-rg-base-command (split-string counsel-rg-base-command))) + ;; REVIEW: See abo-abo/swiper#2339. + (defadvice! +counsel-rg-suppress-error-code-a (fn &rest args) + "Ripgrep returns a non-zero exit code if it encounters any trouble (e.g. you +don't have the needed permissions for a couple files/directories in a project). +Even if rg continues to produce workable results, that non-zero exit code causes +counsel-rg to discard the rest of the output to display an error. + +This advice suppresses the error code, so you can still operate on whatever +workable results ripgrep produces, despite the error." + :around #'counsel-rg + (letf! (defun process-exit-status (proc) + (let ((code (funcall process-exit-status proc))) + (if (= code 2) 0 code))) + (apply fn args))) + ;; Integrate with `helpful' (setq counsel-describe-function-function #'helpful-callable counsel-describe-variable-function #'helpful-variable diff --git a/modules/editor/evil/autoload/advice.el b/modules/editor/evil/autoload/advice.el index eecd72153..1cf4e5aa4 100644 --- a/modules/editor/evil/autoload/advice.el +++ b/modules/editor/evil/autoload/advice.el @@ -78,10 +78,9 @@ more information on modifiers." (defun +evil--insert-newline (&optional above _noextranewline) (let ((pos (save-excursion (beginning-of-line-text) (point))) comment-auto-fill-only-comments) - (require 'smartparens) (evil-narrow-to-field (if above - (if (save-excursion (nth 4 (sp--syntax-ppss pos))) + (if (save-excursion (nth 4 (doom-syntax-ppss pos))) (evil-save-goal-column (setq evil-auto-indent nil) (goto-char pos) @@ -103,7 +102,7 @@ more information on modifiers." (forward-line -1) (back-to-indentation)) (evil-move-end-of-line) - (cond ((sp-point-in-comment pos) + (cond ((doom-point-in-comment-p pos) (setq evil-auto-indent nil) (if comment-line-break-function (funcall comment-line-break-function nil) diff --git a/modules/editor/evil/autoload/embrace.el b/modules/editor/evil/autoload/embrace.el index 6090112ea..cf1c6a925 100644 --- a/modules/editor/evil/autoload/embrace.el +++ b/modules/editor/evil/autoload/embrace.el @@ -18,7 +18,7 @@ (if (eq char 27) (cons "" "") (let* ((pair (+evil--embrace-get-pair (string char))) - (escape (if (sp-point-in-string) "\\\\" "\\")) + (escape (if (doom-point-in-string-p) "\\\\" "\\")) (escape (format "\\1%s" (regexp-quote escape)))) (cons (replace-regexp-in-string "^\\( *\\)" escape (car pair)) (replace-regexp-in-string "^\\( *\\)" escape (cdr pair))))))) diff --git a/modules/editor/evil/autoload/unimpaired.el b/modules/editor/evil/autoload/unimpaired.el index b698b56ea..04100f35c 100644 --- a/modules/editor/evil/autoload/unimpaired.el +++ b/modules/editor/evil/autoload/unimpaired.el @@ -57,13 +57,13 @@ See `+evil/next-preproc-directive' for details." (require 'newcomment) (dotimes (_ (abs count)) (cond ((> count 0) - (while (and (not (eobp)) (sp-point-in-comment)) + (while (and (not (eobp)) (doom-point-in-comment-p)) (forward-line 1)) (unless (comment-search-forward (point-max) 'noerror) (goto-char orig-pt) (user-error "No comment after point"))) (t - (while (and (not (bobp)) (sp-point-in-comment)) + (while (and (not (bobp)) (doom-point-in-comment-p)) (forward-line -1)) (unless (comment-search-backward nil 'noerror) (goto-char orig-pt) diff --git a/modules/editor/evil/init.el b/modules/editor/evil/init.el index f9b1f2924..0c0a89b76 100644 --- a/modules/editor/evil/init.el +++ b/modules/editor/evil/init.el @@ -359,4 +359,13 @@ and complains if a module is loaded too early (during startup)." (dolist (mode evil-collection-mode-list) (dolist (req (or (cdr-safe mode) (list mode))) (with-eval-after-load req - (+evil-collection-init mode +evil-collection-disabled-list)))))) + (+evil-collection-init mode +evil-collection-disabled-list))))) + + ;; HACK: The Diff options in `save-some-buffers's prompt should persist after + ;; you quit view-mode, but evil-collection-view's bindings on q/Q break + ;; this, so these are here to restore them. + ;; REVIEW: PR this upstream! + (map! :after (view evil-collection-view) + :map view-mode-map + :n "q" #'View-quit + :n "Q" #'View-quit-all)) diff --git a/modules/editor/format/README.org b/modules/editor/format/README.org index 1f3b32e52..0d8e812c0 100644 --- a/modules/editor/format/README.org +++ b/modules/editor/format/README.org @@ -42,6 +42,8 @@ be formatted and returned to the buffer using works in many cases, but makes no guarantees that it will work with all formatters. Lisp, Scheme, Python, or similarly indentation-based languages are most likely to see strange results. +- [[fn:save-buffer]] is advised to suppress format-on-save behavior if passed the + universal argument (e.g. [[kbd:SPC u SPC b s]] or [[kbd:C-u C-x C-s]]). ** TODO Changelog # This section will be machine generated. Don't edit it by hand. @@ -176,7 +178,7 @@ enabled, and the running server supports =textDocument/formatting= or =textDocument/rangeFormatting=, it can be used instead of [[doom-package:apheleia]]'s (or Doom's) default formatters by enabling this module with its =+lsp= flag or manually activating the [[fn:+format-with-lsp-mode]] minor -mode (though it's a better idea to use [[fn:+format-with-lsp-maybe-h]] if you're +mode (though it's a better idea to use [[fn:+format-with-lsp-toggle-h]] if you're looking for a function to use with mode hooks; this function will respect pre-existing modifications to [[var:+format-with]]). diff --git a/modules/editor/format/autoload/lsp.el b/modules/editor/format/autoload/lsp.el index 0235b0763..b319478f7 100644 --- a/modules/editor/format/autoload/lsp.el +++ b/modules/editor/format/autoload/lsp.el @@ -44,9 +44,9 @@ mode unconditionally, call `+format-with-lsp-mode' instead." ;;; Apheleia formatters ;;;###autoload -(cl-defun +format-lsp-buffer (&rest plist &key callback &allow-other-keys) +(cl-defun +format-lsp-buffer (&rest plist &key buffer callback &allow-other-keys) "Format the current buffer with any available lsp-mode or eglot formatter." - (if-let* ((fn (+format--lsp-fn)) + (if-let* ((fn (with-current-buffer buffer (+format--lsp-fn))) ((apply fn plist))) (funcall callback) (funcall callback "LSP server doesn't support formatting"))) diff --git a/modules/editor/format/config.el b/modules/editor/format/config.el index bef0b8737..d0658a5f1 100644 --- a/modules/editor/format/config.el +++ b/modules/editor/format/config.el @@ -37,8 +37,8 @@ This is controlled by `+format-on-save-disabled-modes'." ;; Use the formatter provided by lsp-mode and eglot, if available. (when (modulep! +lsp) - (add-hook 'eglot-managed-mode-hook #'+format-with-lsp-maybe-h) - (add-hook 'lsp-managed-mode-hook #'+format-with-lsp-maybe-h)) + (add-hook 'eglot-managed-mode-hook #'+format-with-lsp-toggle-h) + (add-hook 'lsp-managed-mode-hook #'+format-with-lsp-toggle-h)) :config (add-to-list 'doom-debug-variables '(apheleia-log-only-errors . nil)) diff --git a/modules/lang/latex/README.org b/modules/lang/latex/README.org index 7de0b851b..8edf9c52d 100644 --- a/modules/lang/latex/README.org +++ b/modules/lang/latex/README.org @@ -27,8 +27,6 @@ Provide a helping hand when working with LaTeX documents. - +fold :: Use TeX-fold (from [[doom-package:auctex]]) to fold LaTeX macros to unicode, and make folding hook-based and less manual. -- +latexmk :: - Use LatexMk instead of LaTeX to compile documents. - +lsp :: Enable LSP support in latex buffers. Requires [[doom-module::tools lsp]] and a langserver (supports digestif and TexLab). @@ -36,7 +34,6 @@ Provide a helping hand when working with LaTeX documents. ** Packages - [[doom-package:adaptive-wrap]] - [[doom-package:auctex]] -- [[doom-package:auctex-latexmk]] if [[doom-module:+latexmk]] - [[doom-package:cdlatex]] if [[doom-module:+cdlatex]] - [[doom-package:evil-tex]] if [[doom-module::editor evil +everywhere]] - [[doom-package:latex-preview-pane]] diff --git a/modules/lang/latex/config.el b/modules/lang/latex/config.el index c24273487..65a07f42c 100644 --- a/modules/lang/latex/config.el +++ b/modules/lang/latex/config.el @@ -250,19 +250,6 @@ Math faces should stay fixed by the mixed-pitch blacklist, this is mostly for :init (setq-default adaptive-wrap-extra-indent 0)) -(use-package! auctex-latexmk - :when (modulep! +latexmk) - :after latex - :init - ;; Pass the -pdf flag when TeX-PDF-mode is active. - (setq auctex-latexmk-inherit-TeX-PDF-mode t) - ;; Set LatexMk as the default. - (setq-hook! LaTeX-mode TeX-command-default "LatexMk") - :config - ;; Add LatexMk as a TeX target. - (auctex-latexmk-setup)) - - (use-package! evil-tex :when (modulep! :editor evil +everywhere) :hook (LaTeX-mode . evil-tex-mode)) diff --git a/modules/lang/latex/packages.el b/modules/lang/latex/packages.el index 61ab4ce0d..26d7b48fb 100644 --- a/modules/lang/latex/packages.el +++ b/modules/lang/latex/packages.el @@ -3,18 +3,47 @@ (package! auctex :recipe (:files ("*.el" "*.info" "dir" - "doc" "etc" "images" "latex" "style")) - :pin "280cd4a0ca5a9c80e67efc2bec354b3052258e8d") -(package! adaptive-wrap :pin "a3b179ea21aeb4e8cfaf5646bb66d9d045263780") + "doc" "etc" "images" "latex" "style") + ;; HACK: Auctex has a post-install step that generates tex-site.el + ;; and *.texi documentation files, which largely assumes the user + ;; is on a Linux system with various shell tools like sed, gnu + ;; make, tex, etc. -- an assumption I can't safely make about + ;; Doom's users, so reinvent its 'make tex-site.el' task in elisp: + :pre-build + (with-temp-file "tex-site.el" + (insert-file-contents "tex-site.el.in") + (while (re-search-forward "@\\(\\(?:AUCTEX\\|lisp\\)[^@]+\\)@" nil t) + (pcase (match-string 1) + ("AUCTEXVERSION" + (replace-match (with-temp-buffer + (insert-file-contents "auctex.el" nil 0 1024) + (save-match-data + (if (re-search-forward "^;; Version: \\([^\n-]+\\)" nil t) + (match-string-no-properties 1) + "Unknown"))) + t t)) + ("AUCTEXDATE" + (when-let* ((time (cdr (doom-call-process "git" "log" "-n1" "--pretty=tformat:%ct"))) + (time (string-to-number time))) + (replace-match (format-time-string "%Y-%m-%d %T" time) t t))) + ("lispautodir" + (replace-match + (prin1-to-string + `(if (file-writable-p "/usr/local/var/auctex") + "/usr/local/var/auctex" + ,(file-name-concat doom-data-dir "auctex"))) + t t)) + ((or "lisppackagedatadir" "lisppackagelispdir") + (replace-match "(directory-file-name (file-name-directory load-file-name))" t t)) + (it (error "Unknown substitution variable in tex-site.el.in: %s" it)))))) + :pin "764a53c8e93150f0edd169593a4d453810792abe") +(package! adaptive-wrap :pin "dea4e32c18d285a6ca9f72b1eadd61e27a555ed3") (package! latex-preview-pane :pin "5297668a89996b50b2b62f99cba01cc544dbed2e") (when (modulep! :editor evil +everywhere) (package! evil-tex :pin "2a3177c818f106e6c11032ac261f8691f5e11f74")) ;; Optional module features. -(when (modulep! +latexmk) - (package! auctex-latexmk :pin "b00a95e6b34c94987fda5a57c20cfe2f064b1c7a")) - (when (modulep! +cdlatex) (package! cdlatex :pin "33770dec73138909714711b05a63e79da5a19ccd")) diff --git a/modules/lang/markdown/config.el b/modules/lang/markdown/config.el index cad315f38..63d5bd0f0 100644 --- a/modules/lang/markdown/config.el +++ b/modules/lang/markdown/config.el @@ -23,6 +23,7 @@ capture, the end position, and the output buffer.") markdown-gfm-additional-languages '("sh") markdown-make-gfm-checkboxes-buttons t markdown-fontify-whole-heading-line t + markdown-fontify-code-blocks-natively t ;; `+markdown-compile' offers support for many transpilers (see ;; `+markdown-compile-functions'), which it tries until one succeeds. @@ -46,10 +47,6 @@ capture, the end position, and the output buffer.") "" "")) - ;; A shorter alias for org src blocks than "markdown" - (after! org-src - (add-to-list 'org-src-lang-modes '("md" . markdown))) - :config (set-flyspell-predicate! '(markdown-mode gfm-mode) #'+markdown-flyspell-word-p) @@ -77,6 +74,13 @@ capture, the end position, and the output buffer.") :override #'markdown-match-generic-metadata (ignore (goto-char (point-max)))) + ;; HACK: markdown-mode calls a major mode without inhibiting its hooks, which + ;; could contain expensive functionality. I suppress it to speed up their + ;; fontification. + (defadvice! +markdown-optimize-src-buffer-modes-a (fn &rest args) + :around #'markdown-fontify-code-block-natively + (delay-mode-hooks (apply fn args))) + (map! :map markdown-mode-map :localleader "'" #'markdown-edit-code-block diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index 8473f7c6d..8e2fe5550 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -205,6 +205,9 @@ Is relative to `org-directory', unless it is absolute. Is used in Doom's default ;; Our :lang common-lisp module uses sly, so... org-babel-lisp-eval-fn #'sly-eval) + ;; A shorter alias for markdown code blocks. + (add-to-list 'org-src-lang-modes '("md" . markdown)) + ;; I prefer C-c C-c over C-c ' (more consistent) (define-key org-src-mode-map (kbd "C-c C-c") #'org-edit-src-exit) @@ -747,15 +750,6 @@ mutating hooks on exported output, like formatters." :before-while #'org-fix-tags-on-the-fly org-auto-align-tags) - (defadvice! +org--recenter-after-follow-link-a (&rest _args) - "Recenter after following a link, but only internal or file links." - :after '(org-footnote-action - org-follow-timestamp-link - org-link-open-as-file - org-link-search) - (when (get-buffer-window) - (recenter))) - (defadvice! +org--strip-properties-from-outline-a (fn &rest args) "Fix variable height faces in eldoc breadcrumbs." :around #'org-format-outline-path @@ -781,26 +775,14 @@ mutating hooks on exported output, like formatters." (let (persp-autokill-buffer-on-remove) (persp-remove-buffer org-agenda-new-buffers (get-current-persp) - nil)))) - (defun +org-defer-mode-in-agenda-buffers-h () - "`org-agenda' opens temporary, incomplete org-mode buffers. -I've disabled a lot of org-mode's startup processes for these invisible buffers -to speed them up (in `+org--exclude-agenda-buffers-from-recentf-a'). However, if -the user tries to visit one of these buffers they'll see a gimped, half-broken -org buffer. To avoid that, restart `org-mode' when they're switched to so they -can grow up to be fully-fledged org-mode buffers." - (dolist (buffer org-agenda-new-buffers) - (when (buffer-live-p buffer) ; Ensure buffer is not killed - (with-current-buffer buffer - (add-hook 'doom-switch-buffer-hook #'+org--restart-mode-h - nil 'local)))))) + nil))))) (defadvice! +org--restart-mode-before-indirect-buffer-a (&optional buffer _) "Restart `org-mode' in buffers in which the mode has been deferred (see `+org-defer-mode-in-agenda-buffers-h') before they become the base buffer for an -indirect buffer. This ensures that the buffer is fully functional not only when -the *user* visits it, but also when some code interacts with it via an indirect -buffer as done, e.g., by `org-capture'." +indirect org-cpature buffer. This ensures that the buffer is fully functional +not only when the *user* visits it, but also when org-capture interacts with it +via an indirect buffer." :before #'org-capture-get-indirect-buffer (with-current-buffer (or buffer (current-buffer)) (when (memq #'+org--restart-mode-h doom-switch-buffer-hook) @@ -808,7 +790,14 @@ buffer as done, e.g., by `org-capture'." (defvar recentf-exclude) (defadvice! +org--optimize-backgrounded-agenda-buffers-a (fn file) - "Prevent temporarily opened agenda buffers from polluting recentf." + "Disable a lot of org-mode's startup processes for temporary agenda buffers. + + This includes preventing them from polluting recentf. + + However, if the user tries to visit one of these buffers they'll see a + gimped, half-broken org buffer. To avoid that, install a hook to restart + `org-mode' when they're switched to so they can grow up to be fully-fledged + org-mode buffers." :around #'org-get-agenda-file-buffer (let ((recentf-exclude (list (lambda (_file) t))) (doom-inhibit-large-file-detection t) @@ -817,7 +806,12 @@ buffer as done, e.g., by `org-capture'." vc-handled-backends org-mode-hook find-file-hook) - (funcall fn file))) + (let ((buf (funcall fn file))) + (if buf + (with-current-buffer buf + (add-hook 'doom-switch-buffer-hook #'+org--restart-mode-h + nil 'local))) + buf))) (defadvice! +org--fix-inconsistent-uuidgen-case-a (uuid) "Ensure uuidgen is always lowercase (consistent) regardless of system." diff --git a/modules/tools/ansible/packages.el b/modules/tools/ansible/packages.el index 3fd47d5de..b56d1e3a0 100644 --- a/modules/tools/ansible/packages.el +++ b/modules/tools/ansible/packages.el @@ -1,7 +1,7 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/ansible/packages.el -(package! ansible :recipe (:nonrecursive t) :pin "b4dca00f89334392d770a7a67fffc935ec7354aa") +(package! ansible :recipe (:nonrecursive t) :pin "eebb2fb49d3c0a0586d1e4ead9ba618c7d003cae") (package! ansible-doc :pin "86083a7bb2ed0468ca64e52076b06441a2f8e9e0") (package! jinja2-mode :pin "03e5430a7efe1d163a16beaf3c82c5fd2c2caee1") (package! yaml-mode :pin "7b5ce294fb15c2c8926fa476d7218aa415550a2a") diff --git a/modules/ui/vc-gutter/config.el b/modules/ui/vc-gutter/config.el index 21bf72e5d..f88ff4567 100644 --- a/modules/ui/vc-gutter/config.el +++ b/modules/ui/vc-gutter/config.el @@ -3,33 +3,44 @@ ;; ;;; Default styles +;; STYLE: Redefine fringe bitmaps to be sleeker by making them solid bars (with +;; no border) that only take up half the horizontal space in the fringe. This +;; approach lets us avoid robbing fringe space from other packages/modes that +;; may need benefit from it (like magit, flycheck, or flyspell). (when (modulep! +pretty) - ;; UI: make the fringe small enough that the diff bars aren't too domineering, - ;; while leaving enough room for other indicators. (if (fboundp 'fringe-mode) (fringe-mode '8)) - ;; UI: the gutter looks less cramped with some space between it and buffer. (setq-default fringes-outside-margins t) - ;; STYLE: Redefine fringe bitmaps to take up only half the horizontal space in - ;; the fringe. This way we avoid overbearingly large diff bars without - ;; having to shrink the fringe and sacrifice precious space for other fringe - ;; indicators (like flycheck or flyspell). - ;; REVIEW: Extract these into a package with faces that themes can target. - (defadvice! +vc-gutter-define-thin-bitmaps-a (&rest args) - :override #'diff-hl-define-bitmaps - (define-fringe-bitmap 'diff-hl-bmp-middle [224] nil nil '(center repeated)) - (define-fringe-bitmap 'diff-hl-bmp-delete [240 224 192 128] nil nil 'top)) - (defun +vc-gutter-type-face-fn (type _pos) - (intern (format "diff-hl-%s" type))) + (defadvice! +vc-gutter-define-thin-bitmaps-a (&rest _) + :after #'diff-hl-define-bitmaps + (let* ((scale (if (and (boundp 'text-scale-mode-amount) + (numberp text-scale-mode-amount)) + (expt text-scale-mode-step text-scale-mode-amount) + 1)) + (spacing (or (and (display-graphic-p) (default-value 'line-spacing)) 0)) + (h (+ (ceiling (* (frame-char-height) scale)) + (if (floatp spacing) + (truncate (* (frame-char-height) spacing)) + spacing))) + (w (min (frame-parameter nil (intern (format "%s-fringe" diff-hl-side))) + 16)) + (_ (if (zerop w) (setq w 16)))) + (define-fringe-bitmap 'diff-hl-bmp-middle + (make-vector + h (string-to-number (let ((half-w (1- (/ w 2)))) + (concat (make-string half-w ?1) + (make-string (- w half-w) ?0))) + 2)) + nil nil 'center))) (defun +vc-gutter-type-at-pos-fn (type _pos) (if (eq type 'delete) 'diff-hl-bmp-delete 'diff-hl-bmp-middle)) - (advice-add #'diff-hl-fringe-bmp-from-pos :override #'+vc-gutter-type-at-pos-fn) - (advice-add #'diff-hl-fringe-bmp-from-type :override #'+vc-gutter-type-at-pos-fn) + (setq diff-hl-fringe-bmp-function #'+vc-gutter-type-at-pos-fn) (setq diff-hl-draw-borders nil) + (add-hook! 'diff-hl-mode-hook - (defun +vc-gutter-fix-diff-hl-faces-h () + (defun +vc-gutter-make-diff-hl-faces-transparent-h () (mapc (doom-rpartial #'set-face-background nil) '(diff-hl-insert diff-hl-delete @@ -61,6 +72,8 @@ (setq vc-git-diff-switches '("--histogram")) ;; PERF: Slightly more conservative delay before updating the diff (setq diff-hl-flydiff-delay 0.5) ; default: 0.3 + ;; PERF: don't block Emacs when updating vc gutter + (setq diff-hl-update-async t) ;; UX: get realtime feedback in diffs after staging/unstaging hunks. (setq diff-hl-show-staged-changes nil) @@ -107,9 +120,9 @@ (when (modulep! :editor evil) (add-hook! 'diff-hl-flydiff-mode-hook (defun +vc-gutter-init-flydiff-mode-h () - (if (not diff-hl-flydiff-mode) - (remove-hook 'evil-insert-state-exit-hook #'diff-hl-flydiff-update) - (add-hook 'evil-insert-state-exit-hook #'diff-hl-flydiff-update))))) + (if diff-hl-flydiff-mode + (add-hook 'evil-insert-state-exit-hook #'diff-hl-flydiff-update) + (remove-hook 'evil-insert-state-exit-hook #'diff-hl-flydiff-update))))) ;; FIX: Reverting a hunk causes the cursor to be moved to an unexpected place, ;; often far from the target hunk.