;; -*- lexical-binding: t; -*- ;; Nicer minibuffer completion ;; First Selectrum, which provides the core incremental minibuffer completion engine (use-package selectrum :config (selectrum-mode 1) (leader-def-key "z" #'selectrum-repeat)) ;; Then prescient, which adds the ability to sort and filter completions (use-package selectrum-prescient :after selectrum :config (selectrum-prescient-mode 1) (prescient-persist-mode 1)) ;; Marginalia adds annotations to completion candidates (use-package marginalia :demand t :config (marginalia-mode 1) ;; When using Selectrum, ensure that Selectrum is refreshed when cycling annotations. (advice-add #'marginalia-cycle :after (lambda () (when (bound-and-true-p selectrum-mode) (selectrum-exhibit)))) (add-to-list 'marginalia-prompt-categories '("Find file:" . project-file)) (add-to-list 'marginalia-prompt-categories '("Find dir:" . project-file)) (add-to-list 'marginalia-prompt-categories '("Switch to project" . file)) (add-to-list 'marginalia-prompt-categories '("recipe\\|package" . straight)) (add-to-list 'marginalia-prompt-categories '("Password entry" . password-store)) :general (minibuffer-local-map "M-A" #'marginalia-cycle) :custom (marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))) ;; Embark adds context actions to completion candidates (and other things!) (use-package embark :config (defun embark-which-key-indicator () "An embark indicator that displays keymaps using which-key. The which-key help message will show the type and value of the current target followed by an ellipsis if there are further targets." (lambda (&optional keymap targets prefix) (if (null keymap) (which-key--hide-popup-ignore-command) (which-key--show-keymap (if (eq (caar targets) 'embark-become) "Become" (format "Act on %s '%s'%s" (plist-get (car targets) :type) (embark--truncate-target (plist-get (car targets) :target)) (if (cdr targets) "…" ""))) (if prefix (pcase (lookup-key keymap prefix 'accept-default) ((and (pred keymapp) km) km) (_ (key-binding prefix 'accept-default))) keymap) nil nil t)))) (embark-define-keymap embark-straight-map "Keymap for actions for straight.el" ("u" straight-visit-package-website) ("r" straight-get-recipe) ("i" straight-use-package) ("c" straight-check-package) ("F" straight-pull-package) ("f" straight-fetch-package) ("p" straight-push-package) ("n" straight-normalize-package) ("m" straight-merge-package)) (add-to-list 'embark-keymap-alist '(straight . embark-straight-map)) (embark-define-keymap embark-password-store-actions "Keymap for actions for password-store." ("c" password-store-copy) ("f" password-store-copy-field) ("i" password-store-insert) ("I" password-store-generate) ("r" password-store-rename) ("e" password-store-edit) ("k" password-store-remove) ("U" password-store-url)) (add-to-list 'embark-keymap-alist '(password-store . embark-password-store-actions)) ;; Add identifiers in LSP-mode as their own target type (with-eval-after-load 'lsp-mode (defun embark-target-lsp-identifier-at-point () (when lsp-mode (when-let ((sym (embark-target-identifier-at-point))) (cons 'lsp-identifier (cdr sym))))) (add-to-list 'embark-target-finders 'embark-target-lsp-identifier-at-point) (embark-define-keymap embark-lsp-identifier-actions "Keymap for actions on LSP identifiers." :parent embark-identifier-map ("a" lsp-execute-code-action) ("s" lsp-describe-thing-at-point)) (add-to-list 'embark-keymap-alist '(lsp-identifier . embark-lsp-identifier-actions)) (add-to-list 'embark-target-injection-hooks '(lsp-execute-code-action embark--ignore-target)) (add-to-list 'embark-target-injection-hooks '(lsp-describe-thing-at-point embark--ignore-target))) :general ((emacs normal motion insert) "C-." #'embark-act) ((emacs normal motion insert) "M-." #'embark-dwim) ("C-." #'embark-act) ("M-." #'embark-dwim) (embark-file-map "s" #'sudo-edit-find-file "l" #'vlf "g" #'magit-file-dispatch) ('normal embark-collect-mode-map "TAB" #'forward-button "?" #'describe-mode "A" #'embark-collect-direct-action-minor-mode "S" #'tabulated-list-sort "a" #'embark-act "b" #'backward-button "e" #'embark-export "f" #'forward-button "gr" #'revert-buffer "n" #'next-line "p" #'previous-line "q" #'quit-window "s" #'isearch-forward "v" #'embark-collect-toggle-view "z" #'embark-collect-zebra-minor-mode "{" #'tabulated-list-narrow-current-column "}" #'tabulated-list-widen-current-column "" #'backward-button) :custom (embark-prompter 'embark-keymap-prompter) (embark-indicators '(embark-which-key-indicator embark-highlight-indicator embark-isearch-highlight-indicator))) ;; Consult adds a bunch of completing-read based utilities (use-package consult :after selectrum :commands (consult-xref) :init (setq xref-show-xrefs-function #'consult-xref xref-show-definitions-function #'consult-xref) :custom (consult-project-root-function #'projectile-project-root) (consult-find-args "find . -not ( -wholename */.git/* -prune )") (consult-config '((consult-ripgrep :preview-key nil) (consult-grep :preview-key nil))) :general ([remap switch-to-buffer] #'consult-buffer) ([remap imenu] #'consult-imenu) ([remap projectile-ripgrep] #'consult-ripgrep) ([remap projectile-grep] #'consult-grep) ("C-c p" #'consult-yank-from-kill-ring)) (use-package consult-flycheck :after flycheck :general (flycheck-command-map "!" #'consult-flycheck)) (use-package embark-consult :defer 1) ;; Make grep-like embark collect buffers editable (use-package wgrep :general (grep-mode-map "C-x C-q" #'wgrep-change-to-wgrep-mode)) (provide 'init-completion)