Files
sydnix/modules/home/users/msyds/emacs/lisp/syd/completion.el

165 lines
5.9 KiB
EmacsLisp
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;;; -*- lexical-binding: t; -*-
(require 'syd/base)
;;; Hide commands in M-x which do not work in the current mode
(setq read-extended-command-predicate
#'command-completion-default-include-p)
;;; Consult
;;;###autoload
(defun syd-enable-recentf-mode-a ()
"Used as :before advice for `consult-recent-file' to ensure recentf mode is
enabled."
;; REVIEW: Shall we take any extra precautions to only enable `recentf-mode'
;; if it was going to be enabled anyway?
(recentf-mode 1))
;; Consult adds various search and navigation tools using Emacs' completing-read
;; function; i.e., in our case, Vertico.
(use-package consult
:defer t
:config
(advice-add #'consult-recent-file
:before #'syd-enable-recentf-mode-a))
(use-package embark-consult
:after (embark consult))
;;; Vertico
;;;###autoload
(defun syd-vertico-embark-preview ()
"Previews candidate in vertico buffer, unless it's a consult command"
(interactive)
(unless (bound-and-true-p consult--preview-function)
(if (fboundp 'embark-dwim)
(save-selected-window
(let (embark-quit-after-action)
(embark-dwim)))
(user-error "Embark not installed, aborting..."))))
;; Vertico is a simple completion engine that replaces Emacs' built-in
;; completion engine, achieving Just Works™ compatibility. This is in contrast
;; to e.g. Helm and Ivy, which spawn ecosystems orthogonal to Emacs, and
;; diametrically-opposed to each other.
(use-package vertico
:hook (on-first-input . vertico-mode)
:general
(:keymaps 'vertico-map
"DEL" #'vertico-directory-delete-char
"C-SPC" #'syd-vertico-embark-preview
"C-j" #'vertico-next
"C-k" #'vertico-previous
"C-M-j" #'vertico-next-group
"C-M-k" #'vertico-previous-group)
(:keymaps 'vertico-map
:states 'normal
"j" #'vertico-next
"k" #'vertico-previous
"RET" #'vertico-exit)
:custom ((vertico-resize nil)
(vertico-count 17)
(vertico-cycle t))
:config
(setq-default completion-in-region-function #'consult-completion-in-region)
;; 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))
(defun syd-vertico-orderless-dispatch (pattern _index _total)
"Like `orderless-affix-dispatch', but allows affixes to be escaped.
Shamelessly stolen from Doom. }:3"
(let ((len (length pattern))
(alist orderless-affix-dispatch-alist))
(when (> len 0)
(cond
;; Ignore single dispatcher character
((and (= len 1) (alist-get (aref pattern 0) alist)) #'ignore)
;; Prefix
((when-let ((style (alist-get (aref pattern 0) alist))
((not (char-equal (aref pattern (max (1- len) 1)) ?\\))))
(cons style (substring pattern 1))))
;; Suffix
((when-let ((style (alist-get (aref pattern (1- len)) alist))
((not (char-equal (aref pattern (max 0 (- len 2))) ?\\))))
(cons style (substring pattern 0 -1))))))))
;;; Orderless
;; Orderless provides a completion style that divides the pattern into
;; space-separated components, and matches candidates that match all of the
;; components in any order. Each component can match in any one of several
;; ways: literally, as a regexp, as an initialism, in the flex style, or as
;; multiple word prefixes. By default, regexp and literal matches are enabled.
(use-package orderless
:after vertico
:custom ((completion-styles '(orderless basic))
(completion-category-overrides
'((file
(styles ;basic-remote
orderless partial-completion))))
(orderless-style-dispatchers '(syd-vertico-orderless-dispatch))
;; TODO: See Doom's `+vertico-orderless-dispatch'.
(orderless-affix-dispatch-alist
'((?! . orderless-without-literal)
(?& . orderless-annotation)
;; %1 -> {1, ₁, ꘡, ⒈, ...}
(?% . char-fold-to-regexp)
;; ,wcb -> {with-current-buffer, widget-convert-button, ...}
(?, . orderless-initialism)
(?= . orderless-literal)
(?^ . orderless-literal-prefix)
(?~ . orderless-flex)))))
;;;###autoload
(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 (plist-get (car targets) :type) '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 (lambda (binding)
(not (string-suffix-p "-argument" (cdr binding))))))))
;; TODO: Mark the Embark export buffer as a popup.
(use-package embark
:after vertico
:defer t
:custom ((which-key-use-C-h-commands nil)
(prefix-help-command #'embark-prefix-help-command)
;; Embark uses their own custom interface that is essentially
;; equivalent to which-key; just use which-key. }:)
(embark-indicators '(embark-which-key-indicator)))
:general
(:keymaps 'minibuffer-local-map
"C-;" `("Actions" . ,#'embark-act))
(:keymaps 'syd-leader-map
"a" `("Actions" . ,#'embark-act)))
(provide 'syd/completion)