From 5fd6e101afb7db75c698fe7439c490bcf63ca01c Mon Sep 17 00:00:00 2001 From: Madeleine Sydney Date: Mon, 13 Jan 2025 11:39:51 -0700 Subject: [PATCH] feat: More completion things - Further configure Orderless - Configure Orderless dispatch stuff - Further configure Vertico - Add & configure Embark - Integrate w/ which-key - Move General into its own feature (syd-general), for easy import by other modules. --- .../programs/emacs/modules/syd-completion.el | 90 +++++++++++++++++-- .../programs/emacs/modules/syd-general.el | 8 ++ .../programs/emacs/modules/syd-keybinds.el | 5 +- 3 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 users/crumb/programs/emacs/modules/syd-general.el diff --git a/users/crumb/programs/emacs/modules/syd-completion.el b/users/crumb/programs/emacs/modules/syd-completion.el index 87d4b64..aa08be1 100644 --- a/users/crumb/programs/emacs/modules/syd-completion.el +++ b/users/crumb/programs/emacs/modules/syd-completion.el @@ -1,5 +1,7 @@ ;;; syd-completion.el -*- lexical-binding: t; -*- +(require 'syd-general) + (use-package emacs :custom ;; Allow the opening of new minibuffers from inside existing minibuffers. @@ -23,27 +25,101 @@ (use-package vertico :hook (on-first-input . vertico-mode) :general (:keymaps 'vertico-map - "DEL" #'vertico-directory-delete-char - "C-SPC" #'+vertico/embark-preview - "C-j" #'vertico-next - "C-k" #'vertico-previous - "C-M-j" #'vertico-next-group - "C-M-k" #'vertico-previous-group) + "DEL" #'vertico-directory-delete-char + "C-SPC" #'+vertico/embark-preview + "C-j" #'vertico-next + "C-k" #'vertico-previous + "C-M-j" #'vertico-next-group + "C-M-k" #'vertico-previous-group) + :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 +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 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 partial-completion)))))) + '((file + (styles ;basic-remote + orderless partial-completion)))) + (orderless-style-dispatchers '(+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) diff --git a/users/crumb/programs/emacs/modules/syd-general.el b/users/crumb/programs/emacs/modules/syd-general.el new file mode 100644 index 0000000..17d266d --- /dev/null +++ b/users/crumb/programs/emacs/modules/syd-general.el @@ -0,0 +1,8 @@ +;;; syd-general.el -*- lexical-binding: t; -*- + +(use-package general + :custom (general-use-package-emit-autoloads t)) + +(require 'general) + +(provide 'syd-general) diff --git a/users/crumb/programs/emacs/modules/syd-keybinds.el b/users/crumb/programs/emacs/modules/syd-keybinds.el index fa05534..7ec28ce 100644 --- a/users/crumb/programs/emacs/modules/syd-keybinds.el +++ b/users/crumb/programs/emacs/modules/syd-keybinds.el @@ -1,10 +1,7 @@ ;;; syd-keybinds.el -*- lexical-binding: t; -*- ;;; Universal keybindings, not /too/ tied to any particular packages. -(use-package general - :custom (general-use-package-emit-autoloads t)) - -(require 'general) +(require 'syd-general) (defvar syd-leader-key "SPC" "A prefix key akin to Vim's .")