doomemacs/modules/completion/vertico/config.el
Henrik Lissner ad6a3d0f33
refactor: deprecate featurep! for modulep!
featurep! will be renamed modulep! in the future, so it's been
deprecated. They have identical interfaces, and can be replaced without
issue.

featurep! was never quite the right name for this macro. It implied that
it had some connection to featurep, which it doesn't (only that it was
similar in purpose; still, Doom modules are not features). To undo such
implications and be consistent with its namespace (and since we're
heading into a storm of breaking changes with the v3 release anyway),
now was the best opportunity to begin the transition.
2022-08-14 20:43:35 +02:00

310 lines
13 KiB
EmacsLisp

;;; completion/vertico/config.el -*- lexical-binding: t; -*-
(defvar +vertico-company-completion-styles '(basic partial-completion orderless)
"Completion styles for company to use.
The completion/vertico module uses the orderless completion style by default,
but this returns too broad a candidate set for company completion. This variable
overrides `completion-styles' during company completion sessions.")
(defvar +vertico-consult-fd-args nil
"Shell command and arguments the vertico module uses for fd.")
;;
;;; Packages
(use-package! vertico
:hook (doom-first-input . vertico-mode)
:init
(defadvice! +vertico-crm-indicator-a (args)
:filter-args #'completing-read-multiple
(cons (format "[CRM%s] %s"
(replace-regexp-in-string
"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
crm-separator)
(car args))
(cdr args)))
:config
(setq vertico-resize nil
vertico-count 17
vertico-cycle t)
(setq-default completion-in-region-function
(lambda (&rest args)
(apply (if vertico-mode
#'consult-completion-in-region
#'completion--in-region)
args)))
;; Cleans up path when moving directories with shadowed paths syntax, e.g.
;; cleans ~/foo/bar/// to /, and ~/foo/bar/~/ to ~/.
(add-hook 'rfn-eshadow-update-overlay-hook #'vertico-directory-tidy)
(add-hook 'minibuffer-setup-hook #'vertico-repeat-save)
(map! :map vertico-map "DEL" #'vertico-directory-delete-char)
;; These commands are problematic and automatically show the *Completions* buffer
(advice-add #'tmm-add-prompt :after #'minibuffer-hide-completions)
(defadvice! +vertico--suppress-completion-help-a (fn &rest args)
:around #'ffap-menu-ask
(letf! ((#'minibuffer-completion-help #'ignore))
(apply fn args))))
(use-package! orderless
:after-call doom-first-input-hook
:config
(defadvice! +vertico--company-capf--candidates-a (fn &rest args)
"Highlight company matches correctly, and try default completion styles before
orderless."
:around #'company-capf--candidates
(let ((orderless-match-faces [completions-common-part])
(completion-styles +vertico-company-completion-styles))
(apply fn args)))
(defun +vertico-orderless-dispatch (pattern _index _total)
(cond
;; Ensure $ works with Consult commands, which add disambiguation suffixes
((string-suffix-p "$" pattern)
`(orderless-regexp . ,(concat (substring pattern 0 -1) "[\x200000-\x300000]*$")))
;; Ignore single !
((string= "!" pattern) `(orderless-literal . ""))
;; Without literal
((string-prefix-p "!" pattern) `(orderless-without-literal . ,(substring pattern 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)))
;; Initialism matching
((string-prefix-p "`" pattern) `(orderless-initialism . ,(substring pattern 1)))
((string-suffix-p "`" pattern) `(orderless-initialism . ,(substring pattern 0 -1)))
;; Literal matching
((string-prefix-p "=" pattern) `(orderless-literal . ,(substring pattern 1)))
((string-suffix-p "=" pattern) `(orderless-literal . ,(substring pattern 0 -1)))
;; Flex matching
((string-prefix-p "~" pattern) `(orderless-flex . ,(substring pattern 1)))
((string-suffix-p "~" pattern) `(orderless-flex . ,(substring pattern 0 -1)))))
(add-to-list
'completion-styles-alist
'(+vertico-basic-remote
+vertico-basic-remote-try-completion
+vertico-basic-remote-all-completions
"Use basic completion on remote files only"))
(setq completion-styles '(orderless basic)
completion-category-defaults nil
;; note that despite override in the name orderless can still be used in
;; find-file etc.
completion-category-overrides '((file (styles +vertico-basic-remote orderless partial-completion)))
orderless-style-dispatchers '(+vertico-orderless-dispatch)
orderless-component-separator "[ &]")
;; ...otherwise find-file gets different highlighting than other commands
(set-face-attribute 'completions-first-difference nil :inherit nil))
(use-package! consult
:defer t
:preface
(define-key!
[remap apropos] #'consult-apropos
[remap bookmark-jump] #'consult-bookmark
[remap evil-show-marks] #'consult-mark
[remap evil-show-jumps] #'+vertico/jump-list
[remap evil-show-registers] #'consult-register
[remap goto-line] #'consult-goto-line
[remap imenu] #'consult-imenu
[remap locate] #'consult-locate
[remap load-theme] #'consult-theme
[remap man] #'consult-man
[remap recentf-open-files] #'consult-recent-file
[remap switch-to-buffer] #'consult-buffer
[remap switch-to-buffer-other-window] #'consult-buffer-other-window
[remap switch-to-buffer-other-frame] #'consult-buffer-other-frame
[remap yank-pop] #'consult-yank-pop
[remap persp-switch-to-buffer] #'+vertico/switch-workspace-buffer)
(advice-add #'multi-occur :override #'consult-multi-occur)
:config
(defadvice! +vertico--consult-recent-file-a (&rest _args)
"`consult-recent-file' needs to have `recentf-mode' on to work correctly"
:before #'consult-recent-file
(recentf-mode +1))
(setq consult-project-root-function #'doom-project-root
consult-narrow-key "<"
consult-line-numbers-widen t
consult-async-min-input 2
consult-async-refresh-delay 0.15
consult-async-input-throttle 0.2
consult-async-input-debounce 0.1)
(unless +vertico-consult-fd-args
(setq +vertico-consult-fd-args
(if doom-projectile-fd-binary
(format "%s --color=never -i -H -E .git --regex %s"
doom-projectile-fd-binary
(if IS-WINDOWS "--path-separator=/" ""))
consult-find-args)))
(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 (kbd "C-SPC"))
(consult-customize
consult-theme
:preview-key (list (kbd "C-SPC") :debounce 0.5 'any))
(when (modulep! :lang org)
(defvar +vertico--consult-org-source
(list :name "Org Buffer"
:category 'buffer
:narrow ?o
:hidden t
:face 'consult-buffer
:history 'buffer-name-history
:state #'consult--buffer-state
:new
(lambda (name)
(with-current-buffer (get-buffer-create name)
(insert "#+title: " name "\n\n")
(org-mode)
(consult--buffer-action (current-buffer))))
:items
(lambda ()
(mapcar #'buffer-name
(if (featurep 'org)
(org-buffer-list)
(seq-filter
(lambda (x)
(eq (buffer-local-value 'major-mode x) 'org-mode))
(buffer-list)))))))
(add-to-list 'consult-buffer-sources '+vertico--consult-org-source 'append)))
(use-package! consult-dir
:bind (([remap list-directory] . consult-dir)
:map vertico-map
("C-x C-d" . consult-dir)
("C-x C-j" . consult-dir-jump-file))
:config
(when (modulep! :tools docker)
(defun +vertico--consult-dir-docker-hosts ()
"Get a list of hosts from docker."
(when (require 'docker-tramp nil t)
(let ((hosts)
(docker-tramp-use-names t))
(dolist (cand (docker-tramp--parse-running-containers))
(let ((user (unless (string-empty-p (car cand))
(concat (car cand) "@")))
(host (car (cdr cand))))
(push (concat "/docker:" user host ":/") hosts)))
hosts)))
(defvar +vertico--consult-dir-source-tramp-docker
`(:name "Docker"
:narrow ?d
:category file
:face consult-file
:history file-name-history
:items ,#'+vertico--consult-dir-docker-hosts)
"Docker candiadate source for `consult-dir'.")
(add-to-list 'consult-dir-sources '+vertico--consult-dir-source-tramp-docker t))
(add-to-list 'consult-dir-sources 'consult-dir--source-tramp-ssh t)
(add-to-list 'consult-dir-sources 'consult-dir--source-tramp-local t))
(use-package! consult-flycheck
:when (modulep! :checkers syntax)
:after (consult flycheck))
(use-package! embark
:defer t
:init
(setq which-key-use-C-h-commands nil
prefix-help-command #'embark-prefix-help-command)
(map! [remap describe-bindings] #'embark-bindings
"C-;" #'embark-act ; to be moved to :config default if accepted
(:map minibuffer-local-map
"C-;" #'embark-act
"C-c C-;" #'embark-export
"C-c C-l" #'embark-collect
:desc "Export to writable buffer" "C-c C-e" #'+vertico/embark-export-write)
(:leader
:desc "Actions" "a" #'embark-act)) ; to be moved to :config default if accepted
:config
(require 'consult)
(set-popup-rule! "^\\*Embark Export:" :size 0.35 :ttl 0 :quit nil)
(defadvice! +vertico--embark-which-key-prompt-a (fn &rest args)
"Hide the which-key indicator immediately when using the completing-read prompter."
:around #'embark-completing-read-prompter
(which-key--hide-popup-ignore-command)
(let ((embark-indicators
(remq #'embark-which-key-indicator embark-indicators)))
(apply fn args)))
(cl-nsubstitute #'+vertico-embark-which-key-indicator #'embark-mixed-indicator embark-indicators)
;; add the package! target finder before the file target finder,
;; so we don't get a false positive match.
(let ((pos (or (cl-position
'embark-target-file-at-point
embark-target-finders)
(length embark-target-finders))))
(cl-callf2
cons
'+vertico-embark-target-package-fn
(nthcdr pos embark-target-finders)))
(embark-define-keymap +vertico/embark-doom-package-map
"Keymap for Embark package actions for packages installed by Doom."
("h" doom/help-packages)
("b" doom/bump-package)
("c" doom/help-package-config)
("u" doom/help-package-homepage))
(setf (alist-get 'package embark-keymap-alist) #'+vertico/embark-doom-package-map)
(map! (:map embark-file-map
:desc "Open target with sudo" "s" #'doom/sudo-find-file
(:when (modulep! :tools magit)
:desc "Open magit-status of target" "g" #'+vertico/embark-magit-status)
(:when (modulep! :ui workspaces)
:desc "Open in new workspace" "TAB" #'+vertico/embark-open-in-new-workspace))))
(use-package! marginalia
:hook (doom-first-input . marginalia-mode)
:init
(map! :map minibuffer-local-map
:desc "Cycle marginalia views" "M-A" #'marginalia-cycle)
:config
(when (modulep! +icons)
(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup))
(advice-add #'marginalia--project-root :override #'doom-project-root)
(pushnew! marginalia-command-categories
'(+default/find-file-under-here . file)
'(doom/find-file-in-emacsd . project-file)
'(doom/find-file-in-other-project . project-file)
'(doom/find-file-in-private-config . file)
'(doom/describe-active-minor-mode . minor-mode)
'(flycheck-error-list-set-filter . builtin)
'(persp-switch-to-buffer . buffer)
'(projectile-find-file . project-file)
'(projectile-recentf . project-file)
'(projectile-switch-to-buffer . buffer)
'(projectile-switch-project . project-file)))
(use-package! embark-consult
:after (embark consult)
:config
(add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode))
(use-package! wgrep
:commands wgrep-change-to-wgrep-mode
:config (setq wgrep-auto-save-buffer t))
(use-package! vertico-posframe
:when (modulep! +childframe)
:hook (vertico-mode . vertico-posframe-mode)
:config
(add-hook 'doom-after-reload-hook #'posframe-delete-all))