diff --git a/README.md b/README.md index 40f5211b8..6367189bc 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [Install](#install) • [Documentation] • [FAQ] • [Screenshots] • [Contribute](#contribute) ![Made with Doom Emacs](https://img.shields.io/github/tag/doomemacs/doomemacs.svg?style=flat-square&label=release&color=58839b) -![Supports Emacs 27.1–29.2](https://img.shields.io/badge/Supports-Emacs_27.1–29.2-blueviolet.svg?style=flat-square&logo=GNU%20Emacs&logoColor=white) +![Supports Emacs 27.1–29.3](https://img.shields.io/badge/Supports-Emacs_27.1–29.3-blueviolet.svg?style=flat-square&logo=GNU%20Emacs&logoColor=white) ![Latest commit](https://img.shields.io/github/last-commit/doomemacs/doomemacs/master?style=flat-square) ![Build status: master](https://img.shields.io/github/workflow/status/doomemacs/doomemacs/CI/master?style=flat-square) [![Discord Server](https://img.shields.io/discord/406534637242810369?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)][Discord] @@ -99,7 +99,7 @@ Check out [the FAQ][FAQ] for answers to common questions about the project. # Prerequisites - Git 2.23+ -- Emacs 27.1–29.2 (**Recommended: 29.2 + +- Emacs 27.1–29.3 (**Recommended: 29.3 + [native-comp](https://www.emacswiki.org/emacs/GccEmacs)**) - [ripgrep] 11.0+ - GNU `find` @@ -138,8 +138,6 @@ commands you should know about: + `doom env` to dump a snapshot of your shell environment to a file that Doom will load at startup. This allows Emacs to inherit your `PATH`, among other things. -+ `doom build` to recompile all installed packages (use this if you up/downgrade - Emacs). # Roadmap diff --git a/bin/doom b/bin/doom index f9d1841e6..32504f224 100755 --- a/bin/doom +++ b/bin/doom @@ -89,9 +89,9 @@ (user-error (message "Error: %s" (cadr e)) (kill-emacs 2))) -;; UX: Abort if the user is using 'doom' as root, unless ~/.config/emacs is -;; owned by root, in which case we assume the user genuinely wants root to be -;; their primary user account for Emacs. +;; UX: Abort if the user is using 'doom' as root, unless $EMACSDIR is owned by +;; root, in which case we can safely assume the user genuinely wants root to +;; be their primary user account for this session. (when (equal 0 (user-real-uid)) (unless (equal 0 (file-attribute-user-id (file-attributes doom-emacs-dir))) (message @@ -271,10 +271,8 @@ SEE ALSO: (defcli-autoload! ((profiles profile))) (defcli-autoload! ((upgrade up))) (defcli-autoload! (env)) - (defcli-autoload! ((build b purge p rollback)) "packages") + (defcli-autoload! ((build b purge p gc rollback)) "packages") (defcli-autoload! ((install i))) - (defcli-autoload! ((compile c))) - (defcli-autoload! (clean) "compile") ;; TODO Post-3.0 commands ;; (load! "gc" dir) @@ -282,8 +280,6 @@ SEE ALSO: ;; (load! "nuke" dir) ;; (load! "package" dir) ;; (load! "profile" dir) - ;; (defcli-obsolete! ((compile c)) (sync "--compile") "v3.0.0") - ;; (defcli-obsolete! ((build b)) (sync "--rebuild") "v3.0.0") ) (defcli-group! "Diagnostics" diff --git a/docs/faq.org b/docs/faq.org index 480ae45a0..5179ccb86 100644 --- a/docs/faq.org +++ b/docs/faq.org @@ -402,14 +402,13 @@ This command is never needed for changes to =$DOOMDIR/config.el=. ** Copy or sync my config to another system? *Short answer:* it is safe to sync =$DOOMDIR= across systems, but not -=$EMACSDIR=. Once moved, use ~$ doom sync && doom build~ to ensure everything is -set up correctly. +=$EMACSDIR=. Once moved, use ~$ doom sync~ to ensure everything is set up +correctly. *Long answer:* packages can contain baked-in absolute paths and non-portable byte-code. It is never a good idea to mirror it across multiple systems, unless they are all the same (same OS, same version of Emacs, same paths). Most issues -should be solved by running ~$ doom sync && doom build~ on the other end, once -moved. +should be solved by running ~$ doom sync~ on the other end, once moved. ** Start over, in case something went terribly wrong? Delete =$EMACSDIR/.local/straight= and run ~$ doom sync~. diff --git a/lisp/cli/compile.el b/lisp/cli/compile.el deleted file mode 100644 index 88cfed2d9..000000000 --- a/lisp/cli/compile.el +++ /dev/null @@ -1,214 +0,0 @@ -;;; lisp/cli/commands/byte-compile.el -*- lexical-binding: t; -*- - -;; -;;; Variables - -;; None yet! - - -;; -;;; Commands - -(defcli! ((compile c)) - ((recompile-p ("-r" "--recompile")) - (core-p ("-c" "--core")) - (private-p ("-p" "--private")) - (verbose-p ("-v" "--verbose"))) - "Byte-compiles your config or selected modules. - - compile [TARGETS...] - compile :core :user lang/python - compile feature lang - -Accepts :core and :user as special arguments, which target Doom's core files -and your private config files, respectively. To recompile your packages, use -'doom build' instead." - (doom-cli-compile - (if (or core-p private-p) - (append (if core-p (doom-glob doom-emacs-dir "init.el")) - (if core-p (list doom-core-dir)) - (if private-p (list doom-user-dir))) - (or (y-or-n-p - (concat "WARNING: Changes made to your config after compiling it won't take effect until\n" - "this command is rerun or you run 'doom clean'! It will also make error backtraces\n" - "much more difficult to decipher.\n\n" - "If you intend to use it anyway, remember this or it will come back to bite you!\n\n" - "Continue anyway?")) - (user-error "Aborted")) - (append (doom-glob doom-emacs-dir "init.el") - (list doom-core-dir) - (seq-filter - ;; Only compile Doom's modules - (doom-rpartial #'file-in-directory-p doom-emacs-dir) - ;; Omit `doom-user-dir', which is always first - (doom-module-load-path)))) - recompile-p - verbose-p)) - -(defcli! clean () - "Delete all *.elc files." - (doom-compile-clean)) - - -;; -;;; Helpers - -(cl-defun doom-cli-compile (&optional targets recompile-p verbose-p) - "Byte compiles your emacs configuration. - -init.el is always byte-compiled by this. - -If TARGETS is specified, as a list of direcotries - -If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are -byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom -core. It always ignores unit tests and files with `no-byte-compile' enabled. - -WARNING: byte-compilation yields marginal gains and makes debugging new issues -difficult. It is recommended you don't use it unless you understand the -reprecussions. - -Use `doom-compile-clean' or `make clean' to reverse -byte-compilation. - -If RECOMPILE-P is non-nil, only recompile out-of-date files." - (let* ((default-directory doom-emacs-dir) - (targets (nreverse (delete-dups targets))) - ;; In case it is changed during compile-time - (auto-mode-alist auto-mode-alist) - kill-emacs-hook kill-buffer-query-functions) - - (let ((after-load-functions - (if (null targets) - after-load-functions - ;; Assemble el files we want to compile, and preserve in the order - ;; they are loaded in, so we don't run into any scary catch-22s - ;; while byte-compiling, like missing macros. - (cons (let ((target-dirs (seq-filter #'file-directory-p targets))) - (lambda (path) - (and (not (doom-compile--ignore-file-p path)) - (seq-find (doom-partial #'file-in-directory-p path) - target-dirs) - (cl-pushnew path targets)))) - after-load-functions)))) - (doom-log "Reloading Doom in preparation for byte-compilation") - ;; But first we must be sure that Doom and your private config have been - ;; fully loaded. Which usually aren't so in an noninteractive session. - (let ((load-prefer-newer t)) - (require 'doom-start))) - - (if (null targets) - (print! (item "No targets to %scompile" (if recompile-p "re" ""))) - (print! (start "%scompiling your config...") - (if recompile-p "Re" "Byte-")) - - (dolist (dir - (cl-remove-if-not #'file-directory-p targets) - (setq targets (cl-remove-if #'file-directory-p targets))) - (prependq! targets - (doom-files-in - dir :match "\\.el" :filter #'doom-compile--ignore-file-p))) - - (print-group! - (require 'use-package) - (condition-case-unless-debug e - (let* ((total-ok 0) - (total-fail 0) - (total-noop 0) - (byte-compile-verbose nil) - (byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local)) - (byte-compile-dynamic-docstrings t) - (use-package-compute-statistics nil) - (use-package-defaults use-package-defaults) - (use-package-expand-minimally t) - (targets (delete-dups targets)) - (modules (seq-group-by #'doom-module-from-path targets)) - (total-files (length targets)) - (total-modules (length modules)) - (i 0) - last-module) - ;; Prevent packages from being loaded at compile time if they - ;; don't meet their own predicates. - (push (list :no-require t - (lambda (_name args) - (or (when-let (pred (or (plist-get args :if) - (plist-get args :when))) - (not (eval pred t))) - (when-let (pred (plist-get args :unless)) - (eval pred t))))) - use-package-defaults) - (dolist (module-files modules) - (cl-incf i) - (dolist (target (cdr module-files)) - (let ((elc-file (byte-compile-dest-file target))) - (cl-incf - (if (and recompile-p (not (file-newer-than-file-p target elc-file))) - total-noop - (pcase (if (not (doom-file-cookie-p target "if" t)) - 'no-byte-compile - (unless (equal last-module (car module-files)) - (print! (success "(% 3d/%d) Compiling %s") - i total-modules - (if-let (m (caar module-files)) - (format "%s %s module..." m (cdar module-files)) - (format "%d stand alone elisp files..." - (length (cdr module-files)))) - (caar module-files) (cdar module-files)) - (setq last-module (car module-files))) - (if verbose-p - (byte-compile-file target) - (quiet! (byte-compile-file target)))) - (`no-byte-compile - (doom-log "(% 3d/%d) Ignored %s" i total-modules target) - total-noop) - (`nil - (print! (error "(% 3d/%d) Failed to compile %s") - i total-modules (relpath target)) - total-fail) - (_ total-ok))))))) - (print! (class (if (= total-fail 0) 'success 'warn) - "%s %d/%d file(s) (%d ignored)") - (if recompile-p "Recompiled" "Byte-compiled") - total-ok total-files - total-noop) - (= total-fail 0)) - ((debug error) - (print! (error "There were breaking errors.\n\n%s") - "Reverting changes...") - (signal 'doom-error (list 'byte-compile e)))))))) - -(defun doom-compile--ignore-file-p (path) - (let ((filename (file-name-nondirectory path))) - (or (not (equal (file-name-extension path) "el")) - (member filename (list doom-module-packages-file "doctor.el")) - (string-prefix-p "." filename) - (string-prefix-p "test-" filename) - (string-prefix-p "flycheck_" filename) - (string-suffix-p ".example.el" filename)))) - -(defun doom-compile-clean () - "Delete all the compiled elc files in your Emacs configuration and private -module. This does not include your byte-compiled, third party packages.'" - (require 'doom-modules) - (print! (start "Cleaning .elc files")) - (print-group! - (cl-loop with default-directory = doom-emacs-dir - with success = 0 - with esc = (if init-file-debug "" "\033[1A") - for path - in (append (doom-glob doom-emacs-dir "*.elc") - (doom-files-in doom-user-dir :match "\\.elc$" :depth 1) - (doom-files-in doom-core-dir :match "\\.elc$") - (doom-files-in doom-module-load-path :match "\\.elc$" :depth 4)) - if (file-exists-p path) - do (delete-file path) - and do (print! (success "\033[KDeleted %s%s") (relpath path) esc) - and do (cl-incf success) - finally do - (print! (if (> success 0) - (success "\033[K%d elc files deleted" success) - (item "\033[KNo elc files to clean")))) - t)) - -(provide 'doom-cli-compile) -;;; compile.el ends here diff --git a/lisp/cli/help.el b/lisp/cli/help.el deleted file mode 100644 index 0d58aa974..000000000 --- a/lisp/cli/help.el +++ /dev/null @@ -1,466 +0,0 @@ -;;; lisp/cli/help.el -*- lexical-binding: t; -*- -;;; Commentary: -;; -;; This file defines special commands that the Doom CLI will invoke when a -;; command is passed with -?, --help, or --version. They can also be aliased to -;; a sub-command to make more of its capabilities accessible to users, with: -;; -;; (defcli-alias! (myscript (help h)) (:help)) -;; -;; You can define your own command-specific help handlers, e.g. -;; -;; (defcli! (:help myscript subcommand) () ...) -;; -;; And it will be invoked instead of the generic one. -;; -;;; Code: - -;; -;;; Variables - -(defvar doom-help-commands '("%p %c {-?,--help}") - "A list of help commands recognized for the running script. - -Recognizes %p (for the prefix) and %c (for the active command).") - - -;; -;;; Commands - -(defcli! (:root :help) - ((localonly? ("-g" "--no-global") "Hide global options") - (manpage? ("--manpage") "Generate in manpage format") - (commands? ("--commands") "List all known commands") - &multiple - (sections ("--synopsis" "--subcommands" "--similar" "--envvars" - "--postamble") - "Show only the specified sections.") - &context context - &args command) - "Show documentation for a Doom CLI command. - -OPTIONS: - --synopsis, --subcommands, --similar, --envvars, --postamble - TODO" - (doom-cli-load-all) - (when (doom-cli-context-error context) - (terpri)) - (let* ((command (cons (doom-cli-context-prefix context) command)) - (cli (doom-cli-get command t)) - (rcli (doom-cli-get cli)) - (fallbackcli (cl-loop with targets = (doom-cli--command-expand (butlast command) t) - for cmd in (cons command targets) - if (doom-cli-get cmd t) - return it))) - (cond (commands? - (let ((cli (or cli (doom-cli-get (doom-cli-context-prefix context))))) - (print! "Commands under '%s':\n%s" - (doom-cli-command-string cli) - (indent (doom-cli-help--render-commands - (or (doom-cli-subcommands cli) - (user-error "No commands found")) - :prefix (doom-cli-command cli) - :inline? t - :docs? t))))) - ((null sections) - (if (null cli) - (signal 'doom-cli-command-not-found-error command) - (doom-cli-help--print cli context manpage? localonly?) - (exit! :pager?))) - ((dolist (section sections) - (unless (equal section (car sections)) (terpri)) - (pcase section - ("--synopsis" - (print! "%s" (doom-cli-help--render-synopsis - (doom-cli-help--synopsis cli) - "Usage: "))) - ("--subcommands" - (print! "%s\n%s" (bold "Available commands:") - (indent (doom-cli-help--render-commands - (doom-cli-subcommands rcli 1) - :prefix command - :grouped? t - :docs? t) - doom-print-indent-increment))) - ("--similar" - (unless command - (user-error "No command specified")) - (let ((similar (doom-cli-help-similar-commands command 0.4))) - (print! "Similar commands:") - (if (not similar) - (print! (indent (warn "Can't find any!"))) - (dolist (command (seq-take similar 10)) - (print! (indent (item "(%d%%) %s")) - (* (car command) 100) - (doom-cli-command-string (cdr command))))))) - ("--envvars" - (let* ((key "ENVIRONMENT VARIABLES") - (clis (if command (doom-cli-find command) (hash-table-values doom-cli--table))) - (clis (seq-remove #'doom-cli-alias clis)) - (clis (seq-filter (fn! (cdr (assoc key (doom-cli-docs %)))) clis)) - (clis (seq-group-by #'doom-cli-command clis))) - (print! "List of environment variables for %s:\n" command) - (if (null clis) - (print! (indent "None!")) - (dolist (group clis) - (print! (bold "%s%s:" - (doom-cli-command-string (car group)) - (if (doom-cli-fn (doom-cli-get (car group))) - "" " *"))) - (dolist (cli (cdr group)) - (print! (indent "%s") (markup (cdr (assoc key (doom-cli-docs cli)))))))))) - ("--postamble" - (print! "See %s for documentation." - (join (cl-loop with spec = - `((?p . ,(doom-cli-context-prefix context)) - (?c . ,(doom-cli-command-string (cdr (doom-cli-command (or cli fallbackcli)))))) - for cmd in doom-help-commands - for formatted = (trim (format-spec cmd spec)) - collect (replace-regexp-in-string - " +" " " (format "'%s'" formatted))) - " or "))))))))) - -(defcli! (:root :version) - ((simple? ("--simple")) - &context context) - "Show installed versions of Doom, Doom modules, and Emacs." - (doom/version) - (unless simple? - (terpri) - (with-temp-buffer - (insert-file-contents (doom-path doom-emacs-dir "LICENSE")) - (re-search-forward "^Copyright (c) ") - (print! "%s\n" (trim (thing-at-point 'line t))) - (print! (p "Doom Emacs uses the MIT license and is provided without warranty " - "of any kind. You may redistribute and modify copies if " - "given proper attribution. See the LICENSE file for details."))))) - - -;; -;;; Helpers - -(defun doom-cli-help (cli) - "Return an alist of documentation summarizing CLI (a `doom-cli')." - (let* ((rcli (doom-cli-get cli)) - (docs (doom-cli-docs rcli))) - `((command . ,(doom-cli-command-string cli)) - (summary . ,(or (cdr (assoc "SUMMARY" docs)) "TODO")) - (description . ,(or (cdr (assoc "MAIN" docs)) "TODO")) - (synopsis . ,(doom-cli-help--synopsis cli)) - (arguments . ,(doom-cli-help--arguments rcli)) - (options . ,(doom-cli-help--options rcli)) - (commands . ,(doom-cli-subcommands cli 1)) - (sections . ,(seq-filter #'cdr (cddr docs)))))) - -(defun doom-cli-help-similar-commands (command &optional maxscore) - "Return N commands that are similar to COMMAND." - (seq-take-while - (fn! (>= (car %) (or maxscore 0.0))) - (seq-sort-by - #'car #'> - (cl-loop with prefix = (seq-find #'doom-cli-get (nreverse (doom-cli--command-expand command t))) - with input = (doom-cli-command-string (cdr (doom-cli--command command t))) - for command in (hash-table-keys doom-cli--table) - if (doom-cli-fn (doom-cli-get command)) - if (equal prefix (seq-take command (length prefix))) - collect (cons (doom-cli-help--similarity - input (doom-cli-command-string (cdr command))) - command))))) - -(defun doom-cli-help--similarity (s1 s2) - ;; Ratcliff-Obershelp similarity - (let* ((s1 (downcase s1)) - (s2 (downcase s2)) - (s1len (length s1)) - (s2len (length s2))) - (if (or (zerop s1len) - (zerop s2len)) - 0.0 - (/ (let ((i 0) (j 0) (score 0) jlast) - (while (< i s1len) - (unless jlast (setq jlast j)) - (if (and (< j s2len) - (= (aref s1 i) (aref s2 j))) - (progn (cl-incf score) - (cl-incf i) - (cl-incf j)) - (setq m 0) - (cl-incf j) - (when (>= j s2len) - (setq j (or jlast j) - jlast nil) - (cl-incf i)))) - (* 2.0 score)) - (+ (length s1) - (length s2)))))) - -;;; Help: printers -;; TODO Parameterize optional args with `cl-defun' -(defun doom-cli-help--print (cli context &optional manpage? noglobal?) - "Write CLI's documentation in a manpage-esque format to stdout." - (let-alist (doom-cli-help cli) - (let* ((alist - `(,@(if manpage? - `((nil . ,(let* ((title (cadr (member "--load" command-line-args))) - (width (floor (/ (- (doom-cli-context-width context) - (length title)) - 2.0)))) - ;; FIXME Who am I fooling? - (format (format "%%-%ds%%s%%%ds" width width) - "DOOM(1)" title "DOOM(1)"))) - ("NAME" . ,(concat .command " - " .summary)) - ("SYNOPSIS" . ,(doom-cli-help--render-synopsis .synopsis nil t)) - ("DESCRIPTION" . ,.description)) - `((nil . ,(doom-cli-help--render-synopsis .synopsis "Usage: ")) - (nil . ,(string-join (seq-remove #'string-empty-p (list .summary .description)) - "\n\n")))) - ("ARGUMENTS" . ,(doom-cli-help--render-arguments .arguments)) - ("COMMANDS" - . ,(doom-cli-help--render-commands - .commands :prefix (doom-cli-command cli) :grouped? t :docs? t)) - ("OPTIONS" - . ,(doom-cli-help--render-options - (if (or (not (doom-cli-fn cli)) noglobal?) - `(,(assq 'local .options)) - .options) - cli)))) - (command (doom-cli-command cli))) - (letf! (defun printsection (section) - (print! "%s\n" - (if (null section) - (dark "TODO") - (markup - (format-spec - section `((?p . ,(car command)) - (?c . ,(doom-cli-command-string (cdr command)))) - 'ignore))))) - (pcase-dolist (`(,label . ,contents) alist) - (when (and contents (not (string-blank-p contents))) - (when label - (print! (bold "%s%s") label (if manpage? "" ":"))) - (print-group! :if label (printsection contents)))) - (pcase-dolist (`(,label . ,contents) .sections) - (when (and contents (not (assoc label alist))) - (print! (bold "%s:") label) - (print-group! (printsection contents)))))))) - -;;; Help: synopsis -(defun doom-cli-help--synopsis (cli &optional all-options?) - (let* ((rcli (doom-cli-get cli)) - (opts (doom-cli-help--options rcli)) - (opts (mapcar #'car (if all-options? (mapcan #'cdr opts) (alist-get 'local opts)))) - (opts (cl-loop for opt in opts - for args = (cdar opt) - for switches = (mapcar #'car opt) - for multi? = (member "..." args) - if args - collect (format (if multi? "[%s %s]..." "[%s %s]") - (string-join switches "|") - (string-join (remove "..." args) "|")) - else collect (format "[%s]" (string-join switches "|")))) - (args (doom-cli-arguments rcli)) - (subcommands? (doom-cli-subcommands rcli 1 :predicate? t))) - `((command . ,(doom-cli-command cli)) - (options ,@opts) - (required ,@(mapcar (fn! (upcase (format "`%s'" %))) (if subcommands? '(command) (alist-get '&required args)))) - (optional ,@(mapcar (fn! (upcase (format "[`%s']" %)))(alist-get '&optional args))) - (rest ,@(mapcar (fn! (upcase (format "[`%s'...]" %))) (if subcommands? '(args) (alist-get '&args args))))))) - -(defun doom-cli-help--render-synopsis (synopsis &optional prefix) - (let-alist synopsis - (let ((doom-print-indent 0) - (prefix (or prefix "")) - (command (doom-cli-command-string .command))) - (string-trim-right - (format! "%s\n\n" - (fill (concat (bold prefix) - (format "%s " command) - (markup - (join (append .options - (and .options - (or .required - .optional - .rest) - (list (dark "[--]"))) - .required - .optional - .rest)))) - 80 (1+ (length (concat prefix command))))))))) - -;;; Help: arguments -(defun doom-cli-help--arguments (cli &optional all?) - (doom-cli-help--parse-docs (doom-cli-find cli t) "ARGUMENTS")) - -(defun doom-cli-help--render-arguments (arguments) - (mapconcat (lambda (arg) - (format! "%-20s\n%s" - (underscore (car arg)) - (indent (if (equal (cdr arg) "TODO") - (dark (cdr arg)) - (cdr arg)) - doom-print-indent-increment))) - arguments - "\n")) - -;;; Help: commands -(cl-defun doom-cli-help--render-commands (commands &key prefix grouped? docs? (inline? t)) - (with-temp-buffer - (let* ((doom-print-indent 0) - (commands (seq-group-by (fn! (if grouped? (doom-cli-prop (doom-cli-get % t) :group))) - (nreverse commands))) - (toplevel (assq nil commands)) - (rest (remove toplevel commands)) - (drop (if prefix (length prefix) 0)) - (minwidth - (apply - #'max (or (cl-loop for cmd in (apply #'append (mapcar #'cdr commands)) - for cmd = (seq-drop cmd drop) - collect (length (doom-cli-command-string cmd))) - (list 15)))) - (ellipsis (doom-print--style 'dark " […]")) - (ellipsislen (- (length ellipsis) (if (eq doom-print-backend 'ansi) 2 4)))) - (dolist (group (cons toplevel rest)) - (let ((label (if (car-safe group) (cdr commands)))) - (when label - (insert! ((bold "%s:") (car group)) "\n")) - (print-group! :if label - (dolist (command (cdr group)) - (let* ((cli (doom-cli-get command t)) - (rcli (doom-cli-get command)) - (summary (doom-cli-short-docs rcli)) - (subcommands? (doom-cli-subcommands cli 1 :predicate? t))) - (insert! ((format "%%-%ds%%s%%s" - (+ (- minwidth doom-print-indent) - doom-print-indent-increment - (if subcommands? ellipsislen 0))) - (concat (doom-cli-command-string (seq-drop command drop)) - (if subcommands? ellipsis)) - (if inline? " " "\n") - (indent (if (and (doom-cli-alias cli) - (not (doom-cli-type rcli))) - (dark "-> %s" (doom-cli-command-string cli)) - (when docs? - (if summary (markup summary) (dark "TODO")))))) - "\n"))) - (when (cdr rest) - (insert "\n"))))) - (string-trim-right (buffer-string))))) - -;;; Help: options -(defun doom-cli-help--options (cli &optional noformatting?) - "Return an alist summarizing CLI's options. - -The alist's CAR are lists of formatted switches plus their arguments, e.g. -'((\"`--foo'\" \"`BAR'\") ...). Their CDR is their formatted documentation." - (let* ((docs (doom-cli-help--parse-docs (doom-cli-find cli t) "OPTIONS")) - (docs (mapcar (fn! (cons (split-string (car %) ", ") - (cdr %))) - docs)) - (strfmt (if noformatting? "%s" "`%s'")) - local-options - global-options - seen) - (dolist (neighbor (nreverse (doom-cli-find cli))) - (dolist (option (doom-cli-options neighbor)) - (when-let* ((switches (cl-loop for sw in (doom-cli-option-switches option) - if (and (doom-cli-option-flag-p option) - (string-prefix-p "--" sw)) - collect (format "--[no-]%s" (substring sw 2)) - else collect sw)) - (switches (seq-difference switches seen))) - (dolist (switch switches) (push switch seen)) - (push (cons (cl-loop for switch in switches - if (doom-cli-option-arguments option) - collect (cons (format strfmt switch) - (append (doom-cli-help--parse-args it noformatting?) - (when (doom-cli-option-multiple-p option) - (list "...")))) - else collect (list (format strfmt switch))) - (string-join - (or (delq - nil (cons (when-let (docs (doom-cli-option-docs option)) - (concat docs ".")) - (cl-loop for (flags . docs) in docs - unless (equal (seq-difference flags switches) flags) - collect docs))) - '("TODO")) - "\n\n")) - (if (equal (doom-cli-command neighbor) - (doom-cli-command cli)) - local-options - global-options))))) - `((local . ,(nreverse local-options)) - (global . ,(nreverse global-options))))) - -(defun doom-cli-help--render-options (options &optional cli) - (let ((doom-print-indent 0) - (local (assq 'local options)) - (global (assq 'global options))) - (when (or (cdr local) (cdr global)) - (letf! (defun printopts (opts) - (pcase-dolist (`(,switches . ,docs) (cdr opts)) - (let (multiple?) - (insert! - ("%s%s\n%s" - (mapconcat - (fn! (when (member "..." (cdr %)) - (setq multiple? t)) - (string-trim-right - (format "%s %s" - (doom-print--cli-markup (car %)) - (doom-print--cli-markup - (string-join (remove "..." (cdr %)) "|"))))) - switches - ", ") - (if multiple? ", ..." "") - (indent (fill (markup docs)) doom-print-indent-increment)) - "\n\n")))) - (with-temp-buffer - (if (null (cdr local)) - (insert (if global "This command has no local options.\n" "") "\n") - (printopts local)) - (when (cdr global) - (insert! ((bold "Global options:\n"))) - (print-group! (printopts global))) - (string-trim-right (buffer-string))))))) - -;;; Help: internal -(defun doom-cli-help--parse-args (args &optional noformatting?) - (cl-loop for arg in args - if (listp arg) - collect (string-join (doom-cli-help--parse-args arg noformatting?) "|") - else if (symbolp arg) - collect (format (if noformatting? "%s" "`%s'") (upcase (symbol-name arg))) - else collect arg)) - -(defun doom-cli-help--parse-docs (cli-list section-name) - (cl-check-type section-name string) - (let (alist) - (dolist (cli cli-list (nreverse alist)) - (when-let (section (cdr (assoc section-name (doom-cli-docs cli)))) - (with-temp-buffer - (save-excursion (insert section)) - (let ((lead (current-indentation)) - (buffer (current-buffer))) - (while (not (eobp)) - (let ((heading (string-trim (buffer-substring (point-at-bol) (point-at-eol)))) - (beg (point-at-bol 2)) - end) - (forward-line 1) - (while (and (not (eobp)) - (/= (current-indentation) lead) - (forward-line 1))) - (setf (alist-get heading alist nil nil #'equal) - (string-join - (delq - nil (list (alist-get heading alist nil nil #'equal) - (let ((end (point))) - (with-temp-buffer - (insert-buffer-substring buffer beg end) - (goto-char (point-min)) - (indent-rigidly (point-min) (point-max) (- (current-indentation))) - (string-trim-right (buffer-string)))))) - "\n\n")))))))))) - -(provide 'doom-cli-help) -;;; help.el ends here diff --git a/lisp/cli/install.el b/lisp/cli/install.el index 79dddaf8b..3e1e4ef21 100644 --- a/lisp/cli/install.el +++ b/lisp/cli/install.el @@ -55,20 +55,19 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g. (setq doom-user-dir (expand-file-name "doom/" xdg-config-dir))))) (if (file-directory-p doom-user-dir) - (print! (item "Skipping %s (already exists)") (relpath doom-user-dir)) + (print! (item "Skipping %s (already exists)") (path doom-user-dir)) (make-directory doom-user-dir 'parents) - (print! (success "Created %s") (relpath doom-user-dir))) + (print! (success "Created %s") (path doom-user-dir))) ;; Create init.el, config.el & packages.el (print-group! (mapc (lambda (file) (cl-destructuring-bind (filename . template) file - (if (file-exists-p! filename doom-user-dir) - (print! (item "Skipping %s (already exists)") - (path filename)) - (print! (item "Creating %s%s") (relpath doom-user-dir) filename) - (with-temp-file (doom-path doom-user-dir filename) - (insert-file-contents template)) + (setq filename (doom-path doom-user-dir filename)) + (if (file-exists-p filename) + (print! (item "Skipping %s (already exists)...") (path filename)) + (print! (item "Creating %s...") (path filename)) + (with-temp-file filename (insert-file-contents template)) (print! (success "Done!"))))) (let ((template-dir (doom-path doom-emacs-dir "templates"))) `((,doom-module-init-file @@ -96,7 +95,7 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g. (if (eq install? :no) (print! (warn "Not installing plugins, as requested")) (print! "Installing plugins") - (doom-packages-install)) + (doom-packages-ensure)) (print! "Regenerating autoloads files") (doom-profile-generate) diff --git a/lisp/cli/packages.el b/lisp/cli/packages.el index 1cd6d4d45..2f81d22b5 100644 --- a/lisp/cli/packages.el +++ b/lisp/cli/packages.el @@ -13,28 +13,12 @@ ;; ;;; Commands -(defcli! (:before (build b purge p)) (&context context) - (require 'comp nil t) - (doom-initialize-core-packages)) +(defcli-obsolete! ((build b)) (sync "--rebuild") "v3.0.0") -;; DEPRECATED Replace with "doom sync --rebuild" -(defcli! ((build b)) - ((rebuild-p ("-r") "Only rebuild packages that need rebuilding") - (jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation")) - "Byte-compiles & symlinks installed packages. - -This ensures that all needed files are symlinked from their package repo and -their elisp files are byte-compiled. This is especially necessary if you upgrade -Emacs (as byte-code is generally not forward-compatible)." - :benchmark t - (when jobs - (setq native-comp-async-jobs-number (truncate jobs))) - (when (doom-packages-build (not rebuild-p)) - (doom-profile-generate)) - t) +(defcli-obsolete! ((purge p)) (gc) "v3.0.0") ;; TODO Rename to "doom gc" and move to its own file -(defcli! ((purge p)) +(defcli! (gc) ((nobuilds-p ("-b" "--no-builds") "Don't purge unneeded (built) packages") (noelpa-p ("-p" "--no-elpa") "Don't purge ELPA packages") (norepos-p ("-r" "--no-repos") "Don't purge unused straight repos") @@ -50,6 +34,8 @@ possible. It is a good idea to occasionally run this doom purge -g to ensure your package list remains lean." :benchmark t + (require 'comp nil t) + (doom-initialize-core-packages) (straight-check-all) (when (doom-packages-purge (not noelpa-p) @@ -242,154 +228,147 @@ list remains lean." (defun doom-packages--write-missing-eln-errors () "Write .error files for any expected .eln files that are missing." - (when (featurep 'native-compile) - (cl-loop for file in doom-packages--eln-output-expected - for eln-name = (doom-packages--eln-file-name file) - for eln-file = (doom-packages--eln-output-file eln-name) - for error-file = (doom-packages--eln-error-file eln-name) - for error-dir = (file-name-directory error-file) - unless (or (file-exists-p eln-file) - (file-newer-than-file-p error-file file) - (not (file-writable-p error-dir))) - do (make-directory error-dir 'parents) - (write-region "" nil error-file) - (doom-log "Wrote %s" error-file)) - (setq doom-packages--eln-output-expected nil))) + (cl-loop for file in doom-packages--eln-output-expected + for eln-name = (doom-packages--eln-file-name file) + for eln-file = (doom-packages--eln-output-file eln-name) + for error-file = (doom-packages--eln-error-file eln-name) + for error-dir = (file-name-directory error-file) + unless (or (file-exists-p eln-file) + (file-newer-than-file-p error-file file) + (not (file-writable-p error-dir))) + do (make-directory error-dir 'parents) + (write-region "" nil error-file) + (doom-log "Wrote %s" error-file)) + (setq doom-packages--eln-output-expected nil)) (defun doom-packages--compile-site-files () "Queue async compilation for all non-doom Elisp files." - (when (featurep 'native-compile) - (cl-loop with paths = (cl-loop for path in load-path - unless (file-in-directory-p path doom-local-dir) - collect path) - for file in (doom-files-in paths :match "\\.el\\(?:\\.gz\\)?$") - if (and (file-exists-p (byte-compile-dest-file file)) - (not (doom-packages--find-eln-file (doom-packages--eln-file-name file))) - (not (cl-some (fn! (string-match-p % file)) - native-comp-deferred-compilation-deny-list))) do - (doom-log "Compiling %s" file) - (native-compile-async file)))) + (cl-loop with paths = (cl-loop for path in load-path + unless (file-in-directory-p path doom-local-dir) + collect path) + for file in (doom-files-in paths :match "\\.el\\(?:\\.gz\\)?$") + if (and (file-exists-p (byte-compile-dest-file file)) + (not (doom-packages--find-eln-file (doom-packages--eln-file-name file))) + (not (cl-some (fn! (string-match-p % file)) + native-comp-deferred-compilation-deny-list))) do + (doom-log "Compiling %s" file) + (native-compile-async file))) -(defun doom-packages-install () - "Installs missing packages. - -This function will install any primary package (i.e. a package with a `package!' -declaration) or dependency thereof that hasn't already been." +(defun doom-packages-ensure (&optional force-p) + "Ensure packages are installed, built" (doom-initialize-packages) - (print! (start "Installing packages...")) - (let ((pinned (doom-package-pinned-list))) - (print-group! - (add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h) - (if-let (built - (doom-packages--with-recipes (doom-package-recipe-list) - (recipe package type local-repo) - (unless (file-directory-p (straight--repos-dir local-repo)) - (doom-packages--cli-recipes-update)) - (condition-case-unless-debug e - (let ((straight-use-package-pre-build-functions - (cons (lambda (pkg &rest _) - (when-let (commit (cdr (assoc pkg pinned))) - (print! (item "Checked out %s: %s") pkg commit))) - straight-use-package-pre-build-functions))) - (straight-use-package (intern package)) - ;; HACK Line encoding issues can plague repos with dirty - ;; worktree prompts when updating packages or "Local - ;; variables entry is missing the suffix" errors when - ;; installing them (see hlissner/doom-emacs#2637), so - ;; have git handle conversion by force. - (when (and doom--system-windows-p (stringp local-repo)) - (let ((default-directory (straight--repos-dir local-repo))) - (when (file-in-directory-p default-directory straight-base-dir) - (straight--process-run "git" "config" "core.autocrlf" "true"))))) - (error - (signal 'doom-package-error (list package e)))))) - (progn - (when (featurep 'native-compile) - (doom-packages--compile-site-files) - (doom-packages--wait-for-native-compile-jobs) - (doom-packages--write-missing-eln-errors)) - (print! (success "\033[KInstalled %d packages") (length built))) - (print! (item "No packages need to be installed")) - nil)))) - - -(defun doom-packages-build (&optional force-p) - "(Re)build all packages." - (doom-initialize-packages) - (print! (start "(Re)building %spackages...") (if force-p "all " "")) + (if (not (file-directory-p (straight--repos-dir))) + (print! (start "Installing all packages for the first time (this may take a while)...")) + (if force-p + (print! (start "Rebuilding all packages (this may take a while)...")) + (print! (start "Ensuring packages are installed and built...")))) (print-group! - (let ((straight-check-for-modifications - (when (file-directory-p (straight--modified-dir)) - '(find-when-checking))) - (straight--allow-find - (and straight-check-for-modifications - (executable-find straight-find-executable) - t)) - (straight--packages-not-to-rebuild - (or straight--packages-not-to-rebuild (make-hash-table :test #'equal))) - (straight--packages-to-rebuild - (or (if force-p :all straight--packages-to-rebuild) - (make-hash-table :test #'equal))) - (recipes (doom-package-recipe-list))) - (add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h) - (unless force-p - (straight--make-build-cache-available)) - (if-let (built - (doom-packages--with-recipes recipes (package local-repo recipe) - (unless force-p - ;; Ensure packages with outdated files/bytecode are rebuilt - (let* ((build-dir (straight--build-dir package)) - (repo-dir (straight--repos-dir local-repo)) - (build (if (plist-member recipe :build) - (plist-get recipe :build) - t)) - (want-byte-compile - (or (eq build t) - (memq 'compile build))) - (want-native-compile - (or (eq build t) - (memq 'native-compile build)))) - (and (eq (car-safe build) :not) - (setq want-byte-compile (not want-byte-compile) - want-native-compile (not want-native-compile))) - (unless (featurep 'native-compile) - (setq want-native-compile nil)) - (and (or want-byte-compile want-native-compile) - (or (file-newer-than-file-p repo-dir build-dir) - (file-exists-p (straight--modified-dir (or local-repo package))) - (cl-loop with outdated = nil - for file in (doom-files-in build-dir :match "\\.el$" :full t) - if (or (if want-byte-compile (doom-packages--elc-file-outdated-p file)) - (if want-native-compile (doom-packages--eln-file-outdated-p file))) - do (setq outdated t) + (let ((straight-check-for-modifications + (when (file-directory-p (straight--modified-dir)) + '(find-when-checking))) + (straight--allow-find + (and straight-check-for-modifications + (executable-find straight-find-executable) + t)) + (straight--packages-not-to-rebuild + (or straight--packages-not-to-rebuild (make-hash-table :test #'equal))) + (straight--packages-to-rebuild + (or (if force-p :all straight--packages-to-rebuild) + (make-hash-table :test #'equal))) + (recipes (doom-package-recipe-list)) + (pinned (doom-package-pinned-list))) + (add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h) + (straight--make-build-cache-available) + (if-let (built + (doom-packages--with-recipes recipes (package local-repo recipe) + (let ((repo-dir (straight--repos-dir (or local-repo package))) + (build-dir (straight--build-dir package))) + (unless force-p + ;; Ensure packages with outdated files/bytecode are rebuilt + (let* ((build (if (plist-member recipe :build) + (plist-get recipe :build) + t)) + (want-byte-compile + (or (eq build t) + (memq 'compile build))) + (want-native-compile + (or (eq build t) + (memq 'native-compile build)))) + (and (eq (car-safe build) :not) + (setq want-byte-compile (not want-byte-compile) + want-native-compile (not want-native-compile))) + (unless (featurep 'native-compile) + (setq want-native-compile nil)) + (and (or want-byte-compile want-native-compile) + (or (file-newer-than-file-p repo-dir build-dir) + (file-exists-p (straight--modified-dir (or local-repo package))) + (cl-loop with outdated = nil + for file in (doom-files-in build-dir :match "\\.el$" :full t) + if (or (if want-byte-compile (doom-packages--elc-file-outdated-p file)) + (if want-native-compile (doom-packages--eln-file-outdated-p file))) + do (setq outdated t) (when want-native-compile (push file doom-packages--eln-output-expected)) - finally return outdated)) - (puthash package t straight--packages-to-rebuild)))) - (straight-use-package (intern package)))) - (progn - (when (featurep 'native-compile) - (doom-packages--compile-site-files) - (doom-packages--wait-for-native-compile-jobs) - (doom-packages--write-missing-eln-errors)) - ;; HACK Every time you save a file in a package that straight tracks, - ;; it is recorded in ~/.emacs.d/.local/straight/modified/. - ;; Typically, straight will clean these up after rebuilding, but - ;; Doom's use-case circumnavigates that, leaving these files - ;; there and causing a rebuild of those packages each time `doom - ;; sync' or similar is run, so we clean it up ourselves: - (delete-directory (straight--modified-dir) 'recursive) - (print! (success "\033[KRebuilt %d package(s)") (length built))) - (print! (item "No packages need rebuilding")) - nil)))) + finally return outdated)) + (puthash package t straight--packages-to-rebuild)))) + (unless (file-directory-p repo-dir) + (doom-packages--cli-recipes-update)) + (condition-case-unless-debug e + (let ((straight-vc-git-post-clone-hook + (cons (lambda! (&key commit) + (print-group! + (if-let (pin (cdr (assoc package pinned))) + (print! (item "Pinned to %s") pin) + (when commit + (print! (item "Checked out %s") commit))))) + straight-vc-git-post-clone-hook))) + (straight-use-package (intern package)) + (when (file-in-directory-p repo-dir straight-base-dir) + ;; HACK: Straight can sometimes fail to clone a repo, + ;; leaving behind an empty directory which, in + ;; future invocations, it will assume indicates a + ;; successful clone (causing load errors later). + (let ((try 0)) + (while (not (file-directory-p (doom-path repo-dir ".git"))) + (when (= try 3) + (error "Failed to clone package")) + (print! (warn "Failed to clone %S, trying again (attempt #%d)...") package (1+ try)) + (delete-directory repo-dir t) + (delete-directory build-dir t) + (straight-use-package (intern package)) + (cl-incf try))) + ;; HACK: Line encoding issues can plague repos with + ;; dirty worktree prompts when updating packages or + ;; "Local variables entry is missing the suffix" + ;; errors when installing them (see #2637), so have + ;; git handle conversion by force. + (when doom--system-windows-p + (let ((default-directory repo-dir)) + (straight--process-run "git" "config" "core.autocrlf" "true"))))) + (error + (signal 'doom-package-error (list package e))))))) + (progn + (when (featurep 'native-compile) + (doom-packages--compile-site-files) + (doom-packages--wait-for-native-compile-jobs) + (doom-packages--write-missing-eln-errors)) + ;; HACK: Every time you save a file in a package that straight + ;; tracks, it is recorded in ~/.emacs.d/.local/straight/modified/. + ;; Typically, straight will clean these up after rebuilding, but + ;; Doom's use-case circumnavigates that, leaving these files there + ;; and causing a rebuild of those packages each time `doom sync' + ;; or similar is run, so we clean it up ourselves: + (delete-directory (straight--modified-dir) 'recursive) + (print! (success "\033[KBuilt %d package(s)") (length built))) + (print! (item "No packages need attention")) + nil)))) -(defun doom-packages-update () +(defun doom-packages-update (&optional pinned-only-p) "Updates packages." (doom-initialize-packages) (doom-packages--barf-if-incomplete) - (doom-packages--cli-recipes-update) (let* ((repo-dir (straight--repos-dir)) (pinned (doom-package-pinned-list)) (recipes (doom-package-recipe-list)) @@ -397,9 +376,10 @@ declaration) or dependency thereof that hasn't already been." (repos-to-rebuild (make-hash-table :test 'equal)) (total (length recipes)) (esc (unless init-file-debug "\033[1A")) - (i 0) - errors) - (print! (start "Updating packages (this may take a while)...")) + (i 0)) + (if pinned-only-p + (print! (start "Updating pinned packages...")) + (print! (start "Updating all packages (this may take a while)..."))) (doom-packages--with-recipes recipes (recipe package type local-repo) (cl-incf i) (print-group! @@ -412,11 +392,13 @@ declaration) or dependency thereof that hasn't already been." (cl-return)) (let ((default-directory (straight--repos-dir local-repo))) (unless (file-in-directory-p default-directory repo-dir) - (print! (warn "(%d/%d) Skipping %s because it is local") i total package) + (print! (warn "(%d/%d) Skipping %s because it is out-of-tree...") i total package) (cl-return)) (when (eq type 'git) (unless (file-exists-p ".git") (error "%S is not a valid repository" package))) + (when (and pinned-only-p (not (assoc local-repo pinned))) + (cl-return)) (condition-case-unless-debug e (let ((ref (straight-vc-get-commit type local-repo)) (target-ref @@ -430,13 +412,6 @@ declaration) or dependency thereof that hasn't already been." (doom-packages--straight-with (straight-vc-fetch-from-remote recipe) (when .it (straight-merge-package package) - ;; (condition-case e - ;; (straight-merge-package package) - ;; (wrong-type-argument - ;; (if (not (equal (cdr e) '(arrayp nil))) - ;; (signal (car e) (cdr e)) - ;; (delete-directory (straight--build-dir local-repo) t) - ;; (straight-use-package (intern package))))) (setq target-ref (straight-vc-get-commit type local-repo)) (setq output (doom-packages--commit-log-between ref target-ref) commits (length (split-string output "\n" t))) @@ -464,7 +439,7 @@ declaration) or dependency thereof that hasn't already been." (straight-vc-git-default-clone-depth 'full)) (delete-directory repo 'recursive) (print-group! - (straight-use-package (intern package) nil 'no-build)) + (straight-use-package (intern package) nil 'no-build)) (prog1 (file-directory-p repo) (or (not (eq type 'git)) (setq output (doom-packages--commit-log-between ref target-ref) @@ -520,13 +495,14 @@ declaration) or dependency thereof that hasn't already been." (princ "\033[K") (if (hash-table-empty-p packages-to-rebuild) (ignore (print! (success "All %d packages are up-to-date") total)) + (doom-packages--cli-recipes-update) (straight--transaction-finalize) (let ((default-directory (straight--build-dir))) (mapc (doom-rpartial #'delete-directory 'recursive) (hash-table-keys packages-to-rebuild))) (print! (success "Updated %d package(s)") (hash-table-count packages-to-rebuild)) - (doom-packages-build) + (doom-packages-ensure) t)))) @@ -821,5 +797,31 @@ However, in batch mode, print to stdout instead of stderr." "/dev/null"))) (apply fn args))) +;; If the repo failed to clone correctly (usually due to a connection failure), +;; straight proceeds as normal until a later call produces a garbage result +;; (typically, when it fails to fetch the remote branch of the empty directory). +;; This causes Straight to throw an otherwise cryptic type error when it tries +;; to sanitize the result for its log buffer. +;; +;; This error is a common source of user confusion and false positive bug +;; reports, so this advice catches them to regurgitates a more cogent +;; explanation. +(defadvice! doom-cli--straight-throw-error-on-no-branch-a (fn &rest args) + :around #'straight--process-log + (letf! ((defun shell-quote-argument (&rest args) + (unless (car args) + (error "Package was not properly cloned due to a connection failure, please try again later")) + (apply shell-quote-argument args))) + (apply fn args))) + +(defadvice! doom-cli--straight-regurgitate-empty-string-error-a (fn &rest args) + :around #'straight-vc-git-local-repo-name + (condition-case-unless-debug e + (apply fn args) + (wrong-type-argument + (if (eq (cadr e) 'stringp) + (error "Package was not properly cloned due to a connection failure, please try again later") + (signal (car e) (cdr e)))))) + (provide 'doom-cli-packages) ;;; packages.el ends here diff --git a/lisp/cli/sync.el b/lisp/cli/sync.el index 5b042d3bb..e1a7e2abb 100644 --- a/lisp/cli/sync.el +++ b/lisp/cli/sync.el @@ -14,18 +14,21 @@ (defvar doom-before-sync-hook () "Hooks run before 'doom sync' synchronizes the user's config with Doom.") +(defvar doom-cli-sync-info-file (file-name-concat doom-profile-data-dir "sync")) + ;; ;;; Commands -(defcli-alias! (:before (sync s)) (:before build)) - (defcli! ((sync s)) ((noenvvar? ("-e") "Don't regenerate the envvar file") - (noelc? ("-c") "Don't recompile config") - (update? ("-u") "Update installed packages after syncing") - (purge? ("-p") "Purge orphaned package repos & regraft them") - (jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation")) + (update? ("-u") "Update all installed packages after syncing") + (noupdate? ("-U") "Don't update any packages") + (purge? ("--gc") "Purge orphaned package repos & regraft them") + (jobs ("-j" "--jobs" num) "How many threads to use for native compilation") + (rebuild? ("-b" "--rebuild") "Rebuild all installed packages, unconditionally") + (nobuild? ("-B") "Don't rebuild packages when hostname or Emacs version has changed") + &context context) "Synchronize your config with Doom Emacs. This is the equivalent of running autoremove, install, autoloads, then @@ -33,8 +36,10 @@ recompile. Run this whenever you: 1. Modify your `doom!' block, 2. Add or remove `package!' blocks to your config, - 3. Add or remove autoloaded functions in module autoloaded files. - 4. Update Doom outside of Doom (e.g. with git) + 3. Add or remove autoloaded functions in module autoloaded files, + 4. Update Doom outside of Doom (e.g. with git), + 5. Move your Doom config (either $EMACSDIR or $DOOMDIR) to a new location. + 6. When you up (or down) grade Emacs itself. It will ensure that unneeded packages are removed, all needed packages are installed, autoloads files are up-to-date and no byte-compiled files have gone @@ -47,26 +52,49 @@ OPTIONS: :benchmark t (when (doom-profiles-bootloadable-p) (call! '(profiles sync "--reload"))) - (run-hooks 'doom-before-sync-hook) - (add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h) (when jobs (setq native-comp-async-jobs-number (truncate jobs))) - (print! (start "Synchronizing %S profile..." ) - (or (car doom-profile) "default")) + (run-hooks 'doom-before-sync-hook) + (add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h) + (print! (item "Using Emacs %s @ %s") emacs-version (path invocation-directory invocation-name)) + (print! (start "Synchronizing %S profile..." ) (or (car doom-profile) "default")) (unwind-protect (print-group! - (when (and (not noenvvar?) - (file-exists-p doom-env-file)) - (call! '(env))) - (doom-packages-install) - (doom-packages-build) - (when update? - (doom-packages-update)) - (doom-packages-purge purge? purge? purge? purge? purge?) - (when (doom-profile-generate) - (print! (item "Restart Emacs or use 'M-x doom/reload' for changes to take effect")) - (run-hooks 'doom-after-sync-hook)) - t) + ;; If the user has up/downgraded Emacs since last sync, or copied their + ;; config to a different system, then their packages need to be + ;; recompiled. This is necessary because Emacs byte-code is not + ;; necessarily back/forward compatible across major versions, and many + ;; packages bake in hardcoded data at compile-time. + (pcase-let ((`(,old-version . ,old-host) (doom-file-read doom-cli-sync-info-file :by 'read :noerror t)) + (to-rebuild nil)) + (when (and old-version (not (equal old-version emacs-version))) + (print! (warn "Emacs version has changed since last sync (from %s to %s)") old-version emacs-version) + (setq to-rebuild t)) + (when (and old-host (not (equal old-host (system-name)))) + (print! (warn "Your system has changed since last sync")) + (setq to-rebuild t)) + (when (and to-rebuild (not (doom-cli-context-suppress-prompts-p context))) + (cond (nobuild? + (print! (warn "Packages must be rebuilt, but -B has prevented it. Skipping..."))) + ((doom-cli-context-get context 'upgrading) + (print! (warn "Packages will be rebuilt")) + (setq rebuild? t)) + ((y-or-n-p (format! " %s" "Installed packages must be rebuilt. Do so now?")) + (setq rebuild? t)) + ((exit! 0))))) + (when (and (not noenvvar?) + (file-exists-p doom-env-file)) + (call! '(env))) + (doom-packages-ensure rebuild?) + (unless noupdate? (doom-packages-update (not update?))) + (doom-packages-purge purge? purge? purge? purge? purge?) + (when (doom-profile-generate) + (print! (item "Restart Emacs or use 'M-x doom/reload' for changes to take effect")) + (run-hooks 'doom-after-sync-hook)) + (when (or rebuild? (not (file-exists-p doom-cli-sync-info-file))) + (with-temp-file doom-cli-sync-info-file + (prin1 (cons emacs-version (system-name)) (current-buffer)))) + t) (remove-hook 'kill-emacs-hook #'doom-sync--abort-warning-h))) diff --git a/lisp/cli/upgrade.el b/lisp/cli/upgrade.el index f8584a583..c44b300e9 100644 --- a/lisp/cli/upgrade.el +++ b/lisp/cli/upgrade.el @@ -3,7 +3,6 @@ ;;; Code: (load! "packages") -(load! "compile") ;; @@ -22,6 +21,7 @@ (defcli! ((upgrade up)) ((packages? ("-p" "--packages") "Only upgrade packages, not Doom") (jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation") + (nobuild? ("-B") "Don't rebuild packages when hostname or Emacs version has changed") &context context) "Updates Doom and packages. @@ -30,10 +30,11 @@ following shell commands: cd ~/.emacs.d git pull --rebase - doom clean doom sync -u" (let* ((force? (doom-cli-context-suppress-prompts-p context)) - (sync-cmd (append '("sync" "-u") (if jobs `("-j" ,num))))) + (sync-cmd (append '("sync" "-u") + (if nobuild? '("-B")) + (if jobs `("-j" ,jobs))))) (cond (packages? ;; HACK It's messy to use straight to upgrade straight, due to the @@ -54,7 +55,9 @@ following shell commands: ;; Reload Doom's CLI & libraries, in case there were any upstream changes. ;; Major changes will still break, however (print! (item "Reloading Doom Emacs")) + (doom-cli-context-put context 'upgrading t) (exit! "doom" "upgrade" "-p" + (if nobuild? "-B") (if force? "--force") (if jobs (format "--jobs=%d" jobs)))) @@ -96,6 +99,8 @@ following shell commands: (sh! "git" "reset" "--hard" (format "origin/%s" branch)) (sh! "git" "clean" "-ffd"))) + ;; In case of leftover state from a partial/incomplete 'doom upgrade' + (sh! "git" "branch" "-D" target-remote) (sh! "git" "remote" "remove" doom-upgrade-remote) (unwind-protect (let (result) @@ -136,7 +141,6 @@ following shell commands: (ignore (print! (error "Aborted"))) (print! (start "Upgrading Doom Emacs...")) (print-group! - (doom-compile-clean) (doom-cli-context-put context 'straight-recipe (doom-upgrade--get-straight-recipe)) (or (and (zerop (car (sh! "git" "reset" "--hard" target-remote))) (equal (cdr (sh! "git" "rev-parse" "HEAD")) new-rev)) diff --git a/lisp/doom-cli.el b/lisp/doom-cli.el index 7d5bff2f7..eab017d69 100644 --- a/lisp/doom-cli.el +++ b/lisp/doom-cli.el @@ -1783,7 +1783,7 @@ See `defcli!' for information about COMMANDSPEC. TARGET is simply a command list. WHEN specifies what version this command was rendered obsolete." `(let ((ncommand (doom-cli-command-normalize (backquote ,target) doom-cli--group-plist))) - (defcli! ,commandspec (&context context &cli cli &rest args) + (defcli! ,commandspec (&context _context &cli cli &rest args) :docs (format "An obsolete alias for '%s'." (doom-cli-command-string ncommand)) :hide t (print! (warn "'%s' was deprecated in %s") diff --git a/lisp/doom-editor.el b/lisp/doom-editor.el index 2df2cbb66..80696ac35 100644 --- a/lisp/doom-editor.el +++ b/lisp/doom-editor.el @@ -250,8 +250,7 @@ tell you about it. Very annoying. This prevents that." auto-mode-alist '(("/LICENSE\\'" . text-mode) ("\\.log\\'" . text-mode) - ("rc\\'" . conf-mode) - ("\\.\\(?:hex\\|nes\\)\\'" . hexl-mode))) + ("rc\\'" . conf-mode))) ;; diff --git a/lisp/doom-keybinds.el b/lisp/doom-keybinds.el index 210432fc5..31510484e 100644 --- a/lisp/doom-keybinds.el +++ b/lisp/doom-keybinds.el @@ -15,6 +15,12 @@ "An alternative leader prefix key, used for Insert and Emacs states, and for non-evil users.") +(defvar doom-leader-key-states '(normal visual motion) + "which evil modes to activate the leader key for") + +(defvar doom-leader-alt-key-states '(emacs insert) + "which evil modes to activate the alternative leader key for") + (defvar doom-localleader-key "SPC m" "The localleader prefix key, for major-mode specific commands.") @@ -212,8 +218,8 @@ localleader prefix." ((equal doom-leader-alt-key "C-x") (set-keymap-parent doom-leader-map ctl-x-map))) (define-key map (kbd doom-leader-alt-key) 'doom/leader)) - (evil-define-key* '(normal visual motion) map (kbd doom-leader-key) 'doom/leader) - (evil-define-key* '(emacs insert) map (kbd doom-leader-alt-key) 'doom/leader)) + (evil-define-key* doom-leader-key-states map (kbd doom-leader-key) 'doom/leader) + (evil-define-key* doom-leader-alt-key-states map (kbd doom-leader-alt-key) 'doom/leader)) (general-override-mode +1)))) diff --git a/lisp/doom-lib.el b/lisp/doom-lib.el index 9f996d3e7..fd6f34967 100644 --- a/lisp/doom-lib.el +++ b/lisp/doom-lib.el @@ -936,7 +936,7 @@ VARIABLES is a list of variable settings of the form (VAR VALUE), where VAR is the name of the variable (a string) and VALUE is its value (also a string). -The previous values will be be restored upon exit." +The previous values will be restored upon exit." (declare (indent 1) (debug (sexp body))) (unless (consp variables) (error "Invalid VARIABLES: %s" variables)) diff --git a/lisp/doom-profiles.el b/lisp/doom-profiles.el index 94dd3dd09..26ae373d1 100644 --- a/lisp/doom-profiles.el +++ b/lisp/doom-profiles.el @@ -368,7 +368,8 @@ Defaults to the profile at `doom-profile-default'." ;; FIX: Make sure this only runs at startup to protect us Emacs' interpreter ;; re-evaluating this file when lazy-loading dynamic docstrings from the ;; byte-compiled init file. - `((when (doom-context-p 'init) + `((when (or (doom-context-p 'init) + (doom-context-p 'reload)) ,@(cl-loop for var in doom-autoloads-cached-vars if (boundp var) collect `(set-default ',var ',(symbol-value var))) diff --git a/lisp/doom-projects.el b/lisp/doom-projects.el index 4d434e32d..ad498b5da 100644 --- a/lisp/doom-projects.el +++ b/lisp/doom-projects.el @@ -23,6 +23,10 @@ debian, and derivatives). On most it's 'fd'.") ;; ;;; Packages +(after! project + (setq project-list-file (file-name-concat doom-data-dir "projects"))) + +;; DEPRECATED: Will be replaced with project.el (use-package! projectile :commands (projectile-project-root projectile-project-name diff --git a/lisp/doom-start.el b/lisp/doom-start.el index c5b1d46b2..ce022d7cd 100644 --- a/lisp/doom-start.el +++ b/lisp/doom-start.el @@ -143,14 +143,8 @@ (setq selection-coding-system 'utf-8)) -;;; Support for more file extensions -;; Add support for additional file extensions. -(dolist (entry '(("/\\.doom\\(?:rc\\|project\\|module\\|profile\\)\\'" . emacs-lisp-mode) - ("/LICENSE\\'" . text-mode) - ("\\.log\\'" . text-mode) - ("rc\\'" . conf-mode) - ("\\.\\(?:hex\\|nes\\)\\'" . hexl-mode))) - (push entry auto-mode-alist)) +;;; Support for Doom-specific file extensions +(add-to-list 'auto-mode-alist '("/\\.doom\\(?:rc\\|project\\|module\\|profile\\)\\'" . emacs-lisp-mode)) ;; diff --git a/lisp/doom-ui.el b/lisp/doom-ui.el index 64db32afd..0028f1636 100644 --- a/lisp/doom-ui.el +++ b/lisp/doom-ui.el @@ -95,7 +95,6 @@ want to change your symbol font, use `doom-symbol-font'.") (inhibit-redisplay t)) (run-hooks 'doom-switch-buffer-hook))) -(defvar doom--last-frame nil) (defun doom-run-switch-window-or-frame-hooks-h (&optional _) (let ((gc-cons-threshold most-positive-fixnum) (inhibit-redisplay t)) @@ -498,65 +497,69 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original (cons 'custom-theme-directory (delq 'custom-theme-directory custom-theme-load-path))) -(defun doom-init-fonts-h (&optional _reload) +(defun doom-init-fonts-h (&optional reload) "Loads `doom-font', `doom-serif-font', and `doom-variable-pitch-font'." - (let ((this-frame (selected-frame))) - (dolist (map `((default . ,doom-font) - (fixed-pitch . ,doom-font) - (fixed-pitch-serif . ,doom-serif-font) - (variable-pitch . ,doom-variable-pitch-font))) - (condition-case e - (when-let* ((face (car map)) - (font (cdr map))) - (dolist (frame (frame-list)) - (when (display-multi-font-p frame) - (set-face-attribute face frame - :width 'normal :weight 'normal - :slant 'normal :font font))) - (custom-push-theme - 'theme-face face 'user 'set - (let* ((base-specs (cadr (assq 'user (get face 'theme-face)))) - (base-specs (or base-specs '((t nil)))) - (attrs '(:family :foundry :slant :weight :height :width)) - (new-specs nil)) - (dolist (spec base-specs) - ;; Each SPEC has the form (DISPLAY ATTRIBUTE-PLIST) - (let ((display (car spec)) - (plist (copy-tree (nth 1 spec)))) - ;; Alter only DISPLAY conditions matching this frame. - (when (or (memq display '(t default)) - (face-spec-set-match-display display this-frame)) - (dolist (attr attrs) - (setq plist (plist-put plist attr (face-attribute face attr))))) - (push (list display plist) new-specs))) - (nreverse new-specs))) - (put face 'face-modified nil)) - ('error - (ignore-errors (doom--reset-inhibited-vars-h)) - (if (string-prefix-p "Font not available" (error-message-string e)) - (signal 'doom-font-error (list (font-get (cdr map) :family))) - (signal (car e) (cdr e))))))) - (when (fboundp 'set-fontset-font) - (let* ((fn (doom-rpartial #'member (font-family-list))) - (symbol-font (or doom-symbol-font - (cl-find-if fn doom-symbol-fallback-font-families))) - (emoji-font (or doom-emoji-font - (cl-find-if fn doom-emoji-fallback-font-families)))) - (when symbol-font - (dolist (script '(symbol mathematical)) - (set-fontset-font t script symbol-font))) - (when emoji-font - ;; DEPRECATED: make unconditional when we drop 27 support - (when (version<= "28.1" emacs-version) - (set-fontset-font t 'emoji emoji-font)) - ;; some characters in the Emacs symbol script are often covered by emoji - ;; fonts - (set-fontset-font t 'symbol emoji-font nil 'append))) - ;; Nerd Fonts use these Private Use Areas - (dolist (range '((#xe000 . #xf8ff) (#xf0000 . #xfffff))) - (set-fontset-font t range "Symbols Nerd Font Mono"))) - ;; Users should inject their own font logic in `after-setting-font-hook' - (run-hooks 'after-setting-font-hook)) + (let ((initialized-frames (unless reload (get 'doom-font 'initialized-frames)))) + (dolist (frame (if reload (frame-list) (list (selected-frame)))) + (unless (member frame initialized-frames) + (dolist (map `((default . ,doom-font) + (fixed-pitch . ,doom-font) + (fixed-pitch-serif . ,doom-serif-font) + (variable-pitch . ,doom-variable-pitch-font))) + (condition-case e + (when-let* ((face (car map)) + (font (cdr map))) + (when (display-multi-font-p frame) + (set-face-attribute face frame + :width 'normal :weight 'normal + :slant 'normal :font font)) + (custom-push-theme + 'theme-face face 'user 'set + (let* ((base-specs (cadr (assq 'user (get face 'theme-face)))) + (base-specs (or base-specs '((t nil)))) + (attrs '(:family :foundry :slant :weight :height :width)) + (new-specs nil)) + (dolist (spec base-specs) + (let ((display (car spec)) + (plist (copy-tree (nth 1 spec)))) + (when (or (memq display '(t default)) + (face-spec-set-match-display display frame)) + (dolist (attr attrs) + (setq plist (plist-put plist attr (face-attribute face attr))))) + (push (list display plist) new-specs))) + (nreverse new-specs))) + (put face 'face-modified nil)) + ('error + (ignore-errors (doom--reset-inhibited-vars-h)) + (if (string-prefix-p "Font not available" (error-message-string e)) + (signal 'doom-font-error (list (font-get (cdr map) :family))) + (signal (car e) (cdr e)))))) + (put 'doom-font 'initialized-frames + (cons frame (cl-delete-if-not #'frame-live-p initialized-frames)))))) + ;; Only do this once per session (or on `doom/reload-fonts'); superfluous + ;; `set-fontset-font' calls may segfault in some contexts. + (when (or reload (not (get 'doom-font 'initialized))) + (when (fboundp 'set-fontset-font) ; unavailable in emacs-nox + (let* ((fn (doom-rpartial #'member (font-family-list))) + (symbol-font (or doom-symbol-font + (cl-find-if fn doom-symbol-fallback-font-families))) + (emoji-font (or doom-emoji-font + (cl-find-if fn doom-emoji-fallback-font-families)))) + (when symbol-font + (dolist (script '(symbol mathematical)) + (set-fontset-font t script symbol-font))) + (when emoji-font + ;; DEPRECATED: make unconditional when we drop 27 support + (when (version<= "28.1" emacs-version) + (set-fontset-font t 'emoji emoji-font)) + ;; some characters in the Emacs symbol script are often covered by + ;; emoji fonts + (set-fontset-font t 'symbol emoji-font nil 'append))) + ;; Nerd Fonts use these Private Use Areas + (dolist (range '((#xe000 . #xf8ff) (#xf0000 . #xfffff))) + (set-fontset-font t range "Symbols Nerd Font Mono"))) + (run-hooks 'after-setting-font-hook)) + (put 'doom-font 'initialized t)) (defun doom-init-theme-h (&rest _) "Load the theme specified by `doom-theme' in FRAME." diff --git a/lisp/doom.el b/lisp/doom.el index 9545c215a..70873316d 100644 --- a/lisp/doom.el +++ b/lisp/doom.el @@ -201,7 +201,7 @@ "Current version of Doom Emacs core.") ;; DEPRECATED: Remove these when the modules are moved out of core. -(defconst doom-modules-version "24.03.0-pre" +(defconst doom-modules-version "24.04.0-pre" "Current version of Doom Emacs.") (defvar doom-init-time nil @@ -352,12 +352,12 @@ users).") ;;; Startup optimizations ;; Here are Doom's hackiest (and least offensive) startup optimizations. They -;; exploit implementation details and unintended side-effects, and will change -;; often between major Emacs releases. However, I disable them if this is a -;; daemon session (where startup time matters less). +;; exploit implementation details and unintended side-effects in Emacs' startup +;; process, and will change often between major Emacs releases. However, I +;; disable them if this is a daemon session (where startup time matters less). ;; ;; Most of these have been tested on Linux and on fairly fast machines (with -;; SSDs), so your mileage may vary depending on your hardware. +;; SSDs), so your mileage may vary depending on hardware and `window-system'. (unless (daemonp) ;; PERF: `file-name-handler-alist' is consulted on each call to `require', ;; `load', or various file/io functions (like `expand-file-name' or @@ -366,14 +366,13 @@ users).") (let ((old-value (default-toplevel-value 'file-name-handler-alist))) (set-default-toplevel-value 'file-name-handler-alist - ;; HACK: If the bundled elisp for this Emacs install isn't byte-compiled - ;; (but is compressed), then leave the gzip file handler there so Emacs - ;; won't forget how to read read them. - ;; - ;; calc-loaddefs.el is our heuristic for this because it is built-in to - ;; all supported versions of Emacs, and calc.el explicitly loads it - ;; uncompiled. This ensures that the only other, possible fallback would - ;; be calc-loaddefs.el.gz. + ;; 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. (if (eval-when-compile (locate-file-internal "calc-loaddefs.el" load-path)) nil @@ -395,55 +394,46 @@ users).") (unless noninteractive ;; PERF: Resizing the Emacs frame (to accommodate fonts that are smaller or ;; larger than the system font) appears to impact startup time - ;; dramatically. The larger the delta in font size, the greater the delay. - ;; Even trivial deltas can yield a ~1000ms loss, though it varies wildly - ;; depending on font size. + ;; dramatically. The larger the delta, the greater the delay. Even trivial + ;; deltas can yield up to a ~1000ms loss, depending on font size and + ;; `window-system'. PGTK seems least affected and NS/MAC the most. (setq frame-inhibit-implied-resize t) - ;; PERF,UX: Reduce *Message* noise at startup. An empty scratch buffer (or - ;; the dashboard) is more than enough, and faster to display. + ;; PERF: A fair bit of startup time goes into initializing the splash and + ;; scratch buffers in the typical Emacs session (b/c they activate a + ;; non-trivial major mode, generate the splash buffer, and trigger + ;; premature frame redraws by writing to *Messages*). These hacks prevent + ;; most of this work from happening for some decent savings in startup + ;; time. Our dashboard and `doom/open-scratch-buffer' provide a faster + ;; (and more useful) alternative anyway. (setq inhibit-startup-screen t - inhibit-startup-echo-area-message user-login-name) - ;; PERF,UX: Remove "For information about GNU Emacs..." message at startup. - ;; It's redundant with our dashboard and incurs a premature redraw. + inhibit-startup-echo-area-message user-login-name + initial-major-mode 'fundamental-mode + initial-scratch-message nil) + ;; PERF,UX: Prevent "For information about GNU Emacs..." line in *Messages*. (advice-add #'display-startup-echo-area-message :override #'ignore) ;; PERF: Suppress the vanilla startup screen completely. We've disabled it ;; with `inhibit-startup-screen', but it would still initialize anyway. - ;; This involves some file IO and/or bitmap work (depending on the frame - ;; type) that we can no-op for a free 50-100ms boost in startup time. + ;; This involves file IO and/or bitmap work (depending on the frame type) + ;; that we can no-op for a free 50-100ms saving in startup time. (advice-add #'display-startup-screen :override #'ignore) - ;; PERF: Shave seconds off startup time by starting the scratch buffer in - ;; `fundamental-mode', rather than, say, `org-mode' or `text-mode', which - ;; pull in a ton of packages. This buffer is created whether or not we're - ;; in an interactive session. Plus, `doom/open-scratch-buffer' provides a - ;; better scratch buffer, so keep the initial one blank. - (setq initial-major-mode 'fundamental-mode - initial-scratch-message nil) - (unless initial-window-system - ;; PERF: Inexplicably, `tty-run-terminal-initialization' can sometimes - ;; take 2-3s when starting up Emacs in the terminal. Whatever slows it - ;; down at startup doesn't appear to affect it if it's called a little - ;; later in the startup process, so that's what I do. - ;; REVIEW: This optimization is not well understood. Investigate it! + ;; PERF: `tty-run-terminal-initialization' can take 2-3s when starting up + ;; TTY Emacs (non-daemon sessions), depending on your TERM, TERMINFO, + ;; and TERMCAP, but this work isn't very useful on modern systems (the + ;; type I expect Doom's users to be using). The function seems less + ;; expensive if run later in the startup process, so I defer it. + ;; REVIEW: This may no longer be needed in 29+. Needs testing! (define-advice tty-run-terminal-initialization (:override (&rest _) defer) (advice-remove #'tty-run-terminal-initialization #'tty-run-terminal-initialization@defer) (add-hook 'window-setup-hook (doom-partial #'tty-run-terminal-initialization (selected-frame) nil t)))) - ;; PERF,UX: Site files tend to use `load-file', which emits "Loading X..." - ;; messages in the echo area. Writing to the echo-area triggers a - ;; redisplay, which can be expensive during startup. This may also cause - ;; an flash of white when creating the first frame. Needs to be undo - ;; later, though. - (define-advice load-file (:override (file) silence) - (load file nil 'nomessage)) - - ;; PERF: `load-suffixes' and `load-file-rep-suffixes' are consulted on - ;; each `require' and `load'. Doom won't load any modules this early, so - ;; omit .so for a tiny startup boost. Is later restored in doom-start. + ;; PERF: `load-suffixes' and `load-file-rep-suffixes' are consulted on each + ;; `require' and `load'. Doom won't load any modules this early, so omit + ;; .so for a tiny startup boost. Is later restored in doom-start. (put 'load-suffixes 'initial-value (default-toplevel-value 'load-suffixes)) (put 'load-file-rep-suffixes 'initial-value (default-toplevel-value 'load-file-rep-suffixes)) (set-default-toplevel-value 'load-suffixes '(".elc" ".el")) @@ -455,35 +445,34 @@ users).") (setq load-suffixes (get 'load-suffixes 'initial-value) load-file-rep-suffixes (get 'load-file-rep-suffixes 'initial-value)))) - ;; PERF: Doom uses `defcustom' to indicate variables that users are - ;; expected to reconfigure. Trouble is it fires off initializers meant - ;; to accommodate any user attempts to configure them before they were - ;; defined. This is unnecessary work before $DOOMDIR/init.el is loaded, - ;; so I disable them until it is. + ;; PERF: Doom uses `defcustom' merely to announce variables that users may + ;; reconfigure. Trouble is it fires off initializers meant to accommodate + ;; any user attempts to configure them *before* they are defined, which + ;; isn't possible since the user's first opportunity to modify them comes + ;; long after they're defined (in $DOOMDIR/init.el), so this is + ;; unnecessary work. To spare Emacs the startup time, I disable this + ;; behavior until $DOOMDIR is loaded. (setq custom-dont-initialize t) (add-hook! 'doom-before-init-hook (defun doom--reset-custom-dont-initialize-h () (setq custom-dont-initialize nil))) - ;; PERF: Doom disables the UI elements by default, so that there's less - ;; for the frame to initialize. However, the toolbar is still populated - ;; regardless, so I lazy load it until tool-bar-mode is actually used. - (advice-add #'tool-bar-setup :override #'ignore) - - ;; PERF: The mode-line procs a couple dozen times during startup. This is - ;; normally quite fast, but disabling the default mode-line and reducing - ;; the update delay timer seems to stave off ~30-50ms. + ;; PERF: The mode-line procs a couple dozen times during startup, before the + ;; user can even see 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 can substantially affect startup times - ;; and/or produce ugly flashes of unstyled Emacs. + ;; 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: Then reset with advice, because `startup--load-user-init-file' - ;; will never be interrupted by errors. And if these settings are left - ;; set, Emacs could appear frozen or garbled. + ;; 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 ;; Inhibiting `message' only prevents redraws and @@ -491,35 +480,43 @@ users).") (redraw-frame)) (add-hook 'after-init-hook #'doom--reset-inhibited-vars-h) - ;; PERF,UX: An annoying aspect of site-lisp files is that they're often - ;; noisy (they emit load messages or other output to stdout). These - ;; queue unnecessary redraws at startup, cost startup time, and pollute - ;; the logs. I get around it by suppressing it until we can load it - ;; manually, later (in the `startup--load-user-init-file' advice below). + ;; 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 + ;; it does some non-trivial work to set up the toolbar before we can + ;; disable it. To side-step this work, I disable the function and call it + ;; later (see `startup--load-user-init-file@undo-hacks'). + (advice-add #'tool-bar-setup :override #'ignore) + + ;; PERF,UX: site-lisp files are often obnoxiously noisy (emitting load + ;; messages or other output to *Messages* or stdout). These queue + ;; unnecessary redraws at startup which impact startup time depending on + ;; window system. It also pollutes the logs. By suppressing it now, I can + ;; load it myself, later, in a more controlled way (see + ;; `startup--load-user-init-file@undo-hacks'). (put 'site-run-file 'initial-value site-run-file) (setq site-run-file nil) - (define-advice startup--load-user-init-file (:around (fn &rest args) undo-inhibit-vars) - (let (--init--) + (define-advice startup--load-user-init-file (:around (fn &rest args) undo-hacks) + "Undo Doom's startup optimizations to prep for the user's session." + (let (init) (unwind-protect (progn - ;; COMPAT: Onces startup is sufficiently complete, undo some - ;; optimizations to reduce the scope of potential edge cases. - (advice-remove #'load-file #'load-file@silence) - (advice-remove #'tool-bar-setup #'ignore) - (add-transient-hook! 'tool-bar-mode (tool-bar-setup)) (when (setq site-run-file (get 'site-run-file 'initial-value)) (let ((inhibit-startup-screen inhibit-startup-screen)) - (letf! (defun load (file &optional noerror _nomessage &rest args) - (apply load file noerror t args)) + (letf! ((defun load-file (file) (load file nil 'nomessage)) + (defun load (file &optional noerror _nomessage &rest args) + (apply load file noerror t args))) (load site-run-file t t)))) - ;; Then startup as normal. - (apply fn args) - (setq --init-- t)) - (when (or (not --init--) init-file-had-error) + (apply fn args) ; start up as normal + (setq init t)) + (when (or (not init) init-file-had-error) ;; If we don't undo our inhibit-{message,redisplay} and there's an ;; error, we'll see nothing but a blank Emacs frame. (doom--reset-inhibited-vars-h)) + ;; COMPAT: Once startup is sufficiently complete, undo our earlier + ;; optimizations to reduce the scope of potential edge cases. + (advice-remove #'tool-bar-setup #'ignore) + (add-transient-hook! 'tool-bar-mode (tool-bar-setup)) (unless (default-toplevel-value 'mode-line-format) (setq-default mode-line-format (get 'mode-line-format 'initial-value)))))) diff --git a/lisp/lib/files.el b/lisp/lib/files.el index 088463293..6690820dc 100644 --- a/lisp/lib/files.el +++ b/lisp/lib/files.el @@ -484,27 +484,67 @@ If FORCE-P, overwrite the destination file if it exists, without confirmation." file)))) ;;;###autoload -(defun doom/sudo-find-file (file) - "Open FILE as root." - (interactive "FOpen file as root: ") - (find-file (doom--sudo-file-path (expand-file-name file)))) +(defun doom/sudo-find-file (file &optional arg) + "Open FILE as root. + +This will prompt you to save the current buffer, unless prefix ARG is given, in +which case it will save it without prompting." + (interactive + (list (read-file-name "Open file as root: ") + current-prefix-arg)) + ;; HACK: Teach `save-place' to treat the new "remote" buffer as if it were + ;; visiting the same local file (because it is), and preserve the cursor + ;; position as usual. + (letf! ((defun remote-local-name (path) + (if path (or (file-remote-p path 'localname) path))) + (defmacro with-local-name (&rest body) + `(when save-place-mode + (let ((buffer-file-name (remote-local-name buffer-file-name)) + (default-directory (remote-local-name default-directory))) + ,@body)))) + (let ((window-start (window-start)) + (buffer (current-buffer))) + (when (and buffer-file-name (file-equal-p buffer-file-name file)) + (when (buffer-modified-p) + (save-some-buffers arg (lambda () (eq (current-buffer) buffer)))) + (with-local-name (save-place-to-alist))) + (prog1 + ;; HACK: Disable auto-save in temporary tramp buffers because it could + ;; trigger processes that hang silently in the background, making + ;; those buffers inoperable for the rest of that session (Tramp + ;; caches them). + (let ((auto-save-default nil) + ;; REVIEW: use only these when we drop 28 support + (remote-file-name-inhibit-auto-save t) + (remote-file-name-inhibit-auto-save-visited t) + ;; Prevent redundant work + save-place-mode) + (find-file (doom--sudo-file-path (expand-file-name file)))) + ;; Record of the cursor's old position if it isn't at BOB (indicating + ;; this buffer was already open), in case the user wishes to go to it. + (unless (bobp) + (doom-set-jump-h) + ;; save-place-find-file-hook requires point be a BOB to do its thang. + (goto-char (point-min))) + (with-local-name (save-place-find-file-hook)) + (set-window-start nil window-start))))) ;;;###autoload (defun doom/sudo-this-file () "Open the current file as root." (interactive) - (find-file - (doom--sudo-file-path - (or buffer-file-name - (when (or (derived-mode-p 'dired-mode) - (derived-mode-p 'wdired-mode)) - default-directory))))) + (doom/sudo-find-file + (or (buffer-file-name (buffer-base-buffer)) + (when (or (derived-mode-p 'dired-mode) + (derived-mode-p 'wdired-mode)) + default-directory) + (user-error "Cannot determine the file path of the current buffer")))) ;;;###autoload (defun doom/sudo-save-buffer () "Save this file as root." (interactive) - (let ((file (doom--sudo-file-path buffer-file-name))) + (let ((file (doom--sudo-file-path (buffer-file-name (buffer-base-buffer))))) (if-let (buffer (find-file-noselect file)) (let ((origin (current-buffer))) (copy-to-buffer buffer (point-min) (point-max)) @@ -521,9 +561,17 @@ If FORCE-P, overwrite the destination file if it exists, without confirmation." (defun doom/remove-recent-file (file) "Remove FILE from your recently-opened-files list." (interactive - (list (completing-read "Remove recent file: " recentf-list + (list (completing-read "Remove recent file: " + (lambda (string predicate action) + (if (eq action 'metadata) + '(metadata + (display-sort-function . identity) + (cycle-sort-function . identity) + (category . file)) + (complete-with-action + action recentf-list string predicate))) nil t))) - (setq recentf-list (delete file recentf-list)) + (setq recentf-list (delete (recentf-expand-file-name file) recentf-list)) (recentf-save-list) (message "Removed %S from `recentf-list'" (abbreviate-file-name file))) @@ -593,7 +641,12 @@ see), and if nil, defaults to `find-sibling-rules'." (nconc results (mapcar #'expand-file-name - (file-expand-wildcards expansion nil t))))))))) + ;; `file-expand-wildcards' has a new REGEXP + ;; argument in 29+ that is needed here. This swap + ;; makes it behave as if REGEXP == t. + (letf! (defun wildcard-to-regexp (wildcard) + (concat "\\`" wildcard "\\'")) + (file-expand-wildcards expansion nil)))))))))) ;; Delete the file itself (in case it matched), and remove ;; duplicates, in case we have several expansions and some match ;; the same subsets of files. diff --git a/lisp/lib/print.el b/lisp/lib/print.el index 2a0dffaf2..e74c7fce6 100644 --- a/lisp/lib/print.el +++ b/lisp/lib/print.el @@ -84,7 +84,8 @@ and `format!' into colored output, where COLOR is any car of this list (or (doom-print--indent (if args (apply #'format str args) str) "> "))) - (path . abbreviate-file-name) + (path . (lambda (&rest segments) + (abbreviate-file-name (apply #'doom-path segments)))) (symbol . symbol-name) (relpath . (lambda (str &optional dir) (if (or (not str) diff --git a/lisp/packages.el b/lisp/packages.el index dd908a10d..748c7faad 100644 --- a/lisp/packages.el +++ b/lisp/packages.el @@ -2,8 +2,13 @@ ;;; lisp/packages.el ;; doom.el -(package! auto-minor-mode :pin "17cfa1b54800fdef2975c0c0531dad34846a5065") -(package! gcmh :pin "0089f9c3a6d4e9a310d0791cf6fa8f35642ecfd9") +(package! auto-minor-mode + :pin "17cfa1b54800fdef2975c0c0531dad34846a5065") +(package! compat + :recipe (:host github :repo "emacs-compat/compat") + :pin "8d4e8a366681def88751f5e9975738ecd3180deb") +(package! gcmh + :pin "0089f9c3a6d4e9a310d0791cf6fa8f35642ecfd9") ;; doom-packages.el (package! straight @@ -13,10 +18,10 @@ :branch ,straight-repository-branch :local-repo "straight.el" :files ("straight*.el")) - :pin "b3760f5829dba37e855add7323304561eb57a3d4") + :pin "b1062df10ba4c10ff7a3c61b9e124b3242b11bb2") ;; doom-ui.el -(package! nerd-icons :pin "c6a4acf19454b415cba1c43daf4bfca8fccdd9ba") +(package! nerd-icons :pin "8095215a503d8048739de8b4ea4066598edb8cbb") (package! hide-mode-line :pin "bc5d293576c5e08c29e694078b96a5ed85631942") (package! highlight-numbers :pin "8b4744c7f46c72b1d3d599d4fb75ef8183dee307") (package! rainbow-delimiters :pin "f40ece58df8b2f0fb6c8576b527755a552a5e763") @@ -24,10 +29,10 @@ ;; doom-editor.el (package! better-jumper :pin "47622213783ece37d5337dc28d33b530540fc319") -(package! dtrt-indent :pin "0230ec503283b895bd3df6c1e30b35a01aa0b9af") +(package! dtrt-indent :pin "5d1b44f9a1a484ca229cc14f8062609a10ef4891") (package! helpful :pin "a32a5b3d959a7fccf09a71d97b3d7c888ac31c69") -(package! pcre2el :pin "018531ba0cf8e2b28d1108136a0e031b6a45f1c1") -(package! smartparens :pin "0778a8a84064cf2bc3a9857bd0e7a4619cc1e5c3") +(package! pcre2el :pin "380723b2701cceb75c266440fb8db918f3340d50") +(package! smartparens :pin "ddc6233ea6fc2da7a3a8e44face465c15631b02b") (package! ws-butler ;; Use my fork of ws-butler, which has a few choice improvements and ;; optimizations (the original has been abandoned). @@ -35,13 +40,9 @@ :pin "572a10c11b6cb88293de48acbb59a059d36f9ba5") ;; doom-projects.el -(package! projectile :pin "e45f0b0cc43fdc066e7971ff3ed3bf4c78015ed0") -(package! project :pin "10a6b691e36ff897fb2a4b48896e08818afa77b0") +(package! projectile :pin "0163b335a18af0f077a474d4dc6b36e22b5e3274") +(package! project :pin "b6989856abe9411872bdff5c8aa190bef4d86409") ;; doom-keybinds.el -(package! general :pin "bda777cd303db217fd2fbf2087eff40ec4aafda1") -(package! which-key :pin "4d20bc852545a2e602f59084a630f888542052b1") - -(package! compat - :recipe (:host github :repo "emacs-compat/compat") - :pin "eb8fbfa5582a8e5880e2eaa66d15d498bca6a45a") +(package! general :pin "ced143c30de8e20f5a3761a465e684a1dc48471e") +(package! which-key :pin "96911a1d3faf8426a33241f4821319e98421f380") diff --git a/modules/app/everywhere/config.el b/modules/app/everywhere/config.el index d0512f754..32aaadc08 100644 --- a/modules/app/everywhere/config.el +++ b/modules/app/everywhere/config.el @@ -8,16 +8,12 @@ :config (set-yas-minor-mode! 'emacs-everywhere-mode) - ;; HACK Inhibit MAJOR-MODE-local-vars-hook in emacs-everywhere buffers, + ;; HACK: Inhibit MAJOR-MODE-local-vars-hook in emacs-everywhere buffers, ;; because Doom commonly starts servers and other extraneous services on ;; this hook, which will rarely work well in emacs-everywhere's temporary ;; buffers anyway. (setq-hook! 'emacs-everywhere-init-hooks doom-inhibit-local-var-hooks t) - ;; REVIEW: Fixes tecosaur/emacs-everywhere#75. Remove when dealt with - ;; upstream. - (define-key emacs-everywhere-mode-map "\C-c\C-c" #'emacs-everywhere-finish) - (after! doom-modeline (doom-modeline-def-segment emacs-everywhere (concat @@ -36,7 +32,7 @@ (doom-modeline-def-modeline 'emacs-everywhere '(bar modals emacs-everywhere buffer-position word-count parrot selection-info) - '(input-method major-mode checker + '(input-method major-mode check #(" " 0 1 ; "Exit to app" icon + a little padding (rear-nonsticky t display (raise -0.25) diff --git a/modules/app/everywhere/packages.el b/modules/app/everywhere/packages.el index 91e7e4040..7d9518f5f 100644 --- a/modules/app/everywhere/packages.el +++ b/modules/app/everywhere/packages.el @@ -1,4 +1,4 @@ ;; -*- no-byte-compile: t; -*- ;;; app/everywhere/packages.el -(package! emacs-everywhere :pin "fbeff19825336777dccaefedf3f376dd622cd294") +(package! emacs-everywhere :pin "bc91164151ab012ff884af92321557f9b37eeed1") diff --git a/modules/checkers/syntax/config.el b/modules/checkers/syntax/config.el index 3845e5a68..faa1b730e 100644 --- a/modules/checkers/syntax/config.el +++ b/modules/checkers/syntax/config.el @@ -51,16 +51,19 @@ :hook (flycheck-mode . +syntax-init-popups-h) :config (setq flycheck-popup-tip-error-prefix "X ") - (after! evil - ;; Don't display popups while in insert or replace mode, as it can affect - ;; the cursor's position or cause disruptive input delays. - (add-hook! '(evil-insert-state-entry-hook evil-replace-state-entry-hook) - #'flycheck-popup-tip-delete-popup) - (defadvice! +syntax--disable-flycheck-popup-tip-maybe-a (&rest _) - :before-while #'flycheck-popup-tip-show-popup - (if evil-local-mode - (eq evil-state 'normal) - (not (bound-and-true-p company-backend)))))) + + ;; HACK: Only display the flycheck popup if we're in normal mode (for evil + ;; users) or if no selection or completion is active. This popup can + ;; interfere with the active evil mode, clear active regions, and other + ;; funny business (see #7242). + (defadvice! +syntax--disable-flycheck-popup-tip-maybe-a (&rest _) + :before-while #'flycheck-popup-tip-show-popup + (if (and (bound-and-true-p evil-local-mode) + (not (evil-emacs-state-p))) + (evil-normal-state-p) + (and (not (region-active-p)) + (not (bound-and-true-p company-backend)) + (not (ignore-errors (>= corfu--index 0))))))) (use-package! flycheck-posframe diff --git a/modules/completion/company/packages.el b/modules/completion/company/packages.el index 43c389ea7..c4718a4aa 100644 --- a/modules/completion/company/packages.el +++ b/modules/completion/company/packages.el @@ -1,7 +1,7 @@ ;; -*- no-byte-compile: t; -*- ;;; completion/company/packages.el -(package! company :pin "02903bd7088d65a87df0ae0f0d0a7118de147b69") +(package! company :pin "b0a522ac5bf8ba3d2f4f22e3aa846a4f82978a16") (package! company-dict :pin "cd7b8394f6014c57897f65d335d6b2bd65dab1f4") (when (modulep! +childframe) - (package! company-box :pin "b6f53e26adf948aca55c3ff6c22c21a6a6614253")) + (package! company-box :pin "c4f2e243fba03c11e46b1600b124e036f2be7691")) diff --git a/modules/completion/corfu/README.org b/modules/completion/corfu/README.org index fa8502d99..46f85b855 100644 --- a/modules/completion/corfu/README.org +++ b/modules/completion/corfu/README.org @@ -212,6 +212,14 @@ A few variables may be set to change behavior of this module: Whether to prefer navigating org tables over cycling candidates when pressing [[kbd:][TAB]] and [[kbd:][S-TAB]]. +** Turning off auto-completion +To disable idle (as-you-type) completion, unset ~corfu-auto~: +#+begin_src emacs-lisp +;;; in $DOOMDIR/config.el +(after! corfu + (setq corfu-auto nil)) +#+end_src + ** Adding CAPFs to a mode To add other CAPFs on a mode-per-mode basis, put either of the following in your ~config.el~: @@ -242,7 +250,7 @@ all CAPFs are interactive to be called this way, in which case you can use * Troubleshooting [[doom-report:][Report an issue?]] -** Performance issues with ~cape-dabbrev~ +** Troubleshooting ~cape-dabbrev~ If you have performance issues with ~cape-dabbrev~, the first thing I recommend doing is to look at the list of buffers Dabbrev is scanning: @@ -255,6 +263,22 @@ doing is to look at the list of buffers Dabbrev is scanning: ... and modify ~dabbrev-ignored-buffer-regexps~ or ~dabbrev-ignored-buffer-modes~ accordingly. +If you see garbage completion candidates, you can use the following command to +debug the issue: + +#+begin_src emacs-lisp +;;;###autoload +(defun search-in-dabbrev-buffers (search-string) + "Search for SEARCH-STRING in all buffers returned by `dabbrev--select-buffers'." + (interactive "sSearch string: ") + (let ((buffers (dabbrev--select-buffers))) + (multi-occur buffers search-string))) + +;; Example usage: +;; Why are these weird characters appearing in my completions? +(search-in-dabbrev-buffers "\342\200\231") +#+end_src + ** Fixing TAB Keybindings If you encounter an issue where your ~TAB~ keybindings are not responding in Doom diff --git a/modules/completion/corfu/config.el b/modules/completion/corfu/config.el index f50ac40be..1f111cd7d 100644 --- a/modules/completion/corfu/config.el +++ b/modules/completion/corfu/config.el @@ -40,7 +40,8 @@ TAB/S-TAB.") ('aggressive (not (or (bound-and-true-p mct--active) (bound-and-true-p vertico--input) - (eq (current-local-map) read-passwd-map) + (and (featurep 'auth-source) + (eq (current-local-map) read-passwd-map)) (and (featurep 'helm-core) (helm--alive-p)) (and (featurep 'ido) (ido-active)) (where-is-internal 'minibuffer-complete @@ -53,7 +54,7 @@ TAB/S-TAB.") (corfu-mode +1)))) :config (setq corfu-auto t - corfu-auto-delay 0.1 + corfu-auto-delay 0.18 corfu-auto-prefix 2 global-corfu-modes '((not erc-mode @@ -67,8 +68,10 @@ TAB/S-TAB.") corfu-count 16 corfu-max-width 120 corfu-on-exact-match nil - corfu-quit-at-boundary (if (modulep! +orderless) 'separator t) - corfu-quit-no-match (if (modulep! +orderless) 'separator t) + corfu-quit-at-boundary (if (or (modulep! :completion vertico) + (modulep! +orderless)) + 'separator t) + corfu-quit-no-match corfu-quit-at-boundary tab-always-indent 'complete) (add-to-list 'completion-category-overrides `(lsp-capf (styles ,@completion-styles))) (add-to-list 'corfu-auto-commands #'lispy-colon) @@ -112,10 +115,10 @@ TAB/S-TAB.") (use-package! cape :defer t :init - (add-hook! prog-mode + (add-hook! 'prog-mode-hook (defun +corfu-add-cape-file-h () (add-hook 'completion-at-point-functions #'cape-file -10 t))) - (add-hook! (org-mode markdown-mode) + (add-hook! '(org-mode-hook markdown-mode-hook) (defun +corfu-add-cape-elisp-block-h () (add-hook 'completion-at-point-functions #'cape-elisp-block 0 t))) ;; Enable Dabbrev completion basically everywhere as a fallback. @@ -124,17 +127,23 @@ TAB/S-TAB.") ;; Set up `cape-dabbrev' options. (defun +dabbrev-friend-buffer-p (other-buffer) (< (buffer-size other-buffer) +corfu-buffer-scanning-size-limit)) - (add-hook! (prog-mode text-mode conf-mode comint-mode minibuffer-setup - eshell-mode) + (add-hook! '(prog-mode-hook + text-mode-hook + conf-mode-hook + comint-mode-hook + minibuffer-setup-hook + eshell-mode-hook) (defun +corfu-add-cape-dabbrev-h () (add-hook 'completion-at-point-functions #'cape-dabbrev 20 t))) (after! dabbrev (setq dabbrev-friend-buffer-function #'+dabbrev-friend-buffer-p dabbrev-ignored-buffer-regexps - '("^ " + '("\\` " "\\(TAGS\\|tags\\|ETAGS\\|etags\\|GTAGS\\|GRTAGS\\|GPATH\\)\\(<[0-9]+>\\)?") dabbrev-upcase-means-case-search t) - (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode))) + (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode) + (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode) + (add-to-list 'dabbrev-ignored-buffer-modes 'tags-table-mode))) ;; Make these capfs composable. (advice-add #'lsp-completion-at-point :around #'cape-wrap-noninterruptible) diff --git a/modules/completion/corfu/packages.el b/modules/completion/corfu/packages.el index cf45a992f..2dee62c70 100644 --- a/modules/completion/corfu/packages.el +++ b/modules/completion/corfu/packages.el @@ -1,12 +1,16 @@ ;; -*- no-byte-compile: t; -*- ;;; completion/corfu/packages.el -(package! corfu :pin "c1e7b6190b00158e67347b4db0a8f7964e5d2f8b") -(package! cape :pin "a397a0c92de38277b7f835fa999fac400a764908") +(package! corfu :pin "35cd5a0f3cba89766072e3e933d1fe2ee02f2289") +(package! cape :pin "e01e4430234850263d326ad4521849cd46e64059") (when (modulep! +icons) (package! nerd-icons-corfu :pin "7077bb76fefc15aed967476406a19dc5c2500b3c")) -(when (modulep! +orderless) - (package! orderless :pin "b24748093b00b37c3a572c4909f61c08fa27504f")) +(when (and (not (modulep! :completion vertico)) + (modulep! +orderless)) + ;; enabling +orderless without vertico should be fairly niche enough that to + ;; save contributor headaches we should only pin vertico's orderless and leave + ;; this one unpinned + (package! orderless)) (when (modulep! :os tty) (package! corfu-terminal :pin "501548c3d51f926c687e8cd838c5865ec45d03cc")) (when (modulep! :editor snippets) diff --git a/modules/completion/helm/config.el b/modules/completion/helm/config.el index 7f983f872..7dedabbf1 100644 --- a/modules/completion/helm/config.el +++ b/modules/completion/helm/config.el @@ -43,7 +43,9 @@ Can be negative.") ;; symbol at point. helm-imenu-execute-action-at-once-if-one nil ;; Disable special behavior for left/right, M-left/right keys. - helm-ff-lynx-style-map nil) + helm-ff-lynx-style-map nil + ;; Don't commandeer the entire frame for helm commands. + helm-always-two-windows nil) (map! [remap apropos] #'helm-apropos [remap find-library] #'helm-locate-library @@ -188,7 +190,13 @@ Can be negative.") (use-package! helm-descbinds - :hook (helm-mode . helm-descbinds-mode)) + :hook (helm-mode . helm-descbinds-mode) + :config + ;; HACK: Upstream claims that the two packages are incompatible, but changing + ;; `prefix-help-command' seems to smooth the incompatibility over. More + ;; testing is needed... + (setq helm-descbinds-disable-which-key nil + prefix-help-command #'helm-descbinds)) (use-package! helm-icons diff --git a/modules/completion/helm/packages.el b/modules/completion/helm/packages.el index d348d6437..d7a7ae7de 100644 --- a/modules/completion/helm/packages.el +++ b/modules/completion/helm/packages.el @@ -1,10 +1,10 @@ ;; -*- no-byte-compile: t; -*- ;;; completion/helm/packages.el -(package! helm :pin "f34ea6b702648e5c7535a704bdb6c4d7afb4b3b8") +(package! helm :pin "28f62344fed0d8be0bcef5aa8a018ba58198ba0c") (package! helm-company :pin "4622b82353220ee6cc33468f710fa5b6b253b7f1") (package! helm-c-yasnippet :pin "c5880e740da101fde7a995e94a7b16c330e57583") -(package! helm-descbinds :pin "b72515982396b6e336ad7beb6767e95a80fca192") +(package! helm-descbinds :pin "ca03f02da4e54a1d0a2d5498b86e1639aa808d8c") (package! helm-describe-modes :pin "11fb36af119b784539d31c6160002de1957408aa") (package! helm-projectile :pin "e2e38825c975269a4971df25e79b2ae98929624e") (package! helm-rg :pin "ee0a3c09da0c843715344919400ab0a0190cc9dc") diff --git a/modules/completion/ivy/packages.el b/modules/completion/ivy/packages.el index a5dce1fb1..beafb3133 100644 --- a/modules/completion/ivy/packages.el +++ b/modules/completion/ivy/packages.el @@ -1,7 +1,7 @@ ;; -*- no-byte-compile: t; -*- ;;; completion/ivy/packages.el -(package! swiper :pin "8c30f4cab5948aa8d942a3b2bbf5fb6a94d9441d") +(package! swiper :pin "1f88e5499046d166d22bf733a3877aec3b424947") (package! ivy) (package! ivy-hydra) (package! ivy-avy) @@ -13,7 +13,7 @@ (package! wgrep :pin "208b9d01cfffa71037527e3a324684b3ce45ddc4") (if (modulep! +prescient) - (package! ivy-prescient :pin "4b875be52e75f7b81e68a16b62cfbb2f2584042c") + (package! ivy-prescient :pin "c39bf07c56b427bf41aafd7d20eaef5cf3c312b5") (when (modulep! +fuzzy) (package! flx :pin "4b1346eb9a8a76ee9c9dede69738c63ad97ac5b6"))) diff --git a/modules/completion/vertico/config.el b/modules/completion/vertico/config.el index e15bd0fb7..a25826e53 100644 --- a/modules/completion/vertico/config.el +++ b/modules/completion/vertico/config.el @@ -83,6 +83,9 @@ orderless." ((string= "!" pattern) `(orderless-literal . "")) ;; Without literal ((string-prefix-p "!" pattern) `(orderless-without-literal . ,(substring pattern 1))) + ;; Annotation + ((string-prefix-p "&" pattern) `(orderless-annotation . ,(substring pattern 1))) + ((string-suffix-p "&" pattern) `(orderless-annotation . ,(substring pattern 0 -1))) ;; Character folding ((string-prefix-p "%" pattern) `(char-fold-to-regexp . ,(substring pattern 1))) ((string-suffix-p "%" pattern) `(char-fold-to-regexp . ,(substring pattern 0 -1))) @@ -157,13 +160,16 @@ orderless." (consult-customize consult-ripgrep consult-git-grep consult-grep consult-bookmark consult-recent-file - +default/search-project +default/search-other-project - +default/search-project-for-symbol-at-point - +default/search-cwd +default/search-other-cwd - +default/search-notes-for-symbol-at-point - +default/search-emacsd consult--source-recent-file consult--source-project-recent-file consult--source-bookmark :preview-key "C-SPC") + (when (modulep! :config default) + (consult-customize + +default/search-project +default/search-other-project + +default/search-project-for-symbol-at-point + +default/search-cwd +default/search-other-cwd + +default/search-notes-for-symbol-at-point + +default/search-emacsd + :preview-key "C-SPC")) (consult-customize consult-theme :preview-key (list "C-SPC" :debounce 0.5 'any)) @@ -195,13 +201,20 @@ orderless." (use-package! consult-dir - :bind (([remap list-directory] . consult-dir) + :defer t + :init + (map! [remap list-directory] #'consult-dir + (:after vertico :map vertico-map - ("C-x C-d" . consult-dir) - ("C-x C-j" . consult-dir-jump-file)) + "C-x C-d" #'consult-dir + "C-x C-j" #'consult-dir-jump-file)) :config + ;; DEPRECATED: Remove when Doom core replaces projectile with project.el + (setq consult-dir-project-list-function #'consult-dir-projectile-dirs) + (when (modulep! :tools docker) - ;; TODO Replace with `tramp-container--completion-function' when we drop support for <29 + ;; TODO: Replace with `tramp-container--completion-function' when we drop + ;; support for <29 (defun +vertico--consult-dir-container-hosts (host) "Get a list of hosts from HOST." (cl-loop for line in (cdr @@ -209,10 +222,7 @@ orderless." (apply #'process-lines +vertico-consult-dir-container-executable (append +vertico-consult-dir-container-args (list "ps"))))) for cand = (split-string line "[[:space:]]+" t) - collect (let ((user (unless (string-empty-p (car cand)) - (concat (car cand) "@"))) - (hostname (car (last cand)))) - (format "/%s:%s%s:/" host user hostname)))) + collect (format "/%s:%s:/" host (car (last cand))))) (defun +vertico--consult-dir-podman-hosts () (let ((+vertico-consult-dir-container-executable "podman")) @@ -229,7 +239,7 @@ orderless." :face consult-file :history file-name-history :items ,#'+vertico--consult-dir-podman-hosts) - "Podman candiadate source for `consult-dir'.") + "Podman candidate source for `consult-dir'.") (defvar +vertico--consult-dir-source-tramp-docker `(:name "Docker" @@ -238,7 +248,7 @@ orderless." :face consult-file :history file-name-history :items ,#'+vertico--consult-dir-docker-hosts) - "Docker candiadate source for `consult-dir'.") + "Docker candidate source for `consult-dir'.") (add-to-list 'consult-dir-sources '+vertico--consult-dir-source-tramp-podman t) (add-to-list 'consult-dir-sources '+vertico--consult-dir-source-tramp-docker t)) diff --git a/modules/completion/vertico/packages.el b/modules/completion/vertico/packages.el index 8d1f9c75f..e93edda1b 100644 --- a/modules/completion/vertico/packages.el +++ b/modules/completion/vertico/packages.el @@ -1,19 +1,19 @@ ;; -*- no-byte-compile: t; -*- ;;; completion/vertico/packages.el -(package! vertico :pin "68cbd47589446e9674921bae0b98ff8fbe28be23") +(package! vertico :pin "68e51fda552a2f91caab69e83564bc91275b09b1") -(package! orderless :pin "dc7a781acf2e58ac7d20d1b522be0cde5213e057") +(package! orderless :pin "ac4aeb66f331f4c4a430d5556071e33177304c37") -(package! consult :pin "b48ff6bf0527baeb6bfd07c6da9d303ff0b79c3d") +(package! consult :pin "c87b0bf06de0c3cb60bc8d257c770cb981ddcd19") (package! consult-dir :pin "3f5f4b71ebe819392cb090cda71bd39a93bd830a") (when (and (modulep! :checkers syntax) (not (modulep! :checkers syntax +flymake))) (package! consult-flycheck :pin "754f5497d827f7d58009256a21af614cc44378a3")) -(package! embark :pin "c93abadc8220c0caa6fea805f7a736c346d47e7e") -(package! embark-consult :pin "c93abadc8220c0caa6fea805f7a736c346d47e7e") +(package! embark :pin "d3c9d1b4c890cf365846cc2b418f37341999e79f") +(package! embark-consult :pin "d3c9d1b4c890cf365846cc2b418f37341999e79f") -(package! marginalia :pin "f6fe86b989a177355ab3ff7e97a384e10a7b0bb1") +(package! marginalia :pin "3275d1f85cb020280979a050054b843f7563aea2") (package! wgrep :pin "208b9d01cfffa71037527e3a324684b3ce45ddc4") diff --git a/modules/config/default/+evil-bindings.el b/modules/config/default/+evil-bindings.el index 874d054e8..1726297be 100644 --- a/modules/config/default/+evil-bindings.el +++ b/modules/config/default/+evil-bindings.el @@ -434,8 +434,11 @@ ;;; c --- code (:prefix-map ("c" . "code") (:when (and (modulep! :tools lsp) (not (modulep! :tools lsp +eglot))) - :desc "LSP Execute code action" "a" #'lsp-execute-code-action - :desc "LSP Organize imports" "o" #'lsp-organize-imports + :desc "LSP Execute code action" "a" #'lsp-execute-code-action + :desc "LSP Organize imports" "o" #'lsp-organize-imports + :desc "LSP" "l" #'+default/lsp-command-map + :desc "LSP Rename" "r" #'lsp-rename + :desc "Symbols" "S" #'lsp-treemacs-symbols (:when (modulep! :completion ivy) :desc "Jump to symbol in current workspace" "j" #'lsp-ivy-workspace-symbol :desc "Jump to symbol in any workspace" "J" #'lsp-ivy-global-workspace-symbol) @@ -449,10 +452,7 @@ :desc "Errors list" "X" #'lsp-treemacs-errors-list :desc "Incoming call hierarchy" "y" #'lsp-treemacs-call-hierarchy :desc "Outgoing call hierarchy" "Y" (cmd!! #'lsp-treemacs-call-hierarchy t) - :desc "References tree" "R" (cmd!! #'lsp-treemacs-references t) - :desc "Symbols" "S" #'lsp-treemacs-symbols - :desc "LSP" "l" #'+default/lsp-command-map - :desc "LSP Rename" "r" #'lsp-rename)) + :desc "References tree" "R" (cmd!! #'lsp-treemacs-references t))) (:when (modulep! :tools lsp +eglot) :desc "LSP Execute code action" "a" #'eglot-code-actions :desc "LSP Rename" "r" #'eglot-rename diff --git a/modules/editor/evil/packages.el b/modules/editor/evil/packages.el index b38f6ebe4..bb6a67e7c 100644 --- a/modules/editor/evil/packages.el +++ b/modules/editor/evil/packages.el @@ -1,8 +1,8 @@ ;; -*- no-byte-compile: t; -*- ;;; editor/evil/packages.el -(package! evil :pin "5995f6f21f662484440ed67a28ce59e365feb9ad") -(package! evil-args :pin "2671071a4a57eaee7cc8c27b9e4b6fc60fd2ccd3") +(package! evil :pin "0251080640e0da6f0eec2b7d8dd70e9c9b9915d7") +(package! evil-args :pin "a8151556f63c9d45d0c44c8a7ef9e5a542f3cdc7") (package! evil-easymotion :pin "f96c2ed38ddc07908db7c3c11bcd6285a3e8c2e9") (package! evil-embrace :pin "3081d37811b6a3dfaaf01d578c7ab7a746c6064d") (package! evil-escape @@ -11,10 +11,10 @@ (package! evil-exchange :pin "5f0a2d41434c17c6fb02e4f744043775de1c63a2") (package! evil-indent-plus :pin "f392696e4813f1d3a92c7eeed333248914ba6dae") (package! evil-lion :pin "1e838a53b8f18a3c8bdf3e952186abc2ee9cb98e") -(package! evil-nerd-commenter :pin "3b197a2b559b06a7cf39978704b196f53dac802a") +(package! evil-nerd-commenter :pin "ae52c5070a48793e2c24474c9c8dbf20175d18a0") (package! evil-numbers :pin "7a1b62afc12da2b582bf84d722e7b10ca8b97065") (package! evil-snipe :pin "c2108d3932fcd2f75ac3e48250d6badd668f5b4f") -(package! evil-surround :pin "c7116cdc774b1e259eaf3e9e7a318a6c99c2da17") +(package! evil-surround :pin "da05c60b0621cf33161bb4335153f75ff5c29d91") (package! evil-textobj-anyblock :recipe (:host github :repo "willghatch/evil-textobj-anyblock" @@ -35,4 +35,4 @@ (package! neotree) (autoload 'neotree-make-executor "neotree" nil nil 'macro)) - (package! evil-collection :pin "8c84f9bc89fe56e71b56519f886085ddcbc671cf")) + (package! evil-collection :pin "ca977acb83c0dd01fc57dbc6f3d3111e89f4ec9d")) diff --git a/modules/editor/fold/autoload/fold.el b/modules/editor/fold/autoload/fold.el index 1052374bb..8e3e8cf34 100644 --- a/modules/editor/fold/autoload/fold.el +++ b/modules/editor/fold/autoload/fold.el @@ -78,6 +78,18 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." ((+fold--hideshow-fold-p) (+fold-from-eol (hs-toggle-hiding))) ((+fold--ts-fold-p) (ts-fold-toggle))))) +;;;###autoload +(defun +fold/open-rec () + "Recursively open the folded region at point. + +Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." + (interactive) + (save-excursion + (cond ((+fold--vimish-fold-p) (vimish-fold-unfold)) + ((+fold--outline-fold-p) (outline-show-subtree)) + ((+fold--hideshow-fold-p) (+fold-from-eol (hs-show-block))) + ((+fold--ts-fold-p) (ts-fold-open))))) + ;;;###autoload (defun +fold/open () "Open the folded region at point. @@ -87,7 +99,7 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." (save-excursion (cond ((+fold--vimish-fold-p) (vimish-fold-unfold)) ((+fold--outline-fold-p) - (outline-show-children) + (outline-show-branches) (outline-show-entry)) ((+fold--hideshow-fold-p) (+fold-from-eol (hs-show-block))) ((+fold--ts-fold-p) (ts-fold-open))))) @@ -111,7 +123,7 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." (list (if current-prefix-arg (prefix-numeric-value current-prefix-arg)))) (cond ((+fold--ts-fold-p) (ts-fold-open-all)) - ((featurep 'vimish-fold) + ((and (featurep 'vimish-fold) (+fold--vimish-fold-p)) (vimish-fold-unfold-all)) ((save-excursion (+fold--ensure-hideshow-mode) @@ -138,8 +150,12 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." (+fold--ensure-hideshow-mode) (hs-life-goes-on (if (integerp level) - (hs-hide-level-recursive (1- level) (point-min) (point-max)) - (hs-hide-all))))))) + (progn + (outline--show-headings-up-to-level (1+ level)) + (hs-hide-level-recursive (1- level) (point-min) (point-max))) + (hs-hide-all) + (when (fboundp 'outline-hide-sublevels) + (outline-show-only-headings)))))))) ;;;###autoload (defun +fold/next (count) diff --git a/modules/editor/fold/config.el b/modules/editor/fold/config.el index c30b5a80e..e1f7dc21c 100644 --- a/modules/editor/fold/config.el +++ b/modules/editor/fold/config.el @@ -6,7 +6,7 @@ [remap evil-toggle-fold] #'+fold/toggle [remap evil-close-fold] #'+fold/close [remap evil-open-fold] #'+fold/open - [remap evil-open-fold-rec] #'+fold/open + [remap evil-open-fold-rec] #'+fold/open-rec [remap evil-close-folds] #'+fold/close-all [remap evil-open-folds] #'+fold/open-all) (after! evil diff --git a/modules/editor/snippets/packages.el b/modules/editor/snippets/packages.el index 3b3b46387..2c865ec1e 100644 --- a/modules/editor/snippets/packages.el +++ b/modules/editor/snippets/packages.el @@ -1,10 +1,10 @@ ;; -*- no-byte-compile: t; -*- ;;; editor/snippets/packages.el -(package! yasnippet :pin "297546f0853a6a51f5b05e954d0c6aea8caa5ec2") +(package! yasnippet :pin "eb5ba2664c3a68ae4a53bb38b85418dd131b208f") (package! auto-yasnippet :pin "6a9e406d0d7f9dfd6dff7647f358cb05a0b1637e") (package! doom-snippets :recipe (:host github :repo "doomemacs/snippets" :files (:defaults "*")) - :pin "f022984ee1318a4015d5d081b3c3dab5a60dc6ff") + :pin "c1384cc7975ee7ca7d551eb56c104d768440c3cb") diff --git a/modules/emacs/vc/config.el b/modules/emacs/vc/config.el index 3ea79365c..d0a4f2190 100644 --- a/modules/emacs/vc/config.el +++ b/modules/emacs/vc/config.el @@ -28,10 +28,13 @@ "k" #'log-view-msg-prev)) -(after! vc-annotate +(after! vc (set-popup-rules! - '(("^\\*vc-diff" :select nil) ; *vc-diff* - ("^\\*vc-change" :select t))) ; *vc-change-log* + '(("^\\*vc-diff" :select nil :size '+popup-shrink-to-fit) + ("^\\*vc-change-log" :select t)))) + + +(after! vc-annotate (set-evil-initial-state! 'vc-annotate-mode 'normal) ;; Clean up after itself diff --git a/modules/emacs/vc/packages.el b/modules/emacs/vc/packages.el index 7b1f30628..4602753ae 100644 --- a/modules/emacs/vc/packages.el +++ b/modules/emacs/vc/packages.el @@ -6,9 +6,9 @@ (package! smerge-mode :built-in t) (package! browse-at-remote :pin "76aa27dfd469fcae75ed7031bb73830831aaccbf") -(package! git-commit :pin "b68e0a3c3388af8daac662f25ccfd3e980590e12") +(package! git-commit :pin "b5637d665c1e5bd5b76ffb072dbac387f37a5f63") (package! git-timemachine ;; The original lives on codeberg.org; which has uptime issues. :recipe (:host github :repo "emacsmirror/git-timemachine") - :pin "ac933e5cd29583c131401f3bd991d98129c316df") + :pin "5ed73c3831cf6da10ba941e6abba708a86853e8f") (package! git-modes :pin "3cc94974c09c43462dfbfbe20396a414352dbb92") diff --git a/modules/email/mu4e/autoload/email.el b/modules/email/mu4e/autoload/email.el index 336ed40f1..f9efcbf74 100644 --- a/modules/email/mu4e/autoload/email.el +++ b/modules/email/mu4e/autoload/email.el @@ -33,8 +33,11 @@ default/fallback account." :enter-func (lambda () (mu4e-message "Switched to %s" label)) :leave-func - (lambda () (progn (setq +mu4e-personal-addresses nil) - (mu4e-clear-caches))) + (lambda () + (setq +mu4e-personal-addresses nil) + ;; REVIEW: `mu4e-clear-caches' was removed in 1.12.2, but + ;; may still be useful to users on older versions. + (if (fboundp 'mu4e-clear-caches) (mu4e-clear-caches))) :match-func (lambda (msg) (when msg diff --git a/modules/email/mu4e/config.el b/modules/email/mu4e/config.el index f4f6d9c5b..072309620 100644 --- a/modules/email/mu4e/config.el +++ b/modules/email/mu4e/config.el @@ -75,6 +75,7 @@ is non-nil." (setq mu4e-get-mail-command "offlineimap -o -q"))) (setq mu4e-update-interval nil + mu4e-notification-support t mu4e-sent-messages-behavior 'sent mu4e-hide-index-messages t ;; configuration for sending mail @@ -671,77 +672,3 @@ See `+mu4e-msg-gmail-p' and `mu4e-sent-messages-behavior'.") (`refile (mu4e-action-retag-message msg "-\\Inbox")) (`flag (mu4e-action-retag-message msg "+\\Starred")) (`unflag (mu4e-action-retag-message msg "-\\Starred")))))))) - -;; -;;; Alerts - -(use-package! mu4e-alert - :after mu4e - :config - (setq doom-modeline-mu4e t) - - (mu4e-alert-enable-mode-line-display) - (mu4e-alert-enable-notifications) - - (when (version<= "1.6" mu4e-mu-version) - (defadvice! +mu4e-alert-filter-repeated-mails-fixed-a (mails) - "Filters the MAILS that have been seen already\nUses :message-id not :docid." - :override #'mu4e-alert-filter-repeated-mails - (cl-remove-if (lambda (mail) - (prog1 (and (not mu4e-alert-notify-repeated-mails) - (ht-get mu4e-alert-repeated-mails - (plist-get mail :message-id))) - (ht-set! mu4e-alert-repeated-mails - (plist-get mail :message-id) - t))) - mails))) - - (when (featurep :system 'linux) - (mu4e-alert-set-default-style 'libnotify) - - (defvar +mu4e-alert-bell-cmd '("paplay" . "/usr/share/sounds/freedesktop/stereo/message.oga") - "Cons list with command to play a sound, and the sound file to play. -Disabled when set to nil.") - - (setq mu4e-alert-email-notification-types '(subjects)) - (defun +mu4e-alert-grouped-mail-notification-formatter-with-bell (mail-group _all-mails) - "Default function to format MAIL-GROUP for notification. -ALL-MAILS are the all the unread emails" - (when +mu4e-alert-bell-cmd - (start-process "mu4e-alert-bell" nil (car +mu4e-alert-bell-cmd) (cdr +mu4e-alert-bell-cmd))) - (if (> (length mail-group) 1) - (let* ((mail-count (length mail-group)) - (first-mail (car mail-group)) - (title-prefix (format "You have %d unread emails" - mail-count)) - (field-value (mu4e-alert--get-group first-mail)) - (title-suffix (format (pcase mu4e-alert-group-by - (`:from "from %s:") - (`:to "to %s:") - (`:maildir "in %s:") - (`:priority "with %s priority:") - (`:flags "with %s flags:")) - field-value)) - (title (format "%s %s" title-prefix title-suffix))) - (list :title title - :body (s-join "\n" - (mapcar (lambda (mail) - (format "%s%s • %s" - (cond - ((plist-get mail :in-reply-to) "⮩ ") - ((string-match-p "\\`Fwd:" - (plist-get mail :subject)) " ⮯ ") - (t "  ")) - (truncate-string-to-width (or (caar (plist-get mail :from)) - (cdar (plist-get mail :from))) - 20 nil nil t) - (truncate-string-to-width - (replace-regexp-in-string "\\`Re: \\|\\`Fwd: " "" - (plist-get mail :subject)) - 40 nil nil t))) - mail-group)))) - (let* ((new-mail (car mail-group)) - (subject (plist-get new-mail :subject)) - (sender (caar (plist-get new-mail :from)))) - (list :title sender :body subject)))) - (setq mu4e-alert-grouped-mail-notification-formatter #'+mu4e-alert-grouped-mail-notification-formatter-with-bell))) diff --git a/modules/email/mu4e/packages.el b/modules/email/mu4e/packages.el index 6e0aa3fda..1d2642782 100644 --- a/modules/email/mu4e/packages.el +++ b/modules/email/mu4e/packages.el @@ -3,5 +3,3 @@ (when (modulep! +org) (package! org-msg :pin "0b65f0f77a7a71881ddfce19a8cdc60465bda057")) - -(package! mu4e-alert :pin "6beda20fc69771f2778f507c4a9e069dbaf1b628") diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index 9b1c2acc3..c4b0ce5ad 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -78,7 +78,8 @@ This is ignored by ccls.") :return "return" :yield "#require") - (add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.c\\(c\\|pp\\)\\'" "\\1.\\(h\\|hh\\|hpp\\)")) + (add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.c\\(c\\|pp\\)?\\'" "\\1.h\\(h\\|pp\\)?\\'")) + (add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.h\\(h\\|pp\\)?\\'" "\\1.c\\(c\\|pp\\)?\\'")) (when (modulep! +tree-sitter) (add-hook! '(c-mode-local-vars-hook diff --git a/modules/lang/common-lisp/config.el b/modules/lang/common-lisp/config.el index e24ffcbb5..8f866be0c 100644 --- a/modules/lang/common-lisp/config.el +++ b/modules/lang/common-lisp/config.el @@ -174,3 +174,8 @@ :defer t :init (add-to-list 'sly-contribs 'sly-asdf 'append)) + +(use-package! sly-stepper + :defer t + :init + (add-to-list 'sly-contribs 'sly-stepper)) diff --git a/modules/lang/common-lisp/packages.el b/modules/lang/common-lisp/packages.el index 07c972ca4..00d0923d5 100644 --- a/modules/lang/common-lisp/packages.el +++ b/modules/lang/common-lisp/packages.el @@ -3,6 +3,9 @@ (when (package! sly :pin "ed17d2c2bd7aead0fbb09c3d22861c80a522a097") (package! sly-asdf :pin "6f9d751469bb82530db1673c22e7437ca6c95f45") + (package! sly-quicklisp :pin "34c73d43dd9066262387c626c17a9b486db07b2d") + (package! sly-stepper :recipe (:host github :repo "joaotavora/sly-stepper" + :files (:defaults "*.lisp" "*.asd"))) (package! sly-macrostep :pin "5113e4e926cd752b1d0bcc1508b3ebad5def5fad") (package! sly-repl-ansi-color :pin "b9cd52d1cf927bf7e08582d46ab0bcf1d4fb5048") (package! sly-overlay :pin "916b50297a1f3bb110f840b89b8717d194623e5f")) diff --git a/modules/lang/emacs-lisp/autoload.el b/modules/lang/emacs-lisp/autoload.el index d2092fa9c..2fcd75a23 100644 --- a/modules/lang/emacs-lisp/autoload.el +++ b/modules/lang/emacs-lisp/autoload.el @@ -413,20 +413,6 @@ This generally applies to your private config (`doom-user-dir') or Doom's source ;; ;;; Fontification -;;;###autoload -(defun +emacs-lisp-truncate-pin () - "Truncates long SHA1 hashes in `package!' :pin's." - (save-excursion - (goto-char (match-beginning 0)) - (and (stringp (plist-get (sexp-at-point) :pin)) - (search-forward ":pin" nil t) - (let ((start (re-search-forward "\"[^\"\n]\\{12\\}" nil t)) - (finish (and (re-search-forward "\"" (line-end-position) t) - (match-beginning 0)))) - (when (and start finish) - (put-text-property start finish 'display "..."))))) - nil) - (defvar +emacs-lisp--face nil) ;;;###autoload (defun +emacs-lisp-highlight-vars-and-faces (end) diff --git a/modules/lang/emacs-lisp/config.el b/modules/lang/emacs-lisp/config.el index 389589689..4a7b532f8 100644 --- a/modules/lang/emacs-lisp/config.el +++ b/modules/lang/emacs-lisp/config.el @@ -115,8 +115,6 @@ See `+emacs-lisp-non-package-mode' for details.") 'emacs-lisp-mode (append `(;; custom Doom cookies ("^;;;###\\(autodef\\|if\\|package\\)[ \n]" (1 font-lock-warning-face t))) - ;; Shorten the :pin of `package!' statements to 10 characters - `(("(package!\\_>" (0 (+emacs-lisp-truncate-pin)))) ;; highlight defined, special variables & functions (when +emacs-lisp-enable-extra-fontification `((+emacs-lisp-highlight-vars-and-faces . +emacs-lisp--face))))) diff --git a/modules/lang/factor/autoload.el b/modules/lang/factor/autoload.el new file mode 100644 index 000000000..c61098fe1 --- /dev/null +++ b/modules/lang/factor/autoload.el @@ -0,0 +1,8 @@ +;;; lang/factor/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(defun +factor/open-repl () + "Open the Factor Listener." + (interactive) + (call-interactively #'run-factor) + (current-buffer)) diff --git a/modules/lang/factor/config.el b/modules/lang/factor/config.el index 4f89a79e4..f863f27a4 100644 --- a/modules/lang/factor/config.el +++ b/modules/lang/factor/config.el @@ -5,73 +5,79 @@ :init (after! factor-mode (set-eval-handler! 'factor-mode #'fuel-eval-region) - (set-repl-handler! 'factor-mode #'run-factor)) + (set-repl-handler! 'factor-mode #'+factor/open-repl + :persist t + :send-region #'fuel-eval-region + :send-buffer #'fuel-run-file) + (set-lookup-handlers! 'factor-mode + :definition #'fuel-edit-word-at-point + :references #'fuel-show-callers + :documentation #'fuel-help) + (map! :map factor-mode-map + :localleader + "t" #'fuel-test-vocab + "F" #'fuel-run-file + "f" #'run-factor + "a" #'fuel-refresh-all + "L" #'fuel-load-usings + "u" #'fuel-vocab-usage + "U" #'fuel-vocab-uses + (:prefix ("c" . "change") + "w" #'fuel-edit-word-at-point + "d" #'fuel-edit-word-doc-at-point + "v" #'fuel-edit-vocabulary) + (:prefix ("e" . "eval") + "d" #'fuel-eval-definition + "R" #'fuel-eval-extended-region + "r" #'fuel-eval-region) + (:prefix ("h" . "help") + "p" #'fuel-apropos + "h" #'fuel-help + "b" #'fuel-help-display-bookmarks + "v" #'fuel-help-vocab + "w" #'fuel-show-file-words + "c" #'fuel-show-callees + "e" #'fuel-stack-effect-region + "s" #'fuel-stack-effect-sexp) + (:prefix ("s" . "scaffold") + "v" #'fuel-scaffold-vocab + "h" #'fuel-scaffold-help + "t" #'fuel-scaffold-tests) + (:prefix ("r" . "refactor") + "s" #'fuel-refactor-extract-sexp + "w" #'fuel-refactor-extract-region + "v" #'fuel-refactor-extract-vocab + "i" #'fuel-refactor-inline-word + "g" #'fuel-refactor-make-generic + "u" #'fuel-update-usings + "r" #'fuel-refactor-rename-word))) :config - (set-lookup-handlers! 'factor-mode - :definition #'fuel-edit-word-at-point - :references #'fuel-show-callers - :documentation #'fuel-help)) + (set-popup-rules! + '(("^\\*fuel \\(debug\\|xref\\|messages\\)\\*$" :slot 1 :vslot -1) + ("^\\*fuel help\\*$" :slot 2 :vslot 2 :select t :size 0.35) + ("^\\*fuel listener\\*$" :size 0.3 :quit nil :ttl nil))) -(map! :after fuel-help - :map fuel-help-mode-map - :localleader - "e" #'fuel-help-edit - "d" #'fuel-help-delete-bookmark - "B" #'fuel-help-display-bookmarks - "n" #'fuel-help-next - "d" #'fuel-help-kill-page - "p" #'fuel-help-previous - "b" #'fuel-help-bookmark-page - "e" #'fuel-help-edit) + (map! :after fuel-help + :map fuel-help-mode-map + :localleader + "e" #'fuel-help-edit + "d" #'fuel-help-delete-bookmark + "B" #'fuel-help-display-bookmarks + "n" #'fuel-help-next + "d" #'fuel-help-kill-page + "p" #'fuel-help-previous + "b" #'fuel-help-bookmark-page + "e" #'fuel-help-edit) -(map! :after factor-mode - :map factor-mode-map - :localleader - "t" #'fuel-test-vocab - "F" #'fuel-run-file - "f" #'run-factor - "a" #'fuel-refresh-all - "L" #'fuel-load-usings - "u" #'fuel-vocab-usage - "U" #'fuel-vocab-uses - (:prefix ("c" . "change") - "w" #'fuel-edit-word-at-point - "d" #'fuel-edit-word-doc-at-point - "v" #'fuel-edit-vocabulary) - (:prefix ("e" . "eval") - "d" #'fuel-eval-definition - "R" #'fuel-eval-extended-region - "r" #'fuel-eval-region) - (:prefix ("h" . "help") - "p" #'fuel-apropos - "h" #'fuel-help - "b" #'fuel-help-display-bookmarks - "v" #'fuel-help-vocab - "w" #'fuel-show-file-words - "c" #'fuel-show-callees - "e" #'fuel-stack-effect-region - "s" #'fuel-stack-effect-sexp) - (:prefix ("s" . "scaffold") - "v" #'fuel-scaffold-vocab - "h" #'fuel-scaffold-help - "t" #'fuel-scaffold-tests) - (:prefix ("r" . "refactor") - "s" #'fuel-refactor-extract-sexp - "w" #'fuel-refactor-extract-region - "v" #'fuel-refactor-extract-vocab - "i" #'fuel-refactor-inline-word - "g" #'fuel-refactor-make-generic - "u" #'fuel-update-usings - "r" #'fuel-refactor-rename-word)) + (map! :after fuel-listener + :map fuel-listener-mode-map + :localleader + "b" #'fuel-switch-to-buffer + "w" #'fuel-switch-to-buffer-other-window + "f" #'fuel-switch-to-buffer-other-frame + "e" #'fuel-edit-vocabulary + "r" #'fuel-refresh-all + "i" #'fuel-stack-mode + "h" #'fuel-help + "s" #'fuel-scaffold-vocab)) -(map! :after fuel-listener - :map fuel-listener-mode-map - :localleader - "b" #'fuel-switch-to-buffer - "w" #'fuel-switch-to-buffer-other-window - "f" #'fuel-switch-to-buffer-other-frame - "e" #'fuel-edit-vocabulary - "r" #'fuel-refresh-all - "i" #'fuel-stack-mode - "h" #'fuel-help - "s" #'fuel-scaffold-vocab) diff --git a/modules/lang/factor/packages.el b/modules/lang/factor/packages.el index f6b4aff31..55ec98480 100644 --- a/modules/lang/factor/packages.el +++ b/modules/lang/factor/packages.el @@ -1,4 +1,4 @@ ;; -*- no-byte-compile: t; -*- ;;; lang/factor/packages.el -(package! fuel :pin "23fcfc70753abbbdc0e86af06330d63da6e4ea64") +(package! fuel :pin "12fc9d5071e46cac7b558204db5f4f09ea56e9c7") diff --git a/modules/lang/graphql/README.org b/modules/lang/graphql/README.org index 7a6952545..e09e32f00 100644 --- a/modules/lang/graphql/README.org +++ b/modules/lang/graphql/README.org @@ -91,7 +91,7 @@ query GetContinents($continentCode: String!) { With this module, there are 3 ways to view schemas: + =+graphql-doc-open-config= which uses a local [[https://github.com/jimkyndemeyer/graphql-config-examples][=.graphqlconfig=]] file to seed endpoints to query + =graphql-doc= which prompts you to select an endpoint based on ones added manually by =graphql-doc-add-api= -+ =graphql-doc-open-url= which prompts to to manually enter an endpoint url ++ =graphql-doc-open-url= which prompts to manually enter an endpoint url When using the doc viewer, there are a few bindings for navigating around. diff --git a/modules/lang/julia/README.org b/modules/lang/julia/README.org index 38e019278..97f8094b6 100644 --- a/modules/lang/julia/README.org +++ b/modules/lang/julia/README.org @@ -20,22 +20,23 @@ This module adds support for [[https://julialang.org/][the Julia language]] to D - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text editing. Requires [[doom-module::tools tree-sitter]]. -- +snail :: Use Snail, a development environment and REPL interaction package - for Julia in the spirit of Common Lisp’s SLIME and Clojure’s CIDER. It enables - convenient and dynamic REPL-driven development. +- +snail :: + Use Snail, a development environment and REPL interaction package for Julia in + the spirit of Common Lisp’s SLIME and Clojure’s CIDER. It enables convenient + and dynamic REPL-driven development. ** Packages - [[doom-package:julia-mode]] - [[doom-package:julia-repl]] -- if [[doom-package:+lsp]] +- if [[doom-module:+lsp]] - if [[doom-module::tools lsp]] - [[doom-package:lsp-julia]] - [[doom-package:lsp]] - if [[doom-module::tools lsp +eglot]] - [[doom-package:eglot-jl]] - [[doom-package:eglot]] -- if [[doom-package:][+snail]] - - [[doom-package:][julia-snail]] +- if [[doom-module:+snail]] + - [[doom-package:julia-snail]] ** Hacks /No hacks documented for this module./ @@ -63,8 +64,8 @@ Pkg.add("LanguageServer") Pkg.add("SymbolServer") #+end_src -Then configure [[doom-package:lsp-julia]] or [[doom-package:eglot-jl]] depending on whether you have enabled -[[doom-module::tools lsp]] or [[doom-module::tools lsp +eglot]], respectively: +Then configure [[doom-package:lsp-julia]] or [[doom-package:eglot-jl]] depending on whether you have enabled [[doom-module::tools +lsp]] or [[doom-module::tools lsp +eglot]], respectively: *** =lsp-julia= To instruct [[doom-package:lsp-julia]] not to use the built-in package: diff --git a/modules/lang/julia/config.el b/modules/lang/julia/config.el index 657574431..df34a47ae 100644 --- a/modules/lang/julia/config.el +++ b/modules/lang/julia/config.el @@ -53,7 +53,8 @@ :hook (+julia-repl-start . +julia-override-repl-escape-char-h) :hook (+julia-repl-start . julia-repl-use-emacsclient) :config - (set-popup-rule! "^\\*julia.*\\*$" :ttl nil) + (unless (modulep! +snail) + (set-popup-rule! "^\\*julia.*\\*$" :ttl nil)) (when (modulep! :ui workspaces) (defadvice! +julia--namespace-repl-buffer-to-workspace-a (&optional executable-key suffix) diff --git a/modules/lang/julia/packages.el b/modules/lang/julia/packages.el index 5892896be..410dc62b9 100644 --- a/modules/lang/julia/packages.el +++ b/modules/lang/julia/packages.el @@ -1,13 +1,13 @@ ;; -*- no-byte-compile: t; -*- ;;; lang/julia/packages.el -(package! julia-mode :pin "7a8c868e0d3e51ba4a2c621ee22ca9599e0e4bbb") +(package! julia-mode :pin "2dfc869ff6b3878407fe7226669dfaae8d38d541") (package! julia-repl :pin "4947319bc948b3f80d61b0d65a719737275949b8") (when (modulep! +lsp) (if (modulep! :tools lsp +eglot) - (package! eglot-jl :pin "7dc604fe42a459a987853d065cd6d0f3c4cbc02a") + (package! eglot-jl :pin "1d9cab682380f37ca1e9e9933cda13164600706d") (package! lsp-julia :pin "c869b2f6c05a97e5495ed3cc6710a33b4faf41a2"))) (when (modulep! +snail) - (package! julia-snail :pin "d36653bb938050cfabbe3c1ea6d4575071085577")) + (package! julia-snail :pin "a25ce847480a0c2bed24fad3f1ee62904c9c93a5")) diff --git a/modules/lang/nix/config.el b/modules/lang/nix/config.el index 5e6677220..10bfb1731 100644 --- a/modules/lang/nix/config.el +++ b/modules/lang/nix/config.el @@ -11,8 +11,6 @@ :interpreter ("\\(?:cached-\\)?nix-shell" . +nix-shell-init-mode) :mode "\\.nix\\'" :init - ;; Treat flake.lock files as json. Fall back to js-mode because it's faster - ;; than js2-mode, and its extra features aren't needed there. (add-to-list 'auto-mode-alist (cons "/flake\\.lock\\'" (if (modulep! :lang json) diff --git a/modules/lang/org/autoload/org-babel.el b/modules/lang/org/autoload/org-babel.el index 544b0b0c1..de8ba79aa 100644 --- a/modules/lang/org/autoload/org-babel.el +++ b/modules/lang/org/autoload/org-babel.el @@ -23,8 +23,7 @@ (cond ((and (string-prefix-p "jupyter-" lang) (require 'jupyter nil t)) (jupyter-eval-region beg end)) - ((let ((major-mode (org-src-get-lang-mode lang))) - (+eval/region beg end)))))))) + ((+eval-region-as-major-mode beg end (org-src-get-lang-mode lang)))))))) ;;;###autoload diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index ffbfbb19b..bc2b720b8 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -1188,7 +1188,7 @@ between the two." :hook (org-mode . org-eldoc-load) :init (setq org-eldoc-breadcrumb-separator " → ") :config - ;; HACK Fix #2972: infinite recursion when eldoc kicks in in 'org' or 'python' + ;; HACK Fix #2972: infinite recursion when eldoc kicks in 'org' or 'python' ;; src blocks. ;; TODO Should be reported upstream! (puthash "org" #'ignore org-eldoc-local-functions-cache) diff --git a/modules/lang/org/contrib/dragndrop.el b/modules/lang/org/contrib/dragndrop.el index fb3dcae11..cd132cae0 100644 --- a/modules/lang/org/contrib/dragndrop.el +++ b/modules/lang/org/contrib/dragndrop.el @@ -54,35 +54,4 @@ (lambda (path) (if (file-in-directory-p path org-download-image-dir) (file-relative-name path org-download-image-dir) - path))) - - (defadvice! +org--fix-org-download-delete-a (fn beg end &optional times) - "Fix `org-download-delete' for a non-standard `org-download-link-format'." - :around #'org-download--delete - (save-excursion - (save-match-data - (goto-char beg) - (let ((times (or times most-positive-fixnum)) - (linkname - (or (and (string-match "\\[\\[\\(\\w+\\):" org-download-link-format) - (match-string 1 org-download-link-format)) - "file"))) - (while (and (>= (cl-decf times) 0) - (re-search-forward (format "\\[\\[%s:\\([^]]*\\)\\]\\]" - (regexp-quote linkname)) - end t)) - (let ((str (match-string-no-properties 2))) - (delete-region beg (match-end 0)) - (when (file-exists-p str) - (delete-file str)))))))) - - (defadvice! +org--dragndrop-then-display-inline-images-a (_link filename) - :after #'org-download-insert-link - (when (image-type-from-file-name filename) - (save-excursion - (org-display-inline-images - t t - (progn (org-back-to-heading-or-point-min t) (point)) - (progn (org-end-of-subtree t t) - (when (and (org-at-heading-p) (not (eobp))) (backward-char 1)) - (point))))))) + path)))) diff --git a/modules/lang/org/packages.el b/modules/lang/org/packages.el index ce2e1d785..f064bbb99 100644 --- a/modules/lang/org/packages.el +++ b/modules/lang/org/packages.el @@ -31,25 +31,25 @@ (format "(defun org-git-version (&rest _) \"%s-??-%s\")\n" version (cdr (doom-call-process "git" "rev-parse" "--short" "HEAD"))) "(provide 'org-version)\n"))))) - :pin "7a6bb0904d01b50680f9028f7c0f3cfc6ae3aa6e") + :pin "e9c288dfaccc2960e5b6889e6aabea700ad4e05a") (package! org-contrib :recipe (:host github :repo "emacsmirror/org-contrib") - :pin "8fbaceb247a775ad1534af97859c740e82cc955a") + :pin "d4056ce5d5611e1c971c151f182a2d407226fdb1") (package! avy) -(package! htmlize :pin "dd27bc3f26efd728f2b1f01f9e4ac4f61f2ffbf9") +(package! htmlize :pin "09d43dfa44899f194095bb3500a45ec5b34d59c6") (package! org-yt :recipe (:host github :repo "TobiasZawada/org-yt") :pin "56166f48e04d83668f70ed84706b7a4d8b1e5438") -(package! ox-clip :pin "ff117cf3c619eef12eccc0ccbfa3f11adb73ea68") +(package! ox-clip :pin "a549cc8e1747beb6b7e567ffac27e31ba45cb8e8") (package! toc-org :pin "6d3ae0fc47ce79b1ea06cabe21a3c596395409cd") (package! org-cliplink :pin "13e0940b65d22bec34e2de4bc8cba1412a7abfbc") ;; TODO Adjust when this is added to GNU ELPA (when (modulep! +contacts) (package! org-contacts - :pin "7f03eafaad2e5746949c0bebb98353e939c51ade" + :pin "6660db078f7687af3bc31f702e3e957d4d7654bd" :recipe (:host nil :type git :repo "https://repo.or.cz/org-contacts.git"))) @@ -71,7 +71,7 @@ (when (modulep! :tools pdf) (package! org-pdftools :pin "4e420233a153a9c4ab3d1a7e1d7d3211c836f0ac")) (when (modulep! :tools magit) - (package! orgit :pin "84bcb5c318f01b9ffc8d5aa18a7c393fe9c714b2") + (package! orgit :pin "a57beefa24712430fe6b5016b9273129931a8287") (when (modulep! :tools magit +forge) (package! orgit-forge :pin "f2ff9e5ad68b3e860379a1d368ad6d8a9696b719"))) (when (modulep! +brain) @@ -84,11 +84,11 @@ (when (modulep! +ipython) ; DEPRECATED (package! ob-ipython :pin "7147455230841744fb5b95dcbe03320313a77124")) (when (modulep! +jupyter) - (package! jupyter :pin "da306a6dbda6f1e285281765a311938a1d9db022")) + (package! jupyter :pin "2059d79b2fecf6d25a6c796b69ab954645ec37d1")) (when (modulep! +journal) - (package! org-journal :pin "605a7eb984a95fc6ec122df800632bf56ff59514")) + (package! org-journal :pin "17b34ce8df9649a73b715c13698220bde1628668")) (when (modulep! +noter) - (package! org-noter :pin "8be376384772c1f053cb2ce907ddf4d484b390dd")) + (package! org-noter :pin "9e4f57957b8f54db20a4e13bf8d6b32e004ab3e8")) (when (modulep! +pomodoro) (package! org-pomodoro :pin "3f5bcfb80d61556d35fc29e5ddb09750df962cc6")) (when (modulep! +pretty) @@ -100,11 +100,11 @@ :recipe (:host github :repo "anler/centered-window-mode") :pin "80965f6c6afe8d918481433984b493de72af5399") (package! org-tree-slide :pin "e2599a106a26ce5511095e23df4ea04be6687a8a") - (package! org-re-reveal :pin "7c39d15b841c7a8d197a24c89e5fef5d54e271aa") + (package! org-re-reveal :pin "1944ac53d4cdd0fb250cc575447d5e6320fd5f81") (package! revealjs :recipe (:host github :repo "hakimel/reveal.js" :files ("css" "dist" "js" "plugin")) - :pin "16f6633014672567de85aefd1f4639ffea0dde56")) + :pin "6410c756ea91ded3fa5f6b40a872523e7b8fe723")) (cond ((modulep! +roam) (package! org-roam @@ -162,6 +162,6 @@ (when (modulep! +hugo) (package! ox-hugo :recipe (:host github :repo "kaushalmodi/ox-hugo" :nonrecursive t) - :pin "cb1b6cfd7b080e889352150416c1725f11ba937a")) + :pin "c4156d9d383bf97853ba9e16271b7c4d5e697f49")) (when (modulep! :lang rst) (package! ox-rst :pin "99fa790da55b57a3f2e9aa187493ba434a64250e")) diff --git a/modules/lang/rust/config.el b/modules/lang/rust/config.el index 9ed0483e3..1418ff530 100644 --- a/modules/lang/rust/config.el +++ b/modules/lang/rust/config.el @@ -48,7 +48,36 @@ (if (modulep! :tools lsp +eglot) 'eglot 'lsp-mode)) - (add-hook 'rustic-mode-local-vars-hook #'rustic-setup-lsp 'append)) + (add-hook 'rustic-mode-local-vars-hook #'rustic-setup-lsp 'append) + + ;; HACK: Add @scturtle fix for signatures on hover on LSP mode. This code + ;; has not been upstreamed because it depends on the exact format of the + ;; response of Rust Analyzer, which is not stable enough for `lsp-mode' + ;; maintainers (see emacs-lsp/lsp-mode#1740). + (unless (modulep! :tools lsp +eglot) + (defadvice! +rust--dont-cache-results-from-ra-a (fn &rest args) + :after #'lsp-eldoc-function + (when (derived-mode-p 'rust-mode 'rust-ts-mode) + (setq lsp--hover-saved-bounds nil))) + + ;; extract and show short signature for rust-analyzer + (cl-defmethod lsp-clients-extract-signature-on-hover (contents (_server-id (eql rust-analyzer))) + (let* ((value (if lsp-use-plists (plist-get contents :value) (gethash "value" contents))) + (groups (--partition-by (s-blank? it) (s-lines (s-trim value)))) + (mod-group (cond ((s-equals? "```rust" (car (-fifth-item groups))) (-third-item groups)) + ((s-equals? "```rust" (car (-third-item groups))) (-first-item groups)) + (t nil))) + (cmt (if (null mod-group) "" (concat " // " (cadr mod-group)))) + (sig-group (cond ((s-equals? "```rust" (car (-fifth-item groups))) (-fifth-item groups)) + ((s-equals? "```rust" (car (-third-item groups))) (-third-item groups)) + (t (-first-item groups)))) + (sig (->> sig-group + (--drop-while (s-equals? "```rust" it)) + (--take-while (not (s-equals? "```" it))) + (--map (s-replace-regexp "//.*" "" it)) + (--map (s-trim it)) + (s-join " ")))) + (lsp--render-element (concat "```rust\n" sig cmt "\n```")))))) (when (modulep! +tree-sitter) (add-hook 'rustic-mode-local-vars-hook #'tree-sitter! 'append)) diff --git a/modules/lang/scala/packages.el b/modules/lang/scala/packages.el index ac9483e98..18dabf4e2 100644 --- a/modules/lang/scala/packages.el +++ b/modules/lang/scala/packages.el @@ -1,9 +1,9 @@ ;; -*- no-byte-compile: t; -*- ;;; lang/scala/packages.el -(package! sbt-mode :pin "9fe1e8807c22cc1dc56a6233e000969518907f4d") +(package! sbt-mode :pin "cc68728a6ef0600aad369157b3a2d0ce56afba9b") (package! scala-mode :pin "4c6d636b86e3bb1d95de819dc48dda92abdfbcf4") (when (and (modulep! +lsp) (not (modulep! :tools lsp +eglot))) - (package! lsp-metals :pin "da7e54ed65f4e153c94b9c54689908dce142ef37")) + (package! lsp-metals :pin "e55d544996f7321622e1eeafdc3dd128f8e72ce5")) diff --git a/modules/lang/web/+css.el b/modules/lang/web/+css.el index 144670d42..2211abc50 100644 --- a/modules/lang/web/+css.el +++ b/modules/lang/web/+css.el @@ -8,7 +8,8 @@ be aligned. If set to `nil', disable all the above behaviors.") -(add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.\\(\\(s[ac]\\|le\\)ss\\|styl\\)\\'" "\\1\\.css")) +(add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.\\(\\(s[ac]\\|le\\)ss\\|styl\\)\\'" "\\1\\.css\\'")) +(add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.css\\'" "\\1\\.\\(\\(s[ac]\\|le\\)ss\\|styl\\)\\'")) ;; diff --git a/modules/term/eshell/packages.el b/modules/term/eshell/packages.el index 21cf6e767..2c4adcd8e 100644 --- a/modules/term/eshell/packages.el +++ b/modules/term/eshell/packages.el @@ -1,13 +1,13 @@ ;; -*- no-byte-compile: t; -*- ;;; term/eshell/packages.el -(package! eshell-up :pin "ff84e6069b98f2ed00857a0f78bff19d96e4955c") +(package! eshell-up :pin "1999afaa509204b780db44e99ac9648fe7d92d32") (package! eshell-z :pin "337cb241e17bd472bd3677ff166a0800f684213c") (package! shrink-path :pin "c14882c8599aec79a6e8ef2d06454254bb3e1e41") (package! esh-help :pin "417673ed18a983930a66a6692dbfb288a995cb80") (package! eshell-did-you-mean :pin "80cd8c4b186a2fb29621cf634bcf2bcd914f1e3d") -(package! eshell-syntax-highlighting :pin "4ac27eec6595ba116a6151dfaf0b0e0440101e10") +(package! eshell-syntax-highlighting :pin "1d25386bf7d1a97e083d33750a98fbd1c6598138") (unless (featurep :system 'windows) - (package! fish-completion :pin "d34d0b96fde63feedf13c4288183d8d4d4d748cf") + (package! fish-completion :pin "006c613ff7f846b7d0a14422f2bdcc28b21205b8") (package! bash-completion :pin "f1daac0386c24cbe8a244a62c7588cc6847b07ae")) diff --git a/modules/tools/ansible/packages.el b/modules/tools/ansible/packages.el index a9f9837b7..b8f23f34e 100644 --- a/modules/tools/ansible/packages.el +++ b/modules/tools/ansible/packages.el @@ -1,10 +1,10 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/ansible/packages.el -(package! ansible :recipe (:nonrecursive t) :pin "d89ac0ee57742cca0f0e0a3453d9dcc521575690") +(package! ansible :recipe (:nonrecursive t) :pin "1d7de8d3ddac980715eebd87ee66859f8665b101") (package! ansible-doc :pin "86083a7bb2ed0468ca64e52076b06441a2f8e9e0") (package! jinja2-mode :pin "03e5430a7efe1d163a16beaf3c82c5fd2c2caee1") -(package! yaml-mode :pin "5b58248ab255dff6cfa4c4057a191bc4446ee5b6") +(package! yaml-mode :pin "7b5ce294fb15c2c8926fa476d7218aa415550a2a") (when (modulep! :completion company) - (package! company-ansible :pin "79dd421b161efa49fbdffad57fa40edb41f484a3")) + (package! company-ansible :pin "338922601cf9e8ada863fe6f2dd9d5145d9983b0")) diff --git a/modules/tools/biblio/packages.el b/modules/tools/biblio/packages.el index d53e8a994..110386f33 100644 --- a/modules/tools/biblio/packages.el +++ b/modules/tools/biblio/packages.el @@ -2,16 +2,16 @@ ;;; tools/biblio/packages.el (when (modulep! :completion ivy) - (package! bibtex-completion :pin "bf184cc311c9e1724f8b2eaf75b9e202c3aedd16") - (package! ivy-bibtex :pin "bf184cc311c9e1724f8b2eaf75b9e202c3aedd16")) + (package! bibtex-completion :pin "8b71b4f5ce62eeaf18067f57faaddc06449fbe1c") + (package! ivy-bibtex :pin "8b71b4f5ce62eeaf18067f57faaddc06449fbe1c")) (when (modulep! :completion helm) - (package! bibtex-completion :pin "bf184cc311c9e1724f8b2eaf75b9e202c3aedd16") - (package! helm-bibtex :pin "bf184cc311c9e1724f8b2eaf75b9e202c3aedd16")) + (package! bibtex-completion :pin "8b71b4f5ce62eeaf18067f57faaddc06449fbe1c") + (package! helm-bibtex :pin "8b71b4f5ce62eeaf18067f57faaddc06449fbe1c")) (when (modulep! :completion vertico) (package! citar :pin "885b86f6733fd70f42c32dd7791d3447f93db990") (package! citar-embark :pin "885b86f6733fd70f42c32dd7791d3447f93db990") (when (modulep! :lang org +roam2) - (package! citar-org-roam :pin "7d67dccf80065a88cb86ce9a8274383a9e8269c1"))) + (package! citar-org-roam :pin "82d47b5df1926627f56a09055c69b49b31cbbb9f"))) (package! parsebib :pin "ace9df707108b17759c004c7387655277122d4c1") -(package! citeproc :pin "c61c98b9d230ea28b2ca49498134803e1f8ea526") +(package! citeproc :pin "44f90cb296766e03fffc28b7892521ab0e8709f1") diff --git a/modules/tools/debugger/packages.el b/modules/tools/debugger/packages.el index bde6bede8..646b3cbc6 100644 --- a/modules/tools/debugger/packages.el +++ b/modules/tools/debugger/packages.el @@ -6,5 +6,5 @@ (package! realgud-trepan-ni :pin "0ec088ea343835e24ae73da09bea96bfb02a3130"))) (when (modulep! +lsp) - (package! dap-mode :pin "2f0c5b28578ce65ec746e4084ba72ba5c652ea79") + (package! dap-mode :pin "c95537c58e8f3ceac9c827ddf89e4928b24a1cc7") (package! posframe :pin "017deece88360c7297265680d78a0bb316470716")) diff --git a/modules/tools/direnv/packages.el b/modules/tools/direnv/packages.el index 4f474b5ee..5c0bbc572 100644 --- a/modules/tools/direnv/packages.el +++ b/modules/tools/direnv/packages.el @@ -1,4 +1,4 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/direnv/packages.el -(package! envrc :pin "1385e72a730924664697a0961d43516a47a977d7") +(package! envrc :pin "8eb7401700b0080902ce200ad610ff8d2f2dcc27") diff --git a/modules/tools/docker/README.org b/modules/tools/docker/README.org index 3af7085c8..bc42c463d 100644 --- a/modules/tools/docker/README.org +++ b/modules/tools/docker/README.org @@ -95,14 +95,8 @@ C-x C-f /docker:$USER@$CONTAINER:/path/to/file Thanks to [[https://github.com/magit/magit-popup][magit-popup]], all the popups default arguments can be customized. For example, here is how to customize the arguments for =docker-image-run-popup=: #+begin_src emacs-lisp -(setq docker-image-run-arguments '("-i" "-t" "--rm")) -#+end_src - -or inside a =use-package= declaration: -#+begin_src emacs-lisp -(use-package! docker - :bind ("C-c d" . docker) - :custom (docker-image-run-arguments '("-i" "-t" "--rm"))) +(after! docker + (setq docker-image-run-arguments '("-i" "-t" "--rm"))) #+end_src *** Other useful variables diff --git a/modules/tools/docker/packages.el b/modules/tools/docker/packages.el index 77f353589..ccb929619 100644 --- a/modules/tools/docker/packages.el +++ b/modules/tools/docker/packages.el @@ -5,4 +5,4 @@ ;; tramp-container (included with Emacs 29+) replaces docker-tramp (when (< emacs-major-version 29) (package! docker-tramp :pin "19d0771db4e6b89e19c00af5806438e315779c15")) -(package! dockerfile-mode :pin "52c6c00da1d31c0b6c29c74335b3af63ed6bf06c") +(package! dockerfile-mode :pin "39a012a27fcf6fb629c447d13b6974baf906714c") diff --git a/modules/tools/editorconfig/packages.el b/modules/tools/editorconfig/packages.el index db1f0ecf0..baf0a8ed1 100644 --- a/modules/tools/editorconfig/packages.el +++ b/modules/tools/editorconfig/packages.el @@ -3,4 +3,4 @@ (package! editorconfig :recipe (:nonrecursive t) - :pin "c3666c093f3a2a80fb42e513bf0a10d597497c18") + :pin "d73b6392ded0476af93ec7ba75cca2909aa8d2dc") diff --git a/modules/tools/eval/autoload/eval.el b/modules/tools/eval/autoload/eval.el index 78ded4c82..e4ad97864 100644 --- a/modules/tools/eval/autoload/eval.el +++ b/modules/tools/eval/autoload/eval.el @@ -72,6 +72,38 @@ output source-buffer) output) +;;;###autoload +(defun +eval-region-as-major-mode (beg end &optional runner-major-mode) + "Evaluate a region between BEG and END and display the output. + +Evaluate as in RUNNER-MAJOR-MODE. If RUNNER-MAJOR-MODE is nil, use major-mode +of the buffer instead." + (let ((load-file-name buffer-file-name) + (load-true-file-name + (or buffer-file-truename + (if buffer-file-name + (file-truename buffer-file-name)))) + (runner-major-mode (or runner-major-mode major-mode))) + (cond ((if (fboundp '+eval--ensure-in-repl-buffer) + (ignore-errors + (get-buffer-window (or (+eval--ensure-in-repl-buffer) + t)))) + (funcall (or (plist-get (cdr (alist-get runner-major-mode +eval-repls)) :send-region) + #'+eval/send-region-to-repl) + beg end)) + ((let (lang) + (if-let ((runner + (or (alist-get runner-major-mode +eval-runners) + (and (require 'quickrun nil t) + (equal (setq + lang (quickrun--command-key + (buffer-file-name (buffer-base-buffer)))) + "emacs") + (alist-get 'emacs-lisp-mode +eval-runners))))) + (funcall runner beg end) + (let ((quickrun-option-cmdkey lang)) + (quickrun-region beg end)))))))) + ;; ;;; Commands @@ -103,31 +135,7 @@ (defun +eval/region (beg end) "Evaluate a region between BEG and END and display the output." (interactive "r") - (let ((load-file-name buffer-file-name) - (load-true-file-name - (or buffer-file-truename - (if buffer-file-name - (file-truename buffer-file-name))))) - (cond ((and (fboundp '+eval--ensure-in-repl-buffer) - (ignore-errors - (get-buffer-window (or (+eval--ensure-in-repl-buffer) - t)))) - (funcall (or (plist-get (cdr (alist-get major-mode +eval-repls)) :send-region) - #'+eval/send-region-to-repl) - beg end)) - ((let ((runner - (or (alist-get major-mode +eval-runners) - (and (require 'quickrun nil t) - (equal (setq - lang (quickrun--command-key - (buffer-file-name (buffer-base-buffer)))) - "emacs") - (alist-get 'emacs-lisp-mode +eval-runners)))) - lang) - (if runner - (funcall runner beg end) - (let ((quickrun-option-cmdkey lang)) - (quickrun-region beg end)))))))) + (+eval-region-as-major-mode beg end)) ;;;###autoload (defun +eval/line-or-region () diff --git a/modules/tools/eval/autoload/repl.el b/modules/tools/eval/autoload/repl.el index c97ff82a2..4acafcb7f 100644 --- a/modules/tools/eval/autoload/repl.el +++ b/modules/tools/eval/autoload/repl.el @@ -50,7 +50,9 @@ (defun +eval-repl-known-repls () "Yield the available repl functions as a list of symbols." - (seq-uniq (mapcar (pcase-lambda (`(,mode ,fn . _)) (list mode fn)) +eval-repls))) + (cl-delete-duplicates + (mapcar (lambda! ((mode fn &rest _)) (list mode fn)) + +eval-repls))) (defun +doom-pretty-mode-name (mode) "Convert a mode name into a variant nicer for human eyes." @@ -82,15 +84,15 @@ human-readable variant of its associated major mode name." (defun +eval-repl-prompt () "Prompt the user for the choice of a repl to open." - (let* ((knowns (mapcar (pcase-lambda (`(,mode ,fn)) (list (+doom-pretty-mode-name mode) fn)) + (let* ((knowns (mapcar (lambda! ((mode fn)) (list (+doom-pretty-mode-name mode) fn)) (+eval-repl-known-repls))) (founds (mapcar (lambda (fn) (list (+eval-pretty-mode-name-from-fn fn) fn)) (+eval-repl-found-repls))) - (repls (seq-uniq (append knowns founds))) - (names (mapcar #'cl-first repls)) + (repls (cl-delete-duplicates (append knowns founds))) + (names (mapcar #'car repls)) (choice (or (completing-read "Open a REPL for: " names) (user-error "Aborting")))) - (cl-second (assoc choice repls)))) + (cadr (assoc choice repls)))) (defun +eval-repl-from-major-mode () "Fetch the repl associated with the current major mode, if there @@ -103,8 +105,7 @@ is one." prompted for a repl choice, even if the major mode they're in already has a known one." (pcase-let* ((`(,fn ,plist) (+eval-repl-from-major-mode)) - (fn (cond ((or prompt-p (not fn)) (+eval-repl-prompt)) - (t fn))) + (fn (if (or prompt-p (not fn)) (+eval-repl-prompt) fn)) (region (when (use-region-p) (buffer-substring-no-properties (region-beginning) (region-end))))) diff --git a/modules/tools/eval/packages.el b/modules/tools/eval/packages.el index 560920a2d..a7b5f6eb5 100644 --- a/modules/tools/eval/packages.el +++ b/modules/tools/eval/packages.el @@ -1,6 +1,6 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/eval/packages.el -(package! quickrun :pin "248149b0261051bd9eec8bdbc21c22d18d7b1b11") +(package! quickrun :pin "373634cf5143f9680164e27fa844d3b02408e917") (when (modulep! +overlay) (package! eros :pin "a9a92bdc6be0521a6a06eb464be55ed61946639c")) diff --git a/modules/tools/lookup/packages.el b/modules/tools/lookup/packages.el index d1abb858a..95dcdb6a6 100644 --- a/modules/tools/lookup/packages.el +++ b/modules/tools/lookup/packages.el @@ -26,7 +26,7 @@ (when (modulep! +dictionary) (if (featurep :system 'macos) - (package! osx-dictionary :pin "1f5a74f3e5d7f3c443f07433951512cd99e820a6") + (package! osx-dictionary :pin "6abfd6908b0dc773020466225c908000870b383b") (package! define-word :pin "31a8c67405afa99d0e25e7c86a4ee7ef84a808fe") ;; REVIEW: This fork fixes SavchenkoValeriy/emacs-powerthesaurus#40. (package! powerthesaurus diff --git a/modules/tools/lsp/+eglot.el b/modules/tools/lsp/+eglot.el index 8bf7ed20f..a020a00c1 100644 --- a/modules/tools/lsp/+eglot.el +++ b/modules/tools/lsp/+eglot.el @@ -4,7 +4,7 @@ :commands eglot eglot-ensure :hook (eglot-managed-mode . +lsp-optimization-mode) :init - (defadvice! +eglot--ensure-available-mode (fn) + (defadvice! +eglot--ensure-available-mode-a (fn) "Run `eglot-ensure' if the current mode has support." :around #'eglot-ensure (when (alist-get major-mode eglot-server-programs nil nil @@ -15,7 +15,6 @@ (funcall fn))) (setq eglot-sync-connect 1 eglot-autoshutdown t - eglot-send-changes-idle-time 0.5 ;; NOTE: We disable eglot-auto-display-help-buffer because :select t in ;; its popup rule causes eglot to steal focus too often. eglot-auto-display-help-buffer nil) @@ -44,8 +43,8 @@ (defadvice! +lsp--defer-server-shutdown-a (fn &optional server) "Defer server shutdown for a few seconds. This gives the user a chance to open other project files before the server is -auto-killed (which is a potentially expensive process). It also prevents the -server getting expensively restarted when reverting buffers." +auto-killed (which is a potentially expensive process). It also spares the +server an expensive restart when its buffer is reverted." :around #'eglot--managed-mode (letf! (defun eglot-shutdown (server) (if (or (null +lsp-defer-shutdown) diff --git a/modules/tools/lsp/packages.el b/modules/tools/lsp/packages.el index c8c0f44b0..c493ec335 100644 --- a/modules/tools/lsp/packages.el +++ b/modules/tools/lsp/packages.el @@ -3,14 +3,14 @@ (if (modulep! +eglot) (progn - (package! eglot :pin "24f2bf7b28c33e1d677b547956ade5560d27f55f") + (package! eglot :pin "678610fdc544f10ac757ab7acf88ac7c5815ed5a") (when (modulep! :completion vertico) - (package! consult-eglot :pin "049c6319b8a48ff66189d49592c7759f0b356596")) + (package! consult-eglot :pin "64262e72452f8fe6dd49d31bcdd4bd577b7d682d")) (when (and (modulep! :checkers syntax) (not (modulep! :checkers syntax +flymake))) (package! flycheck-eglot :pin "114e1315aaf0dc3196da67da426bbe2b46384fe2"))) - (package! lsp-mode :pin "a5f5ca9a8a4b2ceaf236457bf2524f94c183c2f2") - (package! lsp-ui :pin "bc58c6664577d1d79060c6b32b7ad20e70ee19d0") + (package! lsp-mode :pin "8861252880f6c2f6374a7bca2b945e6447eebd5a") + (package! lsp-ui :pin "942eeecc3d9a23ad006a3476885dfa7cbb5e207e") (when (modulep! :completion ivy) (package! lsp-ivy :pin "9ecf4dd9b1207109802bd1882aa621eb1c385106")) (when (modulep! :completion helm) diff --git a/modules/tools/magit/packages.el b/modules/tools/magit/packages.el index 7bebc3a57..2f046d9b7 100644 --- a/modules/tools/magit/packages.el +++ b/modules/tools/magit/packages.el @@ -1,12 +1,12 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/magit/packages.el -(when (package! magit :pin "0963697f24cfbe80f92312044bd9ab28b914b053") +(when (package! magit :pin "b5637d665c1e5bd5b76ffb072dbac387f37a5f63") (when (modulep! +forge) - (package! forge :pin "68771ca4d53c3aea5c860eeb888cee8e9cb5ca37") + (package! forge :pin "ad94b5665de357347bfc52910eef46a79f74988d") (package! code-review :recipe (:host github :repo "doomelpa/code-review" :files ("graphql" "code-review*.el")) :pin "e4c34fa284da25d8e0bafbae4300f1db5bdcda44")) - (package! magit-todos :pin "1e9acc0ba63fbc297001bf334d63cb4326be80df")) + (package! magit-todos :pin "332ce763f7336ea356964b92723678aa1ed4640f")) diff --git a/modules/tools/pdf/packages.el b/modules/tools/pdf/packages.el index 4bca3a0e1..b80c837a0 100644 --- a/modules/tools/pdf/packages.el +++ b/modules/tools/pdf/packages.el @@ -1,5 +1,5 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/pdf/packages.el -(package! pdf-tools :pin "c69e7656a4678fe25afbd29f3503dd19ee7f9896") -(package! saveplace-pdf-view :pin "abfb5e1f463cffc18218a0f7f2fa141a271b1813") +(package! pdf-tools :pin "a1048bceb2bd3f635437b0f2bfac27cae8c2dabc") +(package! saveplace-pdf-view :pin "ee95460cd934080338f03a16f95b549577425216") diff --git a/modules/tools/terraform/packages.el b/modules/tools/terraform/packages.el index 8409d4229..e598fd0c4 100644 --- a/modules/tools/terraform/packages.el +++ b/modules/tools/terraform/packages.el @@ -1,6 +1,6 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/terraform/packages.el -(package! terraform-mode :pin "e8b57df8c2a3d3171f3768f60eb84067f553289c") +(package! terraform-mode :pin "a645c32a8f0f0d04034262ae5fea330d5c7a33c6") (when (modulep! :completion company) (package! company-terraform :pin "8d5a16d1bbeeb18ca49a8fd57b5d8cd30c8b8dc7")) diff --git a/modules/tools/tree-sitter/packages.el b/modules/tools/tree-sitter/packages.el index db244eba5..71f92c463 100644 --- a/modules/tools/tree-sitter/packages.el +++ b/modules/tools/tree-sitter/packages.el @@ -2,9 +2,9 @@ ;;; tools/tree-sitter/packages.el (package! tree-sitter :pin "3cfab8a0e945db9b3df84437f27945746a43cc71") -(package! tree-sitter-langs :pin "20fbbb85735a9196ba3e7fb33f99b3a904b363ba") +(package! tree-sitter-langs :pin "b7895ca759563f3c7c3b928eb4f816bb4099d866") (package! tree-sitter-indent :pin "4ef246db3e4ff99f672fe5e4b416c890f885c09e") (when (modulep! :editor evil +everywhere) (package! evil-textobj-tree-sitter - :pin "220ceae065852ef4f717fa41efd1ab51ca2346d3")) + :pin "a19ab9d89a00f4a04420f9b5d61b66f04fea5261")) diff --git a/modules/ui/deft/packages.el b/modules/ui/deft/packages.el index ba3427f57..459447348 100644 --- a/modules/ui/deft/packages.el +++ b/modules/ui/deft/packages.el @@ -1,4 +1,4 @@ ;; -*- no-byte-compile: t; -*- ;;; ui/deft/packages.el -(package! deft :pin "28be94d89bff2e1c7edef7244d7c5ba0636b1296") +(package! deft :pin "bb1a16b87c3e0fe70fade6227e47dd7712b89bf6") diff --git a/modules/ui/doom/packages.el b/modules/ui/doom/packages.el index 15cc260ba..9e306c51e 100644 --- a/modules/ui/doom/packages.el +++ b/modules/ui/doom/packages.el @@ -1,5 +1,5 @@ ;; -*- no-byte-compile: t; -*- ;;; ui/doom/packages.el -(package! doom-themes :pin "ff26f26ea3d761375f5fc4070438fbd0f3473d33") -(package! solaire-mode :pin "8af65fbdc50b25ed3214da949b8a484527c7cc14") +(package! doom-themes :pin "3b2422b208d28e8734b300cd3cc6a7f4af5eba55") +(package! solaire-mode :pin "8ccdceeb9298b3c4e35f630914f467bf164f39ad") diff --git a/modules/ui/ligatures/config.el b/modules/ui/ligatures/config.el index 6312493ba..ad8baab5e 100644 --- a/modules/ui/ligatures/config.el +++ b/modules/ui/ligatures/config.el @@ -161,12 +161,13 @@ and cannot run in." (fboundp 'mac-auto-operator-composition-mode)) (add-hook 'doom-init-ui-hook #'mac-auto-operator-composition-mode 'append)) - ;; NOTE: the module does not support Emacs 27 and less, but if we still try to enable ligatures, - ;; it will end up in catastrophic work-loss errors, so we leave the check here for safety. + ;; This module does not support Emacs 27 and less, but if we still try to + ;; enable ligatures, it will end up in catastrophic work-loss errors, so we + ;; leave the check here for safety. ((and (> emacs-major-version 27) (or (featurep 'ns) - (string-match-p "HARFBUZZ" system-configuration-features)) - (featurep 'composite)) ; Emacs loads `composite' at startup + (featurep 'harfbuzz)) + (featurep 'composite)) ; Emacs loads `composite' at startup (use-package! ligature :config diff --git a/modules/ui/modeline/README.org b/modules/ui/modeline/README.org index 128babe4f..f472fa83e 100644 --- a/modules/ui/modeline/README.org +++ b/modules/ui/modeline/README.org @@ -96,7 +96,7 @@ Some possible solutions: (after! doom-modeline (doom-modeline-def-modeline 'main '(bar matches buffer-info remote-host buffer-position parrot selection-info) - '(misc-info minor-modes checker input-method buffer-encoding major-mode process vcs " "))) ; <-- added padding here + '(misc-info minor-modes check input-method buffer-encoding major-mode process vcs " "))) ; <-- added padding here #+end_src 2. Use another font for the mode line (or a different ~:height~) (source) diff --git a/modules/ui/modeline/packages.el b/modules/ui/modeline/packages.el index 8bdce9b70..1bc523b24 100644 --- a/modules/ui/modeline/packages.el +++ b/modules/ui/modeline/packages.el @@ -2,7 +2,7 @@ ;;; ui/modeline/packages.el (unless (modulep! +light) - (package! doom-modeline :pin "bf880ae56f3f6aab7bd334de9bd9b455c63a24c0")) + (package! doom-modeline :pin "e09b8e989fa5fc1d98320aaa29d7138631b20ae5")) (package! anzu :pin "26fb50b429ee968eb944b0615dd0aed1dd66172c") (when (modulep! :editor evil) (package! evil-anzu :pin "d1e98ee6976437164627542909a25c6946497899")) diff --git a/modules/ui/neotree/config.el b/modules/ui/neotree/config.el index 4f46167b9..37148773b 100644 --- a/modules/ui/neotree/config.el +++ b/modules/ui/neotree/config.el @@ -15,7 +15,7 @@ neo-mode-line-type 'none neo-window-width 30 neo-show-updir-line nil - neo-theme 'icons + neo-theme 'nerd neo-banner-message nil neo-confirm-create-file #'off-p neo-confirm-create-directory #'off-p diff --git a/modules/ui/popup/autoload/popup.el b/modules/ui/popup/autoload/popup.el index aa31fac2a..3a8a9e61e 100644 --- a/modules/ui/popup/autoload/popup.el +++ b/modules/ui/popup/autoload/popup.el @@ -106,7 +106,7 @@ the buffer is visible, then set another timer and try again later." (param (if (memq side '(left right)) 'window-width 'window-height))) - (setq list (assq-delete-all 'size alist)) + (setq alist (assq-delete-all 'size alist)) (setf (alist-get param alist) size)) (setf (alist-get 'window-parameters alist) parameters) diff --git a/modules/ui/tabs/config.el b/modules/ui/tabs/config.el index 66504fdef..f9b8af52d 100644 --- a/modules/ui/tabs/config.el +++ b/modules/ui/tabs/config.el @@ -1,5 +1,14 @@ ;;; ui/tabs/config.el -*- lexical-binding: t; -*- +(defcustom +tabs-buffer-update-groups-delay 0.1 + "Minimum wait time (in seconds) before tab groups are recalculated." + :type 'float + :group 'doom) + + +;; +;;; Packages + (use-package! centaur-tabs :hook (doom-first-file . centaur-tabs-mode) :init @@ -20,7 +29,20 @@ (defun +tabs-disable-centaur-tabs-mode-maybe-h () "Disable `centaur-tabs-mode' in current buffer." (when (centaur-tabs-mode-on-p) - (centaur-tabs-local-mode))))) + (centaur-tabs-local-mode)))) + + ;; HACK: `centaur-tabs-buffer-update-groups' is both expensive and called too + ;; frequently. There really is no reason to call it more than 10 times per + ;; second, as buffers rarely change groups more frequently than that. + (let ((time (float-time))) + (defadvice! +tabs--rate-limit-buffer-update-groups-a (fn) + :around #'centaur-tabs-buffer-update-groups + (let ((now (float-time))) + (if-let ((buf (and (< now (+ time +tabs-buffer-update-groups-delay)) + (assq (current-buffer) centaur-tabs--buffers)))) + (car (nth 2 buf)) + (setq time now) + (funcall fn)))))) ;; TODO tab-bar-mode (emacs 27) diff --git a/modules/ui/treemacs/config.el b/modules/ui/treemacs/config.el index d232ec1b0..62e3e6ddb 100644 --- a/modules/ui/treemacs/config.el +++ b/modules/ui/treemacs/config.el @@ -26,7 +26,7 @@ This must be set before `treemacs' has loaded.") treemacs-persist-file (concat doom-cache-dir "treemacs-persist") treemacs-last-error-persist-file (concat doom-cache-dir "treemacs-last-error-persist")) :config - ;; Don't follow the cursor + ;; Don't follow the cursor (it's more disruptive/jarring than helpful as a default) (treemacs-follow-mode -1) (set-popup-rule! "^ ?\\*Treemacs" :ignore t) diff --git a/modules/ui/treemacs/packages.el b/modules/ui/treemacs/packages.el index 59c5fbdea..123adc09c 100644 --- a/modules/ui/treemacs/packages.el +++ b/modules/ui/treemacs/packages.el @@ -1,7 +1,7 @@ ;; -*- no-byte-compile: t; -*- ;;; ui/treemacs/packages.el -(package! treemacs :pin "df26b6ab9a0f467e5ff99f7ed97551ccf756e06c") +(package! treemacs :pin "8c6df39f01a4d47fda2cc943645fa067f771b748") (package! treemacs-nerd-icons :pin "9876cb478145a0ec4e36f64ff6583f3de7126216") ;; These packages have no :pin because they're in the same repo (when (modulep! :editor evil +everywhere) diff --git a/modules/ui/vc-gutter/packages.el b/modules/ui/vc-gutter/packages.el index 2651562a6..3ed651912 100644 --- a/modules/ui/vc-gutter/packages.el +++ b/modules/ui/vc-gutter/packages.el @@ -2,5 +2,5 @@ ;;; ui/vc-gutter/packages.el (if (modulep! +diff-hl) - (package! diff-hl :pin "b8b2727a72fdf64ac98e6cfa136a43cb0cacf72f") + (package! diff-hl :pin "96620839430c1205cbb8c92dd54973397f70f9d2") (package! git-gutter-fringe :pin "648cb5b57faec55711803cdc9434e55a733c3eba")) diff --git a/modules/ui/workspaces/autoload/ivy.el b/modules/ui/workspaces/autoload/ivy.el deleted file mode 100644 index 97b84baf4..000000000 --- a/modules/ui/workspaces/autoload/ivy.el +++ /dev/null @@ -1,17 +0,0 @@ -;;; ui/workspaces/autoload/ivy.el -*- lexical-binding: t; -*- -;;;###if (modulep! :completion ivy) - -;;;###autoload -(defun +workspace--ivy-rich-preview (workspace) - (if-let (buffers (when-let (workspace (gethash workspace *persp-hash*)) - (cl-loop for (type . rest) in (persp-window-conf workspace) - if (eq type 'buffer) - collect (car leaf) - else if (eq type 'leaf) - append (cl-loop for (type . leaf) in rest - if (eq type 'buffer) - collect (car leaf))))) - (string-join buffers " ") - "*No buffers*")) - -;;; ivy.el ends here diff --git a/modules/ui/workspaces/autoload/workspaces.el b/modules/ui/workspaces/autoload/workspaces.el index 840ca1d5c..4cca0c7a8 100644 --- a/modules/ui/workspaces/autoload/workspaces.el +++ b/modules/ui/workspaces/autoload/workspaces.el @@ -318,12 +318,7 @@ workspace, otherwise the new workspace is blank." end of the workspace list." (interactive (list (or current-prefix-arg - (if (modulep! :completion ivy) - (ivy-read "Switch to workspace: " - (+workspace-list-names) - :caller #'+workspace/switch-to - :preselect (+workspace-current-name)) - (completing-read "Switch to workspace: " (+workspace-list-names)))))) + (completing-read "Switch to workspace: " (+workspace-list-names))))) (when (and (stringp index) (string-match-p "^[0-9]+$" index)) (setq index (string-to-number index))) diff --git a/modules/ui/workspaces/config.el b/modules/ui/workspaces/config.el index 68c5d9221..540c76977 100644 --- a/modules/ui/workspaces/config.el +++ b/modules/ui/workspaces/config.el @@ -84,9 +84,10 @@ stored in `persp-save-dir'.") ;; HACK Fix #319: the warnings buffer gets swallowed when creating ;; `+workspaces-main', so display it ourselves, if it exists. (when-let (warnings (get-buffer "*Warnings*")) - (save-excursion - (display-buffer-in-side-window - warnings '((window-height . shrink-window-if-larger-than-buffer)))))))) + (unless (get-buffer-window warnings) + (save-excursion + (display-buffer-in-side-window + warnings '((window-height . shrink-window-if-larger-than-buffer))))))))) (defun +workspaces-init-persp-mode-h () (cond (persp-mode ;; `uniquify' breaks persp-mode. It renames old buffers, which causes @@ -206,13 +207,6 @@ stored in `persp-save-dir'.") ("xt" counsel-projectile-switch-project-action-run-term "invoke term from project root") ("X" counsel-projectile-switch-project-action-org-capture "org-capture into project"))) - (when (modulep! :completion ivy) - (after! ivy-rich - (cl-callf plist-put ivy-rich-display-transformers-list - '+workspace/switch-to - '(:columns ((ivy-rich-candidate (:width 50)) - (+workspace--ivy-rich-preview)))))) - (when (modulep! :completion helm) (after! helm-projectile (setcar helm-source-projectile-projects-actions