From fc35b3cf37d983b7cee13d523fb3f5072abbeed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ot=C3=A1vio=20Schwanck=20dos=20Santos?= Date: Wed, 11 Sep 2024 04:33:36 -0400 Subject: [PATCH 01/25] feat(ruby): add rails-{routes,i18n} & ruby-json-to-hash Close: #5821 --- modules/lang/ruby/config.el | 39 +++++++++++++++++++++++++++++++++++ modules/lang/ruby/packages.el | 5 +++++ 2 files changed, 44 insertions(+) diff --git a/modules/lang/ruby/config.el b/modules/lang/ruby/config.el index 68753bab5..fbf2f4d7f 100644 --- a/modules/lang/ruby/config.el +++ b/modules/lang/ruby/config.el @@ -91,6 +91,16 @@ "P" #'rubocop-autocorrect-project)) +(use-package! ruby-json-to-hash + :defer t + :init + (map! :after ruby-mode + :map ruby-mode-map + :localleader + "J" #'ruby-json-to-hash-parse-json + "j" #'ruby-json-to-hash-toggle-let)) + + ;; ;;; Package & Ruby version management @@ -182,6 +192,9 @@ "v" #'minitest-verify)) +;; +;;; Rails integration + (use-package! projectile-rails :when (modulep! +rails) :hook ((ruby-mode inf-ruby-mode projectile-rails-server-mode) . projectile-rails-mode) @@ -199,3 +212,29 @@ (map! :localleader :map projectile-rails-mode-map "r" #'projectile-rails-command-map)) + +(use-package! rails-routes + :when (featurep! +rails) + :defer t + :init + (map! :after ruby-mode + :map ruby-mode-map + "C-c o" #'rails-routes-insert + "C-c C-o" #'rails-routes-insert-no-cache + "C-c ! o" #'rails-routes-jump) + (map! :after web-mode + :map web-mode-map + "C-c o" #'rails-routes-insert + "C-c C-o" #'rails-routes-insert-no-cache + "C-c ! o" #'rails-routes-jump)) + +(use-package! rails-i18n + :when (featurep! +rails) + :defer t + :init + (map! :after ruby-mode + :map ruby-mode-map + "C-c i" #'rails-i18n-insert-with-cache) + (map! :after web-mode + :map web-mode-map + "C-c i" #'rails-i18n-insert-with-cache)) diff --git a/modules/lang/ruby/packages.el b/modules/lang/ruby/packages.el index 0348ba532..4e53ae02b 100644 --- a/modules/lang/ruby/packages.el +++ b/modules/lang/ruby/packages.el @@ -30,7 +30,12 @@ (package! rspec-mode :pin "29df3d081c6a1cbdf840cd13d45ea1c100c5bbaa") (package! minitest :pin "5999c45c047212cee15a2be67e78787776a79c35") +;; Refactoring +(package! ruby-json-to-hash :pin "383b22bb2e007289ac0dba146787d02ff99d4415") + ;; Rails (when (modulep! +rails) + (package! rails-routes :pin "eab995a9297ca5bd9bd4f4c2737f2fecfc36def0") + (package! rails-i18n :pin "8e87e4e48e31902b8259ded28a208c2e7efea6e9") (package! projectile-rails :pin "701784df7befe17b861f1b53fe9cbc59d0b94b9f") (package! inflections :pin "55caa66a7cc6e0b1a76143fd40eff38416928941")) From f6b7e8ae48076b517acef96159409460357417d2 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 05:27:14 -0400 Subject: [PATCH 02/25] module: add :lang graphviz Close: #7546 Co-authored-by: nbfalcon Co-authored-by: peterhoeg --- modules/lang/graphviz/README.org | 64 +++++++++++++++++++++++++++++++ modules/lang/graphviz/autoload.el | 19 +++++++++ modules/lang/graphviz/config.el | 38 ++++++++++++++++++ modules/lang/graphviz/doctor.el | 6 +++ modules/lang/graphviz/packages.el | 4 ++ templates/init.example.el | 1 + 6 files changed, 132 insertions(+) create mode 100644 modules/lang/graphviz/README.org create mode 100644 modules/lang/graphviz/autoload.el create mode 100644 modules/lang/graphviz/config.el create mode 100644 modules/lang/graphviz/doctor.el create mode 100644 modules/lang/graphviz/packages.el diff --git a/modules/lang/graphviz/README.org b/modules/lang/graphviz/README.org new file mode 100644 index 000000000..b3ffdd766 --- /dev/null +++ b/modules/lang/graphviz/README.org @@ -0,0 +1,64 @@ +:PROPERTIES: +:ID: 3efe8402-e4a1-41c3-ad1a-9aaa3783f68f +:END: +#+title: :lang graphviz +#+subtitle: Diagrams to confuse yourself even more +#+created: Nov 14, 2023 +#+since: 23.09.0-pre + +* Description :unfold: +This module adds graphviz support to Emacs, allowing you to generate diagrams +from plain text. Flycheck is supported. + +** Maintainers +/This module has no dedicated maintainers./ [[doom-contrib-maintainer:][Become a maintainer?]] + +** Module flags +/This module has no flags./ + +** Packages +- [[doom-package:graphviz-dot-mode]] + +** Hacks +/No hacks documented for this module./ + +** TODO Changelog +# This section will be machine generated. Don't edit it by hand. +/This module does not have a changelog yet./ + +* Installation +[[id:01cffea4-3329-45e2-a892-95a384ab2338][Enable this module in your ~doom!~ block.]] + +This module requires that the =graphviz= package be installed on your system to +build diagrams with. You can install it using: +#+begin_src shell +sudo dnf install graphviz # For fedora +sudo apt install graphviz # For debian/ubuntu +#+end_src + +* Usage +This module should configure "out-of-the-box" if you have installed graphviz on +your system. + +With org-babel LaTeX/PDF-export, use a file naming ending with ".pdf", otherwise +LaTeX might complain about a non-existant ~\\includesvg~ command. +#+begin_src dot :file graph-1.pdf +digraph { + A -> B; + B -> D; +} +#+end_src + +* Configuration +There is nothing to configure. Just install dot and it should work. + +* Troubleshooting +/There are no known problems with this module./ [[doom-report:][Report one?]] + +* Frequently asked questions +/This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]] + +* TODO Appendix +#+begin_quote + 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]] +#+end_quote diff --git a/modules/lang/graphviz/autoload.el b/modules/lang/graphviz/autoload.el new file mode 100644 index 000000000..1ace8454e --- /dev/null +++ b/modules/lang/graphviz/autoload.el @@ -0,0 +1,19 @@ +;;; lang/graphviz/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(cl-defun +graphviz-formatter (&key _buffer scratch callback &allow-other-keys) + "Format graphviz graphs." + (with-current-buffer scratch + (let ((inhibit-message t) + (message-log-max nil)) + (goto-char (point-min)) + (graphviz-dot-indent-graph)) + (funcall callback))) + +;;;###autoload +(defun +graphviz/toggle-preview () + "Toggle `graphviz-dot-auto-preview-on-save'." + (interactive nil 'graphviz-dot-mode) + (if graphviz-dot-auto-preview-on-save + (graphviz-turn-off-live-preview) + (graphviz-turn-on-live-preview))) diff --git a/modules/lang/graphviz/config.el b/modules/lang/graphviz/config.el new file mode 100644 index 000000000..7104997f7 --- /dev/null +++ b/modules/lang/graphviz/config.el @@ -0,0 +1,38 @@ +;;; lang/graphviz/config.el -*- lexical-binding: t; -*- + +(use-package! graphviz-dot-mode + :mode "\\.\\(?:nw\\|rack\\)diag\\'" + :init + (after! org-src + (add-to-list '+org-babel-mode-alist '(dot . graphviz-dot-mode)) + (add-to-list 'org-src-lang-modes '("dot" . graphviz-dot-mode))) + :config + (set-company-backend! 'graphviz-dot-mode 'company-graphviz-dot-backend) + (set-formatter! 'graphviz-dot #'+graphviz-formatter :modes '(graphviz-dot-mode)) + (set-tree-sitter-lang! 'graphviz-dot-mode 'dot) + + (when (modulep! +tree-sitter) + (add-hook 'graphiz-dot-mode-hook #'tree-sitter!)) + + (after! dtrt-indent + (add-to-list 'dtrt-indent-hook-mapping-list '(graphviz-mode graphviz-dot-indent-width))) + + (when (and (modulep! :checker syntax) + (not (modulep! :checker syntax +flymake))) + (after! flycheck + (flycheck-define-checker graphviz-dot + "A checker using graphviz dot." + :command ("dot") + :standard-input t + :error-patterns ((error line-start "Error: : " (message "syntax error in line " line (* nonl))) + ;; I have no idea if this can actually be printed + (error line-start "Error: : " (message))) + :modes graphviz-dot-mode) + (add-to-list 'flycheck-checkers 'graphviz-dot))) + + (map! :map graphviz-dot-mode-map + :localleader + :desc "External view" :nv "e" #'graphviz-dot-view + :desc "Preview" :nv "p" #'graphviz-dot-preview + :prefix ("t" . "toggle") + :desc "Preview" :nv "p" #'+graphviz/toggle-preview)) diff --git a/modules/lang/graphviz/doctor.el b/modules/lang/graphviz/doctor.el new file mode 100644 index 000000000..f6fa5a27f --- /dev/null +++ b/modules/lang/graphviz/doctor.el @@ -0,0 +1,6 @@ +;; -*- lexical-binding: t; no-byte-compile: t; -*- +;;; lang/graphviz/doctor.el + +(when (require 'graphviz-dot-mode nil t) + (unless (executable-find graphviz-dot-dot-program) + (warn! "Couldn't find dot. Previewing and exporting will not work"))) diff --git a/modules/lang/graphviz/packages.el b/modules/lang/graphviz/packages.el new file mode 100644 index 000000000..bfed5e023 --- /dev/null +++ b/modules/lang/graphviz/packages.el @@ -0,0 +1,4 @@ +;; -*- no-byte-compile: t; -*- +;;; lang/graphviz/packages.el + +(package! graphviz-dot-mode :pin "8ff793b13707cb511875f56e167ff7f980a31136") diff --git a/templates/init.example.el b/templates/init.example.el index f18e9c4cd..40a5d4658 100644 --- a/templates/init.example.el +++ b/templates/init.example.el @@ -154,6 +154,7 @@ org ; organize your plain life in plain text ;;php ; perl's insecure younger brother ;;plantuml ; diagrams for confusing people more + ;;graphviz ; diagrams for confusing yourself even more ;;purescript ; javascript, but functional ;;python ; beautiful is better than ugly ;;qt ; the 'cutest' gui framework ever From 1baebdafb3b14e05351090d04e46bfcf33c36bf3 Mon Sep 17 00:00:00 2001 From: Sorawee Porncharoenwase Date: Wed, 11 Sep 2024 05:51:49 -0400 Subject: [PATCH 03/25] feat(racket): add +hash-lang `racket-mode` recently added `racket-hash-lang-mode` as an alternative major mode. Close: #7543 Co-authored-by: hlissner --- modules/lang/racket/README.org | 8 +- modules/lang/racket/config.el | 178 ++++++++++++++++++--------------- 2 files changed, 104 insertions(+), 82 deletions(-) diff --git a/modules/lang/racket/README.org b/modules/lang/racket/README.org index 26e759c7e..3d2354a59 100644 --- a/modules/lang/racket/README.org +++ b/modules/lang/racket/README.org @@ -14,8 +14,12 @@ This module adds support for the [[https://www.racket-lang.org/][Racket programm Enable support for ~racket-mode~. Requires [[doom-module::tools lsp]] and a langserver (supports [[https://github.com/jeapostrophe/racket-langserver][racket-langserver]]). - +xp :: - Enable the explore mode (~racket-xp-mode~), which "analyzes expanded code to - explain and explore." + Enable the explore minor mode (~racket-xp-mode~), which "analyzes expanded + code to explain and explore." +- +hash-lang :: + Enable the hash-lang major mode (~racket-hash-lang-mode~), which "uses + color-lexer, indent, and navigation supplied by a #lang." This flag can be + used along with the ~+xp~ flag. ** Packages - [[doom-package:racket-mode]] diff --git a/modules/lang/racket/config.el b/modules/lang/racket/config.el index 46700f830..5bb524f8a 100644 --- a/modules/lang/racket/config.el +++ b/modules/lang/racket/config.el @@ -8,88 +8,106 @@ ;; ;;; Packages -(use-package! racket-mode - :mode "\\.rkt\\'" ; give it precedence over :lang scheme - :config - (set-repl-handler! 'racket-mode #'+racket/open-repl) - (set-lookup-handlers! '(racket-mode racket-repl-mode) - :definition #'+racket-lookup-definition - :documentation #'+racket-lookup-documentation) - (set-docsets! 'racket-mode "Racket") - (set-ligatures! 'racket-mode - :lambda "lambda" - :map "map" - :dot ".") - (set-rotate-patterns! 'racket-mode - :symbols '(("#true" "#false"))) - (set-formatter! 'raco-fmt '("raco" "fmt") :modes '(racket-mode)) +(let (mode + mode-map + mode-exts + mode-hook + mode-local-vars-hook) + (if (modulep! +hash-lang) + (setq mode 'racket-hash-lang-mode + mode-exts '("\\.rkt\\'" ; Racket + "\\.scrbl\\'" ; Scribble + "\\.rhm\\'")) ; Rhombus + (setq mode 'racket-mode + mode-exts `("\\.rkt\\'"))) + (let ((mode-name (symbol-name mode))) + (setq mode-map (intern (format "%s-map" mode-name)) + mode-hook (intern (format "%s-hook" mode-name)) + mode-local-vars-hook (intern (format "%s-local-vars-hook" mode-name)))) - (add-hook! 'racket-mode-hook - #'rainbow-delimiters-mode - #'highlight-quoted-mode) + (use-package! racket-mode + :defer t + :init + (dolist (entry mode-exts) + (add-to-list 'auto-mode-alist (cons entry mode))) + :config + (set-repl-handler! mode #'+racket/open-repl) + (set-lookup-handlers! `(,mode racket-repl-mode) + :definition #'+racket-lookup-definition + :documentation #'+racket-lookup-documentation) + (set-docsets! mode "Racket") + (set-ligatures! mode + :lambda "lambda" + :map "map" + :dot ".") + (set-rotate-patterns! mode :symbols '(("#true" "#false"))) + (set-formatter! 'raco-fmt '("raco" "fmt") :modes (list mode)) - (when (modulep! +lsp) - (add-hook 'racket-mode-local-vars-hook #'lsp! 'append)) + (add-hook mode-hook #'rainbow-delimiters-mode) + (add-hook mode-hook #'highlight-quoted-mode) - (when (modulep! +xp) - (add-hook 'racket-mode-local-vars-hook #'racket-xp-mode) - ;; Both flycheck and racket-xp produce error popups, but racket-xp's are - ;; higher quality so disable flycheck's: - (when (modulep! :checkers syntax) - (add-hook! 'racket-xp-mode-hook - (defun +racket-disable-flycheck-h () - (cl-pushnew 'racket flycheck-disabled-checkers))))) + (when (modulep! +lsp) + (add-hook mode-local-vars-hook #'lsp! 'append)) - (unless (or (modulep! :editor parinfer) - (modulep! :editor lispy)) - (add-hook 'racket-mode-hook #'racket-smart-open-bracket-mode)) + (when (modulep! +xp) + (add-hook mode-local-vars-hook #'racket-xp-mode) + ;; Both flycheck and racket-xp produce error popups, but racket-xp's are + ;; higher quality so disable flycheck's: + (when (modulep! :checkers syntax) + (add-hook! 'racket-xp-mode-hook + (defun +racket-disable-flycheck-h () + (cl-pushnew 'racket flycheck-disabled-checkers))))) - (map! (:map racket-xp-mode-map - [remap racket-doc] #'racket-xp-documentation - [remap racket-visit-definition] #'racket-xp-visit-definition - [remap next-error] #'racket-xp-next-error - [remap previous-error] #'racket-xp-previous-error) - (:localleader - :map racket-mode-map - "a" #'racket-align - "A" #'racket-unalign - "f" #'racket-fold-all-tests - "F" #'racket-unfold-all-tests - "h" #'racket-doc - "i" #'racket-unicode-input-method-enable - "l" #'racket-logger - "o" #'racket-profile - "p" #'racket-cycle-paren-shapes - "r" #'racket-run - "R" #'racket-run-and-switch-to-repl - "t" #'racket-test - "u" #'racket-backward-up-list - "y" #'racket-insert-lambda - (:prefix ("m" . "macros") - "d" #'racket-expand-definition - "e" #'racket-expand-last-sexp - "r" #'racket-expand-region - "a" #'racket-expand-again) - (:prefix ("g" . "goto") - "b" #'racket-unvisit - "d" #'racket-visit-definition - "m" #'racket-visit-module - "r" #'racket-open-require-path) - (:prefix ("s" . "send") - "d" #'racket-send-definition - "e" #'racket-send-last-sexp - "r" #'racket-send-region) - :map racket-repl-mode-map - "l" #'racket-logger - "h" #'racket-repl-documentation - "y" #'racket-insert-lambda - "u" #'racket-backward-up-list - (:prefix ("m" . "macros") - "d" #'racket-expand-definition - "e" #'racket-expand-last-sexp - "f" #'racket-expand-file - "r" #'racket-expand-region) - (:prefix ("g" . "goto") - "b" #'racket-unvisit - "m" #'racket-visit-module - "d" #'racket-repl-visit-definition)))) + (unless (or (modulep! :editor parinfer) + (modulep! :editor lispy)) + (add-hook mode-hook #'racket-smart-open-bracket-mode)) + + (map! (:map racket-xp-mode-map + [remap racket-doc] #'racket-xp-documentation + [remap racket-visit-definition] #'racket-xp-visit-definition + [remap next-error] #'racket-xp-next-error + [remap previous-error] #'racket-xp-previous-error) + (:localleader + :map ,mode-map + "a" #'racket-align + "A" #'racket-unalign + "f" #'racket-fold-all-tests + "F" #'racket-unfold-all-tests + "h" #'racket-doc + "i" #'racket-unicode-input-method-enable + "l" #'racket-logger + "o" #'racket-profile + "p" #'racket-cycle-paren-shapes + "r" #'racket-run + "R" #'racket-run-and-switch-to-repl + "t" #'racket-test + "u" #'racket-backward-up-list + "y" #'racket-insert-lambda + (:prefix ("m" . "macros") + "d" #'racket-expand-definition + "e" #'racket-expand-last-sexp + "r" #'racket-expand-region + "a" #'racket-expand-again) + (:prefix ("g" . "goto") + "b" #'racket-unvisit + "d" #'racket-visit-definition + "m" #'racket-visit-module + "r" #'racket-open-require-path) + (:prefix ("s" . "send") + "d" #'racket-send-definition + "e" #'racket-send-last-sexp + "r" #'racket-send-region) + :map racket-repl-mode-map + "l" #'racket-logger + "h" #'racket-repl-documentation + "y" #'racket-insert-lambda + "u" #'racket-backward-up-list + (:prefix ("m" . "macros") + "d" #'racket-expand-definition + "e" #'racket-expand-last-sexp + "f" #'racket-expand-file + "r" #'racket-expand-region) + (:prefix ("g" . "goto") + "b" #'racket-unvisit + "m" #'racket-visit-module + "d" #'racket-repl-visit-definition))))) From 240493ae9235d2b1b2ffc1d98cd829b7d2bbb236 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 06:20:01 -0400 Subject: [PATCH 04/25] fix: face-* calls crashing new emacsclient frames Those `face-*` calls sometimes returned nil, causing new frames spawned from emacsclient to quietly crash sometimes. By instead relying on `frame-inherited-parameters` we achieve the same but more stable result. Amend: 9753bfb775d0 --- lisp/doom-ui.el | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lisp/doom-ui.el b/lisp/doom-ui.el index 09cd845d2..a5859ad59 100644 --- a/lisp/doom-ui.el +++ b/lisp/doom-ui.el @@ -284,6 +284,14 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original (setq split-width-threshold 160 split-height-threshold nil) +;; Fix incorrect fg/bg in new frames created after the initial frame +;; (which are reroneously displayed as black). +(setq frame-inherited-parameters '(background-color + foreground-color + cursor-color + border-color + mouse-color)) + ;; ;;; Minibuffer @@ -589,11 +597,7 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original (setq doom-theme theme) (put 'doom-theme 'previous-themes (or last-themes 'none)) ;; DEPRECATED Hook into `enable-theme-functions' when we target 29 - (doom-run-hooks 'doom-load-theme-hook) - (when-let* ((fg (face-foreground 'default nil t)) - (bg (face-background 'default nil t))) - (setf (alist-get 'foreground-color default-frame-alist) fg - (alist-get 'background-color default-frame-alist) bg))))))) + (doom-run-hooks 'doom-load-theme-hook)))))) ;; From a8515034deb4495c32657a94d09bcdee30b7ff0b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 13:30:23 -0400 Subject: [PATCH 05/25] refactor: rename childframe predicate function - The name reflected the opposite of what it detected. - It should be treated as an internal (not public) function. --- lisp/doom-ui.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/doom-ui.el b/lisp/doom-ui.el index a5859ad59..0016208aa 100644 --- a/lisp/doom-ui.el +++ b/lisp/doom-ui.el @@ -661,11 +661,11 @@ triggering hooks during startup." (fset 'set-fontset-font #'ignore)) (after! whitespace - (defun doom-is-childframes-p () + (defun doom--in-parent-frame-p () "`whitespace-mode' inundates child frames with whitespace markers, so disable it to fix all that visual noise." (null (frame-parameter nil 'parent-frame))) - (add-function :before-while whitespace-enable-predicate #'doom-is-childframes-p)) + (add-function :before-while whitespace-enable-predicate #'doom--in-parent-frame-p)) (provide 'doom-ui) ;;; doom-ui.el ends here From 546e56f1fa484e26ca368a350edba58c6c4c0439 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 13:57:01 -0400 Subject: [PATCH 06/25] fix: suppress visual startup optimizations in debug mode Also interferes with doom/sandbox's launch targets. --- lisp/doom.el | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/lisp/doom.el b/lisp/doom.el index 40298c768..ef16fe76a 100644 --- a/lisp/doom.el +++ b/lisp/doom.el @@ -470,27 +470,31 @@ users).") (defun doom--reset-custom-dont-initialize-h () (setq custom-dont-initialize nil))) - ;; PERF: The mode-line procs a couple dozen times during startup, before the - ;; user even sees the first mode-line. This is normally fast, but we can't - ;; predict what the user (or packages) will put into the mode-line. Also, - ;; mode-line packages have a bad habit of throwing performance to the - ;; wind, so best we just disable the mode-line until we can see one. - (put 'mode-line-format 'initial-value (default-toplevel-value 'mode-line-format)) - (setq-default mode-line-format nil) - (dolist (buf (buffer-list)) - (with-current-buffer buf (setq mode-line-format nil))) - ;; PERF,UX: Premature redisplays/redraws can substantially affect startup - ;; times and/or flash a white/unstyled Emacs frame during startup, so I - ;; try real hard to suppress them until we're sure the session is ready. - (setq-default inhibit-redisplay t - inhibit-message t) - ;; COMPAT: If the above vars aren't reset, Emacs could appear frozen or - ;; garbled after startup (or in case of an startup error). - (defun doom--reset-inhibited-vars-h () - (setq-default inhibit-redisplay nil - inhibit-message nil) - (remove-hook 'post-command-hook #'doom--reset-inhibited-vars-h)) - (add-hook 'post-command-hook #'doom--reset-inhibited-vars-h -100) + ;; These optimizations are brittle, difficult to debug, and obscure other + ;; issues, so bow out when debug mode is on. + (unless init-file-debug + ;; PERF: The mode-line procs a couple dozen times during startup, before + ;; the user even sees the first mode-line. This is normally fast, but we + ;; can't predict what the user (or packages) will put into the + ;; mode-line. Also, mode-line packages have a bad habit of throwing + ;; performance to the wind, so best we just disable the mode-line until + ;; we can see one. + (put 'mode-line-format 'initial-value (default-toplevel-value 'mode-line-format)) + (setq-default mode-line-format nil) + (dolist (buf (buffer-list)) + (with-current-buffer buf (setq mode-line-format nil))) + ;; PERF,UX: Premature redisplays/redraws can substantially affect startup + ;; times and/or flash a white/unstyled Emacs frame during startup, so I + ;; try real hard to suppress them until we're sure the session is ready. + (setq-default inhibit-redisplay t + inhibit-message t) + ;; COMPAT: If the above vars aren't reset, Emacs could appear frozen or + ;; garbled after startup (or in case of an startup error). + (defun doom--reset-inhibited-vars-h () + (setq-default inhibit-redisplay nil + inhibit-message nil) + (remove-hook 'post-command-hook #'doom--reset-inhibited-vars-h)) + (add-hook 'post-command-hook #'doom--reset-inhibited-vars-h -100)) ;; PERF: Doom disables the UI elements by default, so that there's less for ;; the frame to initialize. However, `tool-bar-setup' is still called and From 6d7a39c482e02d6ca160f67653df44a6df70dd9f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 13:58:01 -0400 Subject: [PATCH 07/25] tweak: load site-lisp verbosely in debug mode --- lisp/doom.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lisp/doom.el b/lisp/doom.el index ef16fe76a..fb697c487 100644 --- a/lisp/doom.el +++ b/lisp/doom.el @@ -519,10 +519,11 @@ users).") (progn (when (setq site-run-file (get 'site-run-file 'initial-value)) (let ((inhibit-startup-screen inhibit-startup-screen)) - (letf! ((defun load-file (file) (load file nil 'nomessage)) + (letf! ((defun load-file (file) + (load file nil (not init-file-debug))) (defun load (file &optional noerror _nomessage &rest args) - (apply load file noerror t args))) - (load site-run-file t t)))) + (apply load file noerror (not init-file-debug) args))) + (load site-run-file t)))) (apply fn args)) ;; Now it's safe to be verbose. (setq-default inhibit-message nil) From 771fccc52bdc56c1816d104a90034c9fe8231ffd Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 14:03:40 -0400 Subject: [PATCH 08/25] nit: minor reformatting & revision Also corrects the version string of obsolete variable `+mu4e-backend`. --- bin/doom | 2 +- lisp/doom-cli-lib.el | 1 - lisp/doom-modules.el | 2 +- lisp/doom-start.el | 4 ++-- lisp/doom-ui.el | 2 +- lisp/doom.el | 23 ++++++++++++----------- modules/completion/company/README.org | 2 +- modules/config/literate/autoload.el | 4 ++-- modules/editor/evil/config.el | 4 ++-- modules/email/mu4e/config.el | 2 +- modules/source.el | 7 ------- modules/ui/indent-guides/config.el | 2 ++ modules/ui/indent-guides/packages.el | 2 +- 13 files changed, 26 insertions(+), 31 deletions(-) delete mode 100644 modules/source.el diff --git a/bin/doom b/bin/doom index f976aa25a..3161b0389 100755 --- a/bin/doom +++ b/bin/doom @@ -164,7 +164,7 @@ EXIT CODES: 5 Invalid, missing, or extra options/arguments 6-15 Reserved for Doom 16-192 Reserved for the user's extensions - 254 Successful run (but then execute `doom-cli-restart-script') + 254 Successful run (then execute the dynamically generated after-script) 255 Uncaught critical errors SEE ALSO: diff --git a/lisp/doom-cli-lib.el b/lisp/doom-cli-lib.el index 948fcf2ff..d8ec8cff7 100644 --- a/lisp/doom-cli-lib.el +++ b/lisp/doom-cli-lib.el @@ -1877,7 +1877,6 @@ errors to `doom-cli-error-file')." (error "Cannot nest `run!' calls")) (doom-run-hooks 'doom-after-init-hook) (doom-context-with 'cli - ;; (doom-modules-initialize) (let* ((args (flatten-list args)) (context (make-doom-cli-context :prefix prefix :whole args)) (doom-cli--context context) diff --git a/lisp/doom-modules.el b/lisp/doom-modules.el index b2d88846a..de07325d5 100644 --- a/lisp/doom-modules.el +++ b/lisp/doom-modules.el @@ -50,7 +50,7 @@ NOT IMPLEMENTED YET. This file contains a module's metadata: their version, maintainers, checks, features, submodules, debug information, etc. And are used to locate modules in the user's file tree.") -;; DEPRECATED: Module warnings will be rewritten in v3, and this variable will no longer be needed. +;; DEPRECATED: Remove in v3, as it will be handled in the CLI (make-obsolete-variable 'doom-obsolete-modules nil "3.0.0") (defconst doom-obsolete-modules '((:feature (version-control (:emacs vc) (:ui vc-gutter)) diff --git a/lisp/doom-start.el b/lisp/doom-start.el index c2a63cfc0..2f0c14efb 100644 --- a/lisp/doom-start.el +++ b/lisp/doom-start.el @@ -339,9 +339,8 @@ If RETURN-P, return the message as a string instead of displaying it." ;; TODO: Catch errors (load! (string-remove-suffix ".el" doom-module-init-file) doom-user-dir t) -;;; Load the rest of $DOOMDIR + modules if noninteractive ;; If the user is loading this file from a batch script, let's assume they want -;; to load their userland config as well. +;; to load their userland config immediately. (when noninteractive (doom-require 'doom-profiles) (let ((init-file (doom-profile-init-file))) @@ -353,6 +352,7 @@ If RETURN-P, return the message as a string instead of displaying it." (doom-load init-file 'noerror) (doom-initialize-packages)))) + ;;; Entry point ;; HACK: This advice hijacks Emacs' initfile loader to accomplish the following: ;; diff --git a/lisp/doom-ui.el b/lisp/doom-ui.el index 0016208aa..e321d6137 100644 --- a/lisp/doom-ui.el +++ b/lisp/doom-ui.el @@ -1,6 +1,6 @@ ;;; doom-ui.el --- defaults for Doom's aesthetics -*- lexical-binding: t; -*- ;;; Commentary: -;;; Code; +;;; Code: ;; ;;; Variables diff --git a/lisp/doom.el b/lisp/doom.el index fb697c487..c85ffbc21 100644 --- a/lisp/doom.el +++ b/lisp/doom.el @@ -54,7 +54,8 @@ ;; - hook: `window-setup-hook' ;; - hook: `doom-init-ui-hook' ;; - hook: `doom-after-init-hook' -;; > After startup is complete: +;; > After startup is complete (if file(s) have been opened from the command +;; line, these will trigger much earlier): ;; - On first input: `doom-first-input-hook' ;; - On first switched-to buffer: `doom-first-buffer-hook' ;; - On first opened file: `doom-first-file-hook' @@ -374,13 +375,13 @@ users).") (let ((old-value (default-toplevel-value 'file-name-handler-alist))) (set-default-toplevel-value 'file-name-handler-alist - ;; HACK: The libraries bundled with Emacs can either be compiled, - ;; compressed, or neither. We use calc-loaddefs.el as a heuristic to - ;; guess what state all these libraries are in. If they're compressed, we - ;; need to leave the gzip file handler in `file-name-handler-alist' so - ;; Emacs knows how to load them. If they're compiled or neither, we can - ;; omit the gzip handler altogether (at least during startup) for a boost - ;; in startup and package load time. + ;; HACK: The elisp libraries bundled with Emacs are either compressed or + ;; not, never both. So if calc-loaddefs.el.gz exists, calc-loaddefs.el + ;; won't, and vice versa. This heuristic is used to guess the state of + ;; all other built-in (or site); if they're compressed, we must leave the + ;; gzip file handler in `file-name-handler-alist' so Emacs knows how to + ;; load them. Otherwise, we can omit it (at least during startup) for a + ;; boost in package load time. (if (eval-when-compile (locate-file-internal "calc-loaddefs.el" load-path)) nil @@ -767,7 +768,7 @@ appropriately against `noninteractive' or the `cli' context." ;;; Last minute initialization (when (daemonp) - (message "Starting Doom Emacs in daemon mode!") + (message "Starting Doom Emacs in daemon mode...") (unless doom-inhibit-log (add-hook! 'doom-after-init-hook :depth 106 (unless doom-inhibit-log @@ -788,8 +789,8 @@ appropriately against `noninteractive' or the `cli' context." (when (doom-context-push 'init) ;; HACK: Ensure OS checks are as fast as possible (given their ubiquity). (setq features (cons :system (delq :system features))) - ;; Remember these variables' initial values, so we can safely reset them at - ;; a later time, or consult them without fear of contamination. + ;; Remember these variables' initial values, so we can safely reset them + ;; at a later time, or consult them without fear of contamination. (dolist (var '(exec-path load-path process-environment)) (put var 'initial-value (default-toplevel-value var)))))) diff --git a/modules/completion/company/README.org b/modules/completion/company/README.org index 2279155c0..342f388af 100644 --- a/modules/completion/company/README.org +++ b/modules/completion/company/README.org @@ -22,7 +22,7 @@ https://assets.doomemacs.org/completion/company/overlay.png ** Module flags - +childframe :: - Display completion candidates in a [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Child-Frames.html][child frame]] rather than an overlay or + Display completion candidates in a [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Child-Frames.html][childframe]] rather than an overlay or tooltip. *Requires GUI Emacs.* - +tng :: Invoke completion on [[kbd:][TAB]] instad of [[kbd:][C-SPC]]. When company is active, [[kbd:][TAB]] and diff --git a/modules/config/literate/autoload.el b/modules/config/literate/autoload.el index 7e3930b65..02f792aad 100644 --- a/modules/config/literate/autoload.el +++ b/modules/config/literate/autoload.el @@ -181,8 +181,8 @@ This is performed with an asyncronous Emacs process, except when (defun +literate-recompile-maybe-h () "Recompile literate config to `doom-user-dir'. -We assume any org file in `doom-user-dir' is connected to your literate -config, and should trigger a recompile if changed." +We assume any org file in `doom-user-dir' is connected to your literate config, +and should trigger a recompile if changed." (and (file-in-directory-p (buffer-file-name (buffer-base-buffer)) (file-name-directory (file-truename +literate-config-file))) diff --git a/modules/editor/evil/config.el b/modules/editor/evil/config.el index c7fb7c24f..cf3155744 100644 --- a/modules/editor/evil/config.el +++ b/modules/editor/evil/config.el @@ -369,8 +369,7 @@ directives. By default, this only recognizes C directives.") ;; ;;; Keybinds -;; Keybinds that have no Emacs+evil analogues (i.e. don't exist): -;; zu{q,w} - undo last marking +;; TODO: zu{q,w} - undo last marking (map! :v "@" #'+evil:apply-macro :m [C-i] #'evil-jump-forward @@ -530,6 +529,7 @@ directives. By default, this only recognizes C directives.") ;; evil-easymotion (:after evil-easymotion :m "gs" evilem-map + ;; TODO: Use named functions (:map evilem-map "a" (evilem-create #'evil-forward-arg) "A" (evilem-create #'evil-backward-arg) diff --git a/modules/email/mu4e/config.el b/modules/email/mu4e/config.el index 9279c0488..7e07a1714 100644 --- a/modules/email/mu4e/config.el +++ b/modules/email/mu4e/config.el @@ -2,7 +2,7 @@ (defvar +mu4e-backend 'mbsync "Which backend to use. Can either be offlineimap, mbsync or nil (manual).") -(make-obsolete-variable '+mu4e-backend "Use the :email mu4e module's +mbsync or +offlineimap flags instead" "3.0.0") +(make-obsolete-variable '+mu4e-backend "Use the :email mu4e module's +mbsync or +offlineimap flags instead" "24.09") (defvar +mu4e-personal-addresses 'nil "Alternative to mu4e-personal-addresses that can be set for each account (mu4e context).") diff --git a/modules/source.el b/modules/source.el deleted file mode 100644 index 3e3a2cec1..000000000 --- a/modules/source.el +++ /dev/null @@ -1,7 +0,0 @@ -;; This file supplies some metadata about this module repo to Doom's module -;; manager. None of them are required, but it's a good idea to include them so -;; Doom can perform some sanity checks for you. - -:root "./" ; where the module tree starts -:version "21.12" ; version of this repo -:requires "3.0.0" ; minimum supported version of Doom's core diff --git a/modules/ui/indent-guides/config.el b/modules/ui/indent-guides/config.el index 6f086aca9..898920d5f 100644 --- a/modules/ui/indent-guides/config.el +++ b/modules/ui/indent-guides/config.el @@ -45,6 +45,8 @@ be enabled. If any function returns non-nil, the mode will not be activated." ;; TODO: Uncomment once we support treesit ;; (setq indent-bars-treesit-support (modulep! :tools tree-sitter)) + ;; indent-bars adds this to `enable-theme-functions', which was introduced in + ;; 29.1, which will be redundant with `doom-load-theme-hook'. (unless (boundp 'enable-theme-functions) (add-hook 'doom-load-theme-hook #'indent-bars-reset-styles)) diff --git a/modules/ui/indent-guides/packages.el b/modules/ui/indent-guides/packages.el index 78d640b43..d557760c4 100644 --- a/modules/ui/indent-guides/packages.el +++ b/modules/ui/indent-guides/packages.el @@ -3,4 +3,4 @@ (package! indent-bars :recipe (:host github :repo "jdtsmith/indent-bars") - :pin "c8376cf4373a6444ca88e88736db7576dedb51d6") + :pin "c8376cf4373a6444ca88e88736db7576dedb51d6") From f8f2b2858014d10b18d8fcf082013b70aa580ea8 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 14:08:11 -0400 Subject: [PATCH 09/25] feat: add doom-log-level Gives doom-log that capability of indicating log levels for its messages, so that I can later work of reducing excessive logging in `doom-debug-mode`. --- lisp/doom-lib.el | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/lisp/doom-lib.el b/lisp/doom-lib.el index 602fa6309..6a354c28c 100644 --- a/lisp/doom-lib.el +++ b/lisp/doom-lib.el @@ -19,10 +19,27 @@ ;;; Logging (defvar doom-inhibit-log (not (or noninteractive init-file-debug)) - "If non-nil, suppress `doom-log' output.") + "If non-nil, suppress `doom-log' output completely.") -(defun doom--log (text &rest args) - (let ((inhibit-message (not init-file-debug)) +(defvar doom-log-level + (if init-file-debug + (if-let ((level (getenv-internal "DEBUG")) + (level (string-to-number level)) + ((not (zerop level)))) + level + 2) + 0) + "How verbosely to log from `doom-log' calls. + +0 -- No logging at all. +1 -- Only warnings. +2 -- Warnings and notices. +3 -- Debug info, warnings, and notices.") + +(defun doom--log (level text &rest args) + (let ((inhibit-message (if noninteractive + (not init-file-debug) + (> level doom-log-level))) (absolute? (string-prefix-p ":" text))) (apply #'message (propertize (concat "* %.06f:%s" (if (not absolute?) ":") text) @@ -38,14 +55,19 @@ ":") args))) +;; This is a macro instead of a function to prevent the potentially expensive +;; evaluation of its arguments when debug mode is off. Return non-nil. (defmacro doom-log (message &rest args) - "Log a message in *Messages*. - -Does not emit the message in the echo area. This is a macro instead of a -function to prevent the potentially expensive evaluation of its arguments when -debug mode is off. Return non-nil." + "Log a message to stderr or *Messages* (without displaying in the echo area)." (declare (debug t)) - `(unless doom-inhibit-log (doom--log ,message ,@args))) + (let ((level (if (integerp message) + (prog1 message + (setq message (pop args))) + 2))) + `(when (and (not doom-inhibit-log) + (or (not noninteractive) + (<= ,level doom-log-level))) + (doom--log ,level ,message ,@args)))) ;; From 4ca5819532a440575411462f986b3844d987f549 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 14:12:04 -0400 Subject: [PATCH 10/25] fix(lib): file!: lower current-load-list priority Also changes it to consider base buffer's filename (for `eval` contexts). --- lisp/doom-lib.el | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lisp/doom-lib.el b/lisp/doom-lib.el index 6a354c28c..e8418b11f 100644 --- a/lisp/doom-lib.el +++ b/lisp/doom-lib.el @@ -312,14 +312,13 @@ TRIGGER-HOOK is a list of quoted hooks and/or sharp-quoted functions." (defmacro file! () "Return the file of the file this macro was called." - (or - ;; REVIEW: Use `macroexp-file-name' once 27 support is dropped. - (let ((file (car (last current-load-list)))) - (if (stringp file) file)) - (bound-and-true-p byte-compile-current-file) - load-file-name - buffer-file-name ; for `eval' - (error "file!: cannot deduce the current file path"))) + (or (bound-and-true-p byte-compile-current-file) + load-file-name + (buffer-file-name (buffer-base-buffer)) ; for `eval' + ;; REVIEW: Use `macroexp-file-name' once 27 support is dropped. + (let ((file (car (last current-load-list)))) + (if (stringp file) file)) + (error "file!: cannot deduce the current file path"))) (defmacro dir! () "Return the directory of the file in which this macro was called." From a974210605e21451eab1af5ad9ee6bf3bcec8e64 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 14:12:45 -0400 Subject: [PATCH 11/25] refactor(lib): letf!: use define-advice & split defun/defun* --- lisp/doom-lib.el | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/lisp/doom-lib.el b/lisp/doom-lib.el index e8418b11f..b253bf6eb 100644 --- a/lisp/doom-lib.el +++ b/lisp/doom-lib.el @@ -360,16 +360,33 @@ NAME, ARGLIST, and BODY are the same as `defun', `defun*', `defmacro', and (setq body (pcase type (`defmacro `(cl-macrolet ((,@rest)) ,body)) - (`defadvice `(progn (defadvice! ,@rest) - (unwind-protect ,body (undefadvice! ,@rest)))) - ((or `defun `defun*) + (`defadvice + (if (keywordp (cadr rest)) + (cl-destructuring-bind (target where fn) rest + `(when-let (fn ,fn) + (advice-add ,target ,where fn) + (unwind-protect ,body (advice-remove ,target fn)))) + (let* ((fn (pop rest)) + (argspec (pop rest))) + (when (< (length argspec) 3) + (setq argspec + (list (nth 0 argspec) + (nth 1 argspec) + (or (nth 2 argspec) (gensym (format "%s-a" (symbol-name fn))))))) + (let ((name (nth 2 argspec))) + `(progn + (define-advice ,fn ,argspec ,@rest) + (unwind-protect ,body + (advice-remove #',fn #',name) + ,(if name `(fmakunbound ',name)))))))) + (`defun `(cl-letf ((,(car rest) (symbol-function #',(car rest)))) (ignore ,(car rest)) - ,(if (eq type 'defun*) - `(cl-labels ((,@rest)) ,body) - `(cl-letf (((symbol-function #',(car rest)) - (lambda! ,(cadr rest) ,@(cddr rest)))) - ,body)))) + (cl-letf (((symbol-function #',(car rest)) + (lambda! ,(cadr rest) ,@(cddr rest)))) + ,body))) + (`defun* + `(cl-labels ((,@rest)) ,body)) (_ (when (eq (car-safe type) 'function) (setq type (list 'symbol-function type))) From 70bfb9f0e92c853d72f5614a1a2a67474c97b8fa Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 14:53:22 -0400 Subject: [PATCH 12/25] docs: letf!: add demo & rewrite docstring --- lisp/demos.org | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ lisp/doom-lib.el | 26 ++++++++++--------- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/lisp/demos.org b/lisp/demos.org index 3572ce417..dd10ae570 100644 --- a/lisp/demos.org +++ b/lisp/demos.org @@ -361,6 +361,71 @@ Or to create aliases for functions that behave differently: (:baz hello :boop nil) (:bar 42))) #+end_src +* letf! +:PROPERTIES: +:added: 3.0.0-pre +:END: +#+begin_src emacs-lisp :eval yes +(letf! (defun greet (name) + (message "Hello %s" name)) + (greet "Doom")) ; #=> Hello Doom +#+end_src + +#+RESULTS: +: Hello Doom + +Multiple definitions: +#+begin_src emacs-lisp :eval yes :results output +(letf! ((defun greet (name) + (princ (format "Hello %s" name)) + (terpri)) + (defun destroy (name) + (princ (format "Blood for the %s god!" name)) + (terpri))) + (greet "Doom") + (destroy "Doom")) +#+end_src + +#+RESULTS: +: Hello Doom +: Blood for the Doom god! + +If defining an already-existing function, the old definition will be bound to a +variable by the same name: +#+begin_src emacs-lisp :eval yes :results output +(letf! (defun princ (str) + (funcall princ (format "[overwritten] %s" str))) + (princ "Doom Emacs")) +#+end_src + +#+RESULTS: +: [overwritten] Doom Emacs + +Defining temporary advice: +#+begin_src emacs-lisp :eval yes +(letf! ((defun advised-message (fn message &rest args) + (apply fn (concat "[advised (1)] " message) args)) + (defadvice #'message :around #'advised-message) + (defadvice message (:around (fn message &rest args)) + (apply fn (concat "[advised (2)] " message) args))) + (message "Hello world")) +#+end_src + +#+RESULTS: +: [advised (1)] [advised (2)] Hello world + +Calling "lexical" functions recursively: +#+begin_src emacs-lisp :eval yes +(letf! (defun* triangle (number) + (cond ((<= number 0) 0) + ((= number 1) 1) + ((> number 1) + (+ number (triangle (1- number)))))) + (triangle 5)) +#+end_src + +#+RESULTS: +: 15 * load! :PROPERTIES: diff --git a/lisp/doom-lib.el b/lisp/doom-lib.el index b253bf6eb..31b7851e1 100644 --- a/lisp/doom-lib.el +++ b/lisp/doom-lib.el @@ -332,24 +332,26 @@ TRIGGER-HOOK is a list of quoted hooks and/or sharp-quoted functions." "Temporarily rebind function, macros, and advice in BODY. Intended as syntax sugar for `cl-letf', `cl-labels', `cl-macrolet', and -temporary advice. +temporary advice (`define-advice'). BINDINGS is either: - A list of, or a single, `defun', `defun*', `defmacro', or `defadvice' forms. A list of (PLACE VALUE) bindings as `cl-letf*' would accept. + A list of, or a single, `defun', `defun*', `defmacro', or `defadvice' forms. -TYPE is one of: +The def* forms accepted are: - `defun' (uses `cl-letf') - `defun*' (uses `cl-labels'; allows recursive references), - `defmacro' (uses `cl-macrolet') - `defadvice' (uses `defadvice!' before BODY, then `undefadvice!' after) - -NAME, ARGLIST, and BODY are the same as `defun', `defun*', `defmacro', and -`defadvice!', respectively. - -\(fn ((TYPE NAME ARGLIST &rest BODY) ...) BODY...)" + (defun NAME (ARGS...) &rest BODY) + Defines a temporary function with `cl-letf' + (defun* NAME (ARGS...) &rest BODY) + Defines a temporary function with `cl-labels' (allows recursive + definitions). + (defmacro NAME (ARGS...) &rest BODY) + Uses `cl-macrolet'. + (defadvice FUNCTION WHERE ADVICE) + Uses `advice-add' (then `advice-remove' afterwards). + (defadvice FUNCTION (HOW LAMBDA-LIST &optional NAME DEPTH) &rest BODY) + Defines temporary advice with `define-advice'." (declare (indent defun)) (setq body (macroexp-progn body)) (when (memq (car bindings) '(defun defun* defmacro defadvice)) From 19d68887b10e47d7e9f7c87c2f6e65c8db372dbc Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 14:56:07 -0400 Subject: [PATCH 13/25] refactor: remove redundant auto-mode-alist entries I moved these into lisp/init.el in e02d3c7, but didn't remove the old forms (though they weren't doing anything, anyway). Amend: e02d3c79a940 --- lisp/doom-start.el | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lisp/doom-start.el b/lisp/doom-start.el index 2f0c14efb..3cc4b950a 100644 --- a/lisp/doom-start.el +++ b/lisp/doom-start.el @@ -143,11 +143,6 @@ (setq selection-coding-system 'utf-8)) -;;; Support for Doom-specific file extensions -(add-to-list 'auto-mode-alist '("/\\.doom\\(?:project\\|module\\|profile\\)\\'" . lisp-data-mode)) -(add-to-list 'auto-mode-alist '("/\\.doomrc\\'" . emacs-lisp-mode)) - - ;; ;;; MODE-local-vars-hook From de6a077669450b937909d003718441170f91c43c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 15:00:07 -0400 Subject: [PATCH 14/25] fix: early-init.el: don't suppress legit file errors The NOERROR argument on `load` no only suppress file-missing errors, but file permission errors, so I avoided it. However, if any `require` *inside* `doom.el` throws `file-missing`, this bootstrapper will assume this means we're loading a non-Doom config. --- early-init.el | 55 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/early-init.el b/early-init.el index 9d6778109..277eeecb0 100644 --- a/early-init.el +++ b/early-init.el @@ -105,38 +105,37 @@ ;; To reduce that burden -- and since Doom doesn't load any dynamic modules ;; this early -- I remove `.so' from `load-suffixes' and pass the ;; `must-suffix' arg to `load'. See the docs of `load' for details. - (if (let ((load-suffixes '(".elc" ".el"))) + (if (let ((load-suffixes '(".elc" ".el")) + (doom-file (expand-file-name "lisp/doom" user-emacs-directory))) ;; I avoid `load's NOERROR argument because it suppresses other, ;; legitimate errors (like permission or IO errors), which gets ;; incorrectly interpreted as "this is not a Doom config". - (condition-case-unless-debug _ + (if (file-exists-p (concat doom-file ".el")) ;; Load the heart of Doom Emacs. - (load (expand-file-name "lisp/doom" user-emacs-directory) - nil (not init-file-debug) nil 'must-suffix) - ;; Failing that, assume that we're loading a non-Doom config. - (file-missing - ;; HACK: `startup--load-user-init-file' resolves $EMACSDIR from a - ;; lexical (and so, not-trivially-modifiable) - ;; `startup-init-directory', so Emacs will fail to locate the - ;; correct $EMACSDIR/init.el without help. - (define-advice startup--load-user-init-file (:filter-args (args) reroute-to-profile) - (list (lambda () (expand-file-name "init.el" user-emacs-directory)) - nil (nth 2 args))) - ;; (Re)set `user-init-file' for the `load' call further below, and - ;; do so here while our `file-name-handler-alist' optimization is - ;; still effective (benefits `expand-file-name'). BTW: Emacs resets - ;; `user-init-file' and `early-init-file' after this file is loaded. - (setq user-init-file (expand-file-name "early-init" user-emacs-directory)) - ;; COMPAT: I make no assumptions about the config we're going to - ;; load, so undo this file's global side-effects. - (setq load-prefer-newer t) - ;; PERF: But make an exception for `gc-cons-threshold', which I - ;; think all Emacs users and configs will benefit from. Still, - ;; setting it to `most-positive-fixnum' is dangerous if downstream - ;; does not reset it later to something reasonable, so I use 16mb - ;; as a best fit guess. It's better than Emacs' 80kb default. - (setq gc-cons-threshold (* 16 1024 1024)) - nil))) + (load doom-file nil (not init-file-debug) nil 'must-suffix) + ;; Failing that, assume we're loading a non-Doom config... + ;; HACK: `startup--load-user-init-file' resolves $EMACSDIR from a + ;; lexical (and so, not-trivially-modifiable) + ;; `startup-init-directory', so Emacs will fail to locate the + ;; correct $EMACSDIR/init.el without help. + (define-advice startup--load-user-init-file (:filter-args (args) reroute-to-profile) + (list (lambda () (expand-file-name "init.el" user-emacs-directory)) + nil (nth 2 args))) + ;; (Re)set `user-init-file' for the `load' call further below, and do + ;; so here while our `file-name-handler-alist' optimization is still + ;; effective (benefits `expand-file-name'). BTW: Emacs resets + ;; `user-init-file' and `early-init-file' after this file is loaded. + (setq user-init-file (expand-file-name "early-init" user-emacs-directory)) + ;; COMPAT: I make no assumptions about the config we're going to + ;; load, so undo this file's global side-effects. + (setq load-prefer-newer t) + ;; PERF: But make an exception for `gc-cons-threshold', which I think + ;; all Emacs users and configs will benefit from. Still, setting it + ;; to `most-positive-fixnum' is dangerous if downstream does not + ;; reset it later to something reasonable, so I use 16mb as a best + ;; fit guess. It's better than Emacs' 80kb default. + (setq gc-cons-threshold (* 16 1024 1024)) + nil)) ;; ...Otherwise, we're loading a Doom config, so continue as normal. (doom-require (if noninteractive 'doom-cli 'doom-start)))) From 3256fc7fca470f5ea3b9cbe4684c5a168b907e83 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 15:05:01 -0400 Subject: [PATCH 15/25] fix: trigger defcustom setters in files opened from command-line --- lisp/doom.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lisp/doom.el b/lisp/doom.el index c85ffbc21..9e9873ddd 100644 --- a/lisp/doom.el +++ b/lisp/doom.el @@ -470,6 +470,9 @@ users).") (add-hook! 'doom-before-init-hook (defun doom--reset-custom-dont-initialize-h () (setq custom-dont-initialize nil))) + (define-advice command-line-1 (:around (fn args-left) respect-defcustom-setters) + (let ((custom-dont-initialize nil)) + (funcall fn args-left))) ;; These optimizations are brittle, difficult to debug, and obscure other ;; issues, so bow out when debug mode is on. From 9bd9d5535416946d9d7adb07e2d55d5fb85a1f30 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 15:05:54 -0400 Subject: [PATCH 16/25] fix(lib): define doom-context-error --- lisp/doom-lib.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/doom-lib.el b/lisp/doom-lib.el index 31b7851e1..b5561ebf8 100644 --- a/lisp/doom-lib.el +++ b/lisp/doom-lib.el @@ -7,6 +7,7 @@ (define-error 'doom-font-error "Could not find a font on your system" 'doom-error) (define-error 'doom-nosync-error "Doom hasn't been initialized yet; did you remember to run 'doom sync' in the shell?" 'doom-error) (define-error 'doom-core-error "Unexpected error in Doom's core" 'doom-error) +(define-error 'doom-context-error "Incorrect context error" 'doom-error) (define-error 'doom-hook-error "Error in a Doom startup hook" 'doom-error) (define-error 'doom-autoload-error "Error in Doom's autoloads file" 'doom-error) (define-error 'doom-user-error "Error caused by user's config or system" 'doom-error) From 1dc606bb279146ac32aa8dfbe86dc839fa6f8b3e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 17:10:00 -0400 Subject: [PATCH 17/25] fix(file-templates): __doom-readme: use doom-modules-version --- modules/editor/file-templates/templates/org-mode/__doom-readme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/editor/file-templates/templates/org-mode/__doom-readme b/modules/editor/file-templates/templates/org-mode/__doom-readme index ffe6fd092..19a6a2edd 100644 --- a/modules/editor/file-templates/templates/org-mode/__doom-readme +++ b/modules/editor/file-templates/templates/org-mode/__doom-readme @@ -7,7 +7,7 @@ #+title: `(+file-templates-module-for-path)` #+subtitle: #+created: `(format-time-string "%B %d, %Y")` -#+since: `(car (split-string doom-version "-"))` (#COMMIT-OR-PR-REF) +#+since: `(car (split-string doom-modules-version "-"))` (#COMMIT-OR-PR-REF) * Description :unfold: $0Replace this with a short (1-2 sentence) description of what this module does. From f27a85ed354fa146a218fc2d26604317c9cc4723 Mon Sep 17 00:00:00 2001 From: Ag Ibragimov Date: Wed, 11 Sep 2024 17:18:01 -0400 Subject: [PATCH 18/25] module: add :emacs eww Close: #6866 Co-authored-by: hlissner --- modules/emacs/eww/README.org | 55 +++++++++++++++ modules/emacs/eww/autoload.el | 128 ++++++++++++++++++++++++++++++++++ modules/emacs/eww/config.el | 48 +++++++++++++ modules/emacs/eww/packages.el | 4 ++ templates/init.example.el | 3 +- 5 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 modules/emacs/eww/README.org create mode 100644 modules/emacs/eww/autoload.el create mode 100644 modules/emacs/eww/config.el create mode 100644 modules/emacs/eww/packages.el diff --git a/modules/emacs/eww/README.org b/modules/emacs/eww/README.org new file mode 100644 index 000000000..c09b07927 --- /dev/null +++ b/modules/emacs/eww/README.org @@ -0,0 +1,55 @@ +:PROPERTIES: +:ID: 4f6e0ee2-7837-4d15-853f-c8863d065f21 +:END: +#+title: :emacs eww +#+subtitle: The internet is gross +#+created: September 11, 2024 +#+since: 24.10 + +* Description :unfold: +This module augments eww (Emacs Web Wowser); Emacs' built-in web browser, with +some reasonable defaults and helper commands. + +** Maintainers +/This module has no dedicated maintainers./ [[doom-contrib-maintainer:][Become a maintainer?]] + +** Module flags +/This module has no flags./ + +** Packages +/This module doesn't install any packages./ + +** Hacks +- The buffer is renamed to match the current page's URL or title. + +** TODO Changelog +# This section will be machine generated. Don't edit it by hand. +/This module does not have a changelog yet./ + +* Installation +[[id:01cffea4-3329-45e2-a892-95a384ab2338][Enable this module in your ~doom!~ block.]] + +/This module has no external requirements./ + +* Usage +#+begin_quote +󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] +#+end_quote + +Type ~M-x eww~ and enter an URL. + +* TODO Configuration +#+begin_quote +󱌣 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]] +#+end_quote + +* Troubleshooting +/There are no known problems with this module./ [[doom-report:][Report one?]] + +* Frequently asked questions +/This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]] + +* TODO Appendix +#+begin_quote +󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]] +#+end_quote diff --git a/modules/emacs/eww/autoload.el b/modules/emacs/eww/autoload.el new file mode 100644 index 000000000..b83c551a0 --- /dev/null +++ b/modules/emacs/eww/autoload.el @@ -0,0 +1,128 @@ +;;; emacs/eww/autoload.el -*- lexical-binding: t; -*- + +;; NOTE: Many of these functions were adapted from Protesilaos Stavrou's +;; dotfiles. See https://protesilaos.com/codelog/2021-03-25-emacs-eww + +;; Adapted from `prot-eww-jump-to-url-on-page' +(defun eww--capture-url-on-page (&optional position) + "Capture all the links on the current web page. + +Return a list of strings. Strings are in the form LABEL @ URL. +When optional argument POSITION is non-nil, include position info in the strings +too, so strings take the form: LABEL @ URL ~ POSITION." + (let (links match) + (save-excursion + (goto-char (point-max)) + ;; NOTE 2021-07-25: The first clause in the `or' is meant to address a bug + ;; where if a URL is in `point-min' it does not get captured. + (while (setq match (text-property-search-backward 'shr-url)) + (let* ((raw-url (prop-match-value match)) + (start-point-prop (prop-match-beginning match)) + (end-point-prop (prop-match-end match)) + (url (when (stringp raw-url) + (propertize raw-url 'face 'link))) + (label (replace-regexp-in-string + "\n" " " ; NOTE 2021-07-25: newlines break completion + (buffer-substring-no-properties + start-point-prop end-point-prop))) + (point start-point-prop) + (line (line-number-at-pos point t)) + (column (save-excursion (goto-char point) (current-column))) + (coordinates (propertize + (format "%d,%d (%d)" line column point) + 'face 'shadow))) + (when url + (push (if position + (format "%-15s ~ %s @ %s" coordinates label url) + (format "%s @ %s" label url)) + links))))) + links)) + +;; Adapted from `prot-eww--rename-buffer' +(defun +eww-page-title-or-url (&rest _) + (let ((prop (if (string-empty-p (plist-get eww-data :title)) :url :title))) + (format "*%s # eww*" (plist-get eww-data prop)))) + + +;; +;;; Commands + +;; Adapted from `prot-eww-quit' +;;;###autoload +(defun +eww/quit () + "Quit eww and kill all its buffers." + (interactive nil 'eww-mode) + (when (yes-or-no-p "Are you sure you want to quit eww?") + (save-match-data + (cl-loop with case-fold-search = t + for buf in (doom-buffer-list) + if (with-current-buffer buf + (or (eq major-mode 'eww-mode) + (and (derived-mode-p 'special-mode) + (string-match "\\*.*eww.*\\*" (buffer-name))))) + do (kill-buffer buf))))) + +;; Adapted from `prot-eww-jump-to-url-on-page' +;;;###autoload +(defun +eww/jump-to-url-on-page (&optional arg) + "Jump to URL position on the page using completion. + +When called without ARG (\\[universal-argument]) get URLs only +from the visible portion of the buffer. But when ARG is provided +consider whole buffer." + (interactive "P" 'eww-mode) + (unless (derived-mode-p 'eww-mode) + (user-error "Not in an eww buffer!")) + (let* ((links + (if arg + (eww--capture-url-on-page t) + (save-restriction + (if (use-region-p) + (narrow-to-region (region-beginning) (region-end)) + (narrow-to-region (window-start) (window-end))) + (eww--capture-url-on-page t)))) + (prompt-scope (if arg + (propertize "URL on the page" 'face 'warning) + "visible URL")) + (prompt (format "Jump to %s: " prompt-scope)) + (selection (completing-read prompt links nil t)) + (position (replace-regexp-in-string "^.*(\\([0-9]+\\))[\s\t]+~" "\\1" selection)) + (point (string-to-number position))) + (goto-char point) + (recenter))) + +;; Adapted from `prot-eww-open-in-other-window' +;;;###autoload +(defun +eww/open-in-other-window () + "Use `eww-open-in-new-buffer' in another window." + (interactive nil 'ewe-mode) + (other-window-prefix) + (eww-open-in-new-buffer)) + +;;;###autoload +(defun +eww/copy-current-url () + "Copy the open page's URL to the kill ring." + (interactive nil 'eww-mode) + (let ((url (eww-current-url))) + (kill-new url) + (message url))) + +;;;###autoload +(defun +eww/increase-font-size () + "Increase the font size in `eww-mode'." + (interactive nil 'eww-mode) + (if shr-use-fonts + (let* ((cur (face-attribute 'shr-text :height nil)) + (cur (if (floatp cur) cur 1.0))) + (set-face-attribute 'shr-text nil :height (+ cur 0.1))) + (text-scale-increase 0.5))) + +;;;###autoload +(defun +eww/decrease-font-size () + "Decrease the font size in `eww-mode'." + (interactive nil 'eww-mode) + (if shr-use-fonts + (let* ((cur (face-attribute 'shr-text :height nil)) + (cur (if (floatp cur) cur 1.0))) + (set-face-attribute 'shr-text nil :height (- cur 0.1))) + (text-scale-decrease 0.5))) diff --git a/modules/emacs/eww/config.el b/modules/emacs/eww/config.el new file mode 100644 index 000000000..37c168035 --- /dev/null +++ b/modules/emacs/eww/config.el @@ -0,0 +1,48 @@ +;;; emacs/eww/config.el -*- lexical-binding: t; -*- + +(use-package! eww + :defer t + :config + (map! :map eww-mode-map + [remap text-scale-increase] #'+eww/increase-font-size + [remap text-scale-decrease] #'+eww/decrease-font-size + [remap imenu] #'+eww/jump-to-url-on-page + [remap quit-window] #'+eww/quit + :ni [C-return] #'+eww/open-in-other-window + :n "yy" #'+eww/copy-current-url + :n "zk" #'text-scale-increase + :n "zj" #'text-scale-decrease + + (:localleader + :desc "external browser" "e" #'eww-browse-with-external-browser + :desc "buffers" "b" #'eww-switch-to-buffer + + (:prefix ("t" . "toggle") + :desc "readable" "r" #'eww-readable + :desc "colors" "c" #'eww-toggle-colors + :desc "fonts" "f" #'eww-toggle-fonts + :desc "images" "i" #'eww-toggle-images) + + (:prefix ("y" . "copy") + :desc "copy url" "y" #'+eww/copy-current-url + :desc "copy for Org" "o" #'org-eww-copy-for-org-mode))) + + ;; HACK: There are packages that use eww to pop up html documentation; we want + ;; those to open in a popup, but if the user calls `eww' directly, it should + ;; open in the current window. + (defadvice! +eww-open-in-fullscreen-if-interactive-a (fn &rest args) + :around #'eww + (if (called-interactively-p 'any) + (apply fn args) + (let (display-buffer-alist) + (apply fn args)))) + + ;; HACK: Rename the eww buffer to match the open page's title or URL. + (if (boundp 'eww-auto-rename-buffer) + (setq eww-auto-rename-buffer #'+eww-page-title-or-url) ; for >=29.1 + ;; REVIEW: Remove when we drop 28 support + (add-hook! 'eww-after-render-hook + (defun +eww--rename-buffer-to-page-title-or-url-h (&rest _) + (rename-buffer (+eww-page-title-or-url)))) + (advice-add #'eww-back-url :after #'+eww--rename-buffer-to-page-title-or-url-h) + (advice-add #'eww-forward-url :after #'+eww--rename-buffer-to-page-title-or-url-h))) diff --git a/modules/emacs/eww/packages.el b/modules/emacs/eww/packages.el new file mode 100644 index 000000000..fd7bf1310 --- /dev/null +++ b/modules/emacs/eww/packages.el @@ -0,0 +1,4 @@ +;; -*- no-byte-compile: t; -*- +;;; emacs/eww/packages.el + +(package! eww :built-in t) diff --git a/templates/init.example.el b/templates/init.example.el index 40a5d4658..187cd99be 100644 --- a/templates/init.example.el +++ b/templates/init.example.el @@ -69,7 +69,8 @@ :emacs dired ; making dired pretty [functional] electric ; smarter, keyword-based electric-indent - ;;ibuffer ; interactive buffer management + ;;eww ; the internet is gross + ;;ibuffer ; interactive buffer management undo ; persistent, smarter undo for your inevitable mistakes vc ; version-control and Emacs, sitting in a tree From 5880348a6c668ca0846289dcff80f7d67cfb3bce Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 17:55:33 -0400 Subject: [PATCH 19/25] perf(cli): doomscript: reduce init time In 4989661, I reduced the init time for bin/doom by eliminating the extra `emacs` call in its shebang. This does the same for bin/doomscript. Ref: 498966179f2e --- bin/doomscript | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/bin/doomscript b/bin/doomscript index 2017a4c23..9babc3030 100755 --- a/bin/doomscript +++ b/bin/doomscript @@ -22,7 +22,16 @@ fi case "$EMACS" in *term*) EMACS=emacs ;; # in {ansi-,v}term - *) EMACS="${EMACS:-emacs}" ;; + *\ *) ;; + *) EMACS="${EMACS:-emacs}" + # Only sanity-check $EMACS if it's a path or executable + if ! type "$EMACS" >/dev/null 2>&1; then + echo "Error: failed to run Emacs with command '$EMACS'" + echo + echo "Are you sure Emacs is installed and in your \$PATH?" + exit 1 + fi >&2 + ;; esac # Careful not to use -Q! It implies --no-site-lisp, which omits the site-lisp @@ -31,17 +40,6 @@ esac # (like Snap or NixOS). emacs="$EMACS -q --no-site-file --batch" -# $TMPDIR (or $TEMP and $TMP on Windows) aren't guaranteed to have values, and -# mktemp isn't available on all systems, but you know what is? Emacs! So I rely -# on it to provide TMPDIR. And can second as a quick existence check for Emacs. -TMPDIR="${TMPDIR:-$($emacs --eval '(princ (temporary-file-directory))' 2>/dev/null)}" -if [ -z "$TMPDIR" ]; then - echo "Error: failed to run Emacs with command '$EMACS'" - echo - echo "Are you sure Emacs is installed and in your \$PATH?" - exit 1 -fi >&2 - # Doom respects $EMACSDIR to tell it where Doom lives. If it fails, then this is # either isn't bash, or it's a posix shell being directly sourced with sh, which # is unsupported. @@ -79,6 +77,11 @@ exit=$? # To simulate execve syscalls (which replaces the running process), Doom # generates a temporary exit-script if a Doomscript returns a 254 exit code. if [ "${exit:-0}" -eq 254 ]; then + # $TMPDIR (or $TEMP and $TMP on Windows) aren't guaranteed to have values, + # and mktemp isn't available on all systems, but you know what is? Emacs! So + # I rely on it to provide TMPDIR. + export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-$($emacs -Q --eval '(princ (temporary-file-directory))' 2>/dev/null)}}}" + # The user may have a noexec flag set on /tmp, so the exit-script should be # passed to /bin/sh rather than executed directly. sh "${TMPDIR}/doom.${__DOOMPID}.${__DOOMSTEP}.sh" "$0" "$@" From b853c4106a44c4be8f31b72023428e04c79c1f03 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 17:58:27 -0400 Subject: [PATCH 20/25] fix(default): SPC g r: revert without prompting to save Will save-then-revert now, instead of first prompting to save a modified buffer before reverting. --- modules/config/default/+evil-bindings.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/config/default/+evil-bindings.el b/modules/config/default/+evil-bindings.el index f6f2832e0..55e94f3ce 100644 --- a/modules/config/default/+evil-bindings.el +++ b/modules/config/default/+evil-bindings.el @@ -511,8 +511,8 @@ :desc "Copy link to homepage" "Y" #'+vc/browse-at-remote-kill-homepage :desc "Git time machine" "t" #'git-timemachine-toggle (:when (modulep! :ui vc-gutter) - :desc "Revert hunk at point" "r" #'+vc-gutter/revert-hunk - :desc "stage hunk at point" "s" #'+vc-gutter/stage-hunk + :desc "Revert hunk at point" "r" #'+vc-gutter/save-and-revert-hunk + :desc "Stage hunk at point" "s" #'+vc-gutter/stage-hunk :desc "Jump to next hunk" "]" #'+vc-gutter/next-hunk :desc "Jump to previous hunk" "[" #'+vc-gutter/previous-hunk) (:when (modulep! :tools magit) From bd140955164ca854450c52f4b5c4ca9e0f5c878b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 18:30:48 -0400 Subject: [PATCH 21/25] fix(ligatures): lisp modes disobeying null +ligatures-extra-symbols Fix: #7440 --- modules/ui/ligatures/config.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/ui/ligatures/config.el b/modules/ui/ligatures/config.el index abed3896e..e3236227b 100644 --- a/modules/ui/ligatures/config.el +++ b/modules/ui/ligatures/config.el @@ -124,6 +124,11 @@ and cannot run in." (setq prettify-symbols-unprettify-at-point 'right-edge) (when (modulep! +extra) + ;; Lisp modes offer their own defaults for `prettify-symbols-mode' (just a + ;; lambda symbol substitution), but this might be unexpected if the user + ;; enables +extra but has unset `+ligatures-extra-symbols'. + (setq lisp-prettify-symbols-alist nil) + (add-hook 'after-change-major-mode-hook #'+ligatures-init-extra-symbols-h)) (cond From 288b6dc962d76412a2c7db825d7dadc829945460 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 20:02:34 -0400 Subject: [PATCH 22/25] fix(cli): doom run: symlinks to XDG dirs beyond $HOME The targets for $XDG_*_HOME symlinks weren't created correctly if they were set to an absolute path outside of the user's $HOME. Fix: #8062 --- lisp/cli/run.el | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lisp/cli/run.el b/lisp/cli/run.el index 1d4699056..8819f3e3c 100644 --- a/lisp/cli/run.el +++ b/lisp/cli/run.el @@ -43,7 +43,7 @@ performance, it is best to run Doom out of ~/.config/emacs or ~/.emacs.d." ;; Evaluate piped-in text directly, if given. (eval (read input) t) (doom-run-repl context)) - (let* ((tempdir (doom-path (temporary-file-directory) "doom.run")) + (let* ((tempdir (doom-path (temporary-file-directory) "doom.run")) (tempemacsdir (doom-path tempdir ".emacs.d"))) (delete-directory tempdir t) ; start from scratch (make-directory tempemacsdir t) @@ -51,18 +51,20 @@ performance, it is best to run Doom out of ~/.config/emacs or ~/.emacs.d." ;; configs, or binscripts, we symlink these to the sandbox. ;; REVIEW: Use `--init-directory' when we drop 29 support OR when Doom is ;; in bootloader mode. - (dolist (dir (list (or (getenv "XDG_DATA_HOME") "~/.local/share") - (or (getenv "XDG_BIN_HOME") "~/.local/bin") - (or (getenv "XDG_CONFIG_HOME") "~/.config") - (or (getenv "XDG_CACHE_HOME") "~/.cache"))) - (let* ((xdg-dir (doom-path dir)) - (target (doom-path tempdir (file-relative-name xdg-dir "~")))) - (when (file-directory-p xdg-dir) + (dolist (dir (list (cons "XDG_DATA_HOME" ".local/share") + (cons "XDG_STATE_HOME" ".local/state") + (cons "XDG_BIN_HOME" ".local/bin") + (cons "XDG_CONFIG_HOME" ".config") + (cons "XDG_CACHE_HOME" ".cache"))) + (let* ((source (expand-file-name (or (getenv (car dir)) (expand-file-name (cdr dir) "~")))) + (target (expand-file-name (cdr dir) tempdir))) + (when (file-directory-p source) (unless (file-symlink-p target) (make-directory (file-name-directory target) t) - (make-symbolic-link xdg-dir target))))) + (make-symbolic-link source target))))) (with-temp-file (doom-path tempemacsdir "early-init.el") (prin1 `(progn + ;; Restore sane values for these envvars (setenv "HOME" ,(getenv "HOME")) (setenv "EMACSDIR" ,doom-emacs-dir) (setenv "DOOMDIR" ,doom-user-dir) From 37dbc9977878a30ac57031dbe164d8aad545e701 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 11 Sep 2024 20:41:13 -0400 Subject: [PATCH 23/25] fix(fold): truncate-string-to-width: type errors In 9a6bcc3, the new default for `truncate-string-ellipsis` was long enough that it could cause `truncate-string-to-width` to error out (see exceeded `truncate-string-to-width`s END-COLUMN argument. Amend: 9a6bcc31f963 Fix: #8044 --- modules/editor/fold/config.el | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/editor/fold/config.el b/modules/editor/fold/config.el index 6bae1a36e..1248f4725 100644 --- a/modules/editor/fold/config.el +++ b/modules/editor/fold/config.el @@ -38,9 +38,6 @@ this." (after! org (setq org-ellipsis +fold-ellipsis)) -(after! mule-util - (setq truncate-string-ellipsis +fold-ellipsis)) - ;; ;;; Packages From be422c451602a6bde61244932cd8043563cc7629 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 12 Sep 2024 03:51:38 -0400 Subject: [PATCH 24/25] fix(graphviz): org babel integration Forgot that `ob-dot.el` exists in Org. I blindly expected the `graphviz-dot-mode` package to provide babel support in f6b7e8a. Also, `org-src-lang-modes` expects its CDRs to omit the -mode suffix, which should fix syntax highlighting of graphviz/dot babel blocks. Amend: f6b7e8ae4807 Ref: #7546 --- modules/lang/graphviz/config.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/lang/graphviz/config.el b/modules/lang/graphviz/config.el index 7104997f7..38e7c6fcc 100644 --- a/modules/lang/graphviz/config.el +++ b/modules/lang/graphviz/config.el @@ -4,8 +4,7 @@ :mode "\\.\\(?:nw\\|rack\\)diag\\'" :init (after! org-src - (add-to-list '+org-babel-mode-alist '(dot . graphviz-dot-mode)) - (add-to-list 'org-src-lang-modes '("dot" . graphviz-dot-mode))) + (add-to-list 'org-src-lang-modes '("dot" . graphviz-dot))) :config (set-company-backend! 'graphviz-dot-mode 'company-graphviz-dot-backend) (set-formatter! 'graphviz-dot #'+graphviz-formatter :modes '(graphviz-dot-mode)) From 9359a81e8103aa19dba40eff4be802ec55a38e97 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 12 Sep 2024 06:05:28 -0400 Subject: [PATCH 25/25] fix: gui frames fail to open from emacsclient This was a tricky regression to track down. 9753bfb tries to fix an issue where the `default` face's :foreground changes to `#000000` in any new frames created after the initial one (by calling `make-frame`), because those frames' `background-color` and `foreground-color` parameters default to "#000000" (possibly a bug with `disable-theme` too eagerly defaulting them to black). 240493a replaces that with new, seemingly cleaner approach: setting `frame-inherited-parameters`, which instructs `make-frame` to copy those parameters from the last open frame, however, those parameters in the initial daemon frame will be set to "unspecified-bg" or "unspecified-fg" (see the docstring for `face-{back,fore}ground`), which are invalid color strings. `make-frame` crashes tries to create a frame with those color values, causing #8059. Fix: #8059 Amend: 240493ae9235 Amend: 9753bfb775d0 --- lisp/doom-ui.el | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lisp/doom-ui.el b/lisp/doom-ui.el index e321d6137..dbfa2064e 100644 --- a/lisp/doom-ui.el +++ b/lisp/doom-ui.el @@ -284,14 +284,6 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original (setq split-width-threshold 160 split-height-threshold nil) -;; Fix incorrect fg/bg in new frames created after the initial frame -;; (which are reroneously displayed as black). -(setq frame-inherited-parameters '(background-color - foreground-color - cursor-color - border-color - mouse-color)) - ;; ;;; Minibuffer @@ -597,7 +589,19 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original (setq doom-theme theme) (put 'doom-theme 'previous-themes (or last-themes 'none)) ;; DEPRECATED Hook into `enable-theme-functions' when we target 29 - (doom-run-hooks 'doom-load-theme-hook)))))) + (doom-run-hooks 'doom-load-theme-hook) + ;; Fix incorrect fg/bg in new frames created after the initial frame + ;; (which are reroneously displayed as black). + (pcase-dolist (`(,param ,fn ,face) + '((foreground-color face-foreground default) + (background-color face-background default) + (cursor-color face-background cursor) + (border-color face-background border) + (mouse-color face-background mouse))) + (when-let* ((color (funcall fn face nil t)) + ((stringp color)) + ((not (string-prefix-p "unspecified-" color)))) + (setf (alist-get param default-frame-alist) color)))))))) ;;