diff options
Diffstat (limited to '.config/emacs/lisp/evil-collection/modes/corfu')
| -rw-r--r-- | .config/emacs/lisp/evil-collection/modes/corfu/README.org | 54 | ||||
| -rw-r--r-- | .config/emacs/lisp/evil-collection/modes/corfu/evil-collection-corfu.el | 180 |
2 files changed, 234 insertions, 0 deletions
diff --git a/.config/emacs/lisp/evil-collection/modes/corfu/README.org b/.config/emacs/lisp/evil-collection/modes/corfu/README.org new file mode 100644 index 0000000..71820eb --- /dev/null +++ b/.config/emacs/lisp/evil-collection/modes/corfu/README.org @@ -0,0 +1,54 @@ +* corfu + + Evil bindings for [[https://github.com/minad/corfu][corfu]] in-buffer completion. + + Bindings apply in =insert= state on =corfu-map= and are gated by + =evil-collection-corfu-key-themes=. Only =default= is enabled out of the box. + +** Key bindings + +*** default theme + + | Command | Original | Evil | + |-----------------------------------------+----------+-------------------------------------| + | =corfu-next= | =<down>= | =C-n=, =C-j=, =M-j=, =<down>= | + | =corfu-previous= | =<up>= | =C-p=, =C-k=, =M-k=, =<up>= | + | =corfu-insert= | =RET= | =RET= | + | =corfu-complete= | =TAB= | =TAB= | + | =corfu-quit= | =C-g= | =C-g= | + | =evil-collection-corfu-quit-and-escape= | n/a | =<escape>= | + | =corfu-scroll-up= | n/a | =C-d= (when =evil-want-C-u-scroll=) | + | =corfu-scroll-down= | n/a | =C-u= (when =evil-want-C-d-scroll=) | + +*** tab-n-go theme + + Also sets =corfu-cycle= to =t= and =corfu-preselect= to =prompt=. + + | Command | Original | Evil | + |------------------+----------+--------------------| + | =corfu-next= | n/a | =TAB= | + | =corfu-previous= | n/a | =S-TAB=, =backtab= | + +*** magic-return theme + + =RET= / =<return>= insert the candidate when one is selected, otherwise + fall through to the buffer's default newline. + +*** magic-backspace theme + + =DEL= / =<backspace>= reset the selection when one is active, otherwise + fall through. + +** New commands + + | Command | Purpose | + |-----------------------------------------+----------------------------------------------------------| + | =evil-collection-corfu-quit-and-escape= | =corfu-quit= then =evil-normal-state=. | + | =evil-collection-corfu-insert-exact= | Insert current candidate with =exact= status, else quit. | + +** Customization + + | Variable | Default | Purpose | + |------------------------------------------+------------------------------+-----------------------------------------------------------------------| + | =evil-collection-corfu-key-themes= | =(default)= | Themes from =default=, =tab-n-go=, =magic-return=, =magic-backspace=. | + | =evil-collection-corfu-supported-states= | =(insert replace emacs nil)= | Evil states in which =corfu= is allowed to run. | diff --git a/.config/emacs/lisp/evil-collection/modes/corfu/evil-collection-corfu.el b/.config/emacs/lisp/evil-collection/modes/corfu/evil-collection-corfu.el new file mode 100644 index 0000000..f70dedc --- /dev/null +++ b/.config/emacs/lisp/evil-collection/modes/corfu/evil-collection-corfu.el @@ -0,0 +1,180 @@ +;;; evil-collection-corfu.el --- Bindings for `corfu-mode' -*- lexical-binding: t -*- + +;; Copyright (C) 2022 James Nguyen + +;; Author: James Nguyen <james@jojojames.com> +;; Maintainer: James Nguyen <james@jojojames.com> +;; URL: https://github.com/emacs-evil/evil-collection +;; Version: 0.0.1 +;; Package-Requires: ((emacs "27.1")) +;; Keywords: evil, corfu, convenience, matching + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: +;;; Bindings for `corfu-mode'. + +;;; Code: +(require 'corfu nil t) +(require 'evil-collection) + +(defgroup evil-collection-corfu nil + "Evil bindings for `corfu-mode'." + :group 'evil-collection) + +(defvar corfu-map) +(defvar corfu-cycle) +(defvar corfu-preselect) +(defvar corfu--index) + +(declare-function corfu-insert "corfu") +(declare-function corfu-reset "corfu") +(declare-function corfu-quit "corfu") + +(defconst evil-collection-corfu-maps '(corfu-map)) + +(defun evil-collection-corfu-quit-and-escape () + "Call `corfu-quit' and then return to Normal State." + (interactive) + (call-interactively 'corfu-quit) + (evil-normal-state)) + +;; https://github.com/minad/corfu/pull/169 +;; https://github.com/minad/corfu/pull/225 +(defun evil-collection-corfu-unread-this-command-keys () + (when (> (length (this-command-keys)) 0) + (setq unread-command-events (nconc + (listify-key-sequence (this-command-keys)) + unread-command-events)) + (clear-this-command-keys t))) + +(defun evil-collection-corfu-insert-exact () + "Insert current candidate with the `exact' status. +Quit if no candidate is selected." + (interactive) + (if (>= corfu--index 0) + (corfu--insert 'exact) + (corfu-quit))) + +(defcustom evil-collection-corfu-key-themes '(default) + "Determines the key theme to be mapped. + +This variable should be set before `evil-collection-corfu-setup' is called. + +By default, only default is added to this list as the other key themes might +be too obtrusive. + +This key theme variable may be refactored in the future so use with caution." + :type + '(repeat + :tag "Key Themes" + (choice + (const + :tag "Default Theme" default) + (const + :tag "Tab & Go" tab-n-go) + (const + :tag "Magic Return" magic-return) + (const + :tag "Magic Backspace" magic-backspace)))) + +(defcustom evil-collection-corfu-supported-states '(insert replace emacs nil) + "The `evil-state's which `corfu' function can be requested." + :type '(repeat symbol)) + +;;;###autoload +(defun evil-collection-corfu-setup () + "Set up `evil' bindings for `corfu'." + (when (memq 'default evil-collection-corfu-key-themes) + (evil-collection-define-key 'insert 'corfu-map + (kbd "C-n") 'corfu-next + (kbd "C-p") 'corfu-previous + (kbd "C-j") 'corfu-next + (kbd "C-k") 'corfu-previous + (kbd "M-j") 'corfu-next + (kbd "M-k") 'corfu-previous + (kbd "<down>") 'corfu-next + (kbd "<up>") 'corfu-previous + (kbd "<escape>") 'evil-collection-corfu-quit-and-escape)) + + ;; https://github.com/minad/corfu#tab-and-go-completion + (when (memq 'tab-n-go evil-collection-corfu-key-themes) + (setq corfu-cycle t + corfu-preselect 'prompt) + (evil-collection-define-key 'insert 'corfu-map + (kbd "TAB") 'corfu-next + [tab] 'corfu-next + [S-tab] 'corfu-previous + [backtab] 'corfu-previous)) + + (when (memq 'magic-return evil-collection-corfu-key-themes) + (defvar evil-collection-corfu-insert-or-next-line + `(menu-item "" nil :filter ,(lambda (&optional _) + (when (>= corfu--index 0) + 'corfu-insert))) + "If we made a selection during `corfu' completion, select it.") + ;; FIXME: Not sure why we need to use `define-key' here instead of + ;; `evil-collection-define-key';. + (when (evil-collection-can-bind-key "<return>") + (define-key corfu-map (kbd "<return>") + evil-collection-corfu-insert-or-next-line)) + (when (evil-collection-can-bind-key "RET") + (define-key corfu-map (kbd "RET") + evil-collection-corfu-insert-or-next-line))) + + (when (memq 'magic-backspace evil-collection-corfu-key-themes) + (defvar evil-collection-corfu-cancel-or-backspace + `(menu-item "" nil :filter ,(lambda (&optional _) + (when (>= corfu--index 0) + 'corfu-reset))) + "If we made a selection during `corfu' completion, cancel it.") + (evil-collection-define-key 'insert + 'corfu-map (kbd "DEL") evil-collection-corfu-cancel-or-backspace) + (evil-collection-define-key 'insert + 'corfu-map [backspace] evil-collection-corfu-cancel-or-backspace) + (evil-collection-define-key 'insert + 'corfu-map (kbd "<backspace>") evil-collection-corfu-cancel-or-backspace)) + + (when evil-want-C-u-scroll + (evil-collection-define-key 'insert 'corfu-map + (kbd "C-d") 'corfu-scroll-up)) + (when evil-want-C-d-scroll + (evil-collection-define-key 'insert 'corfu-map + (kbd "C-u") 'corfu-scroll-down)) + + (advice-add 'corfu--setup :after (lambda (&rest _) (evil-normalize-keymaps))) + (advice-add 'corfu--teardown :after (lambda (&rest _) (evil-normalize-keymaps))) + (advice-add 'corfu--continue-p + :before-while (lambda (&rest _) (memq evil-state evil-collection-corfu-supported-states))) + + (cl-defmethod corfu--insert :around (status) + (if (or (eq this-command 'evil-collection-corfu-insert-exact) + (not (eq status 'exact))) + (cl-call-next-method) + (evil-collection-corfu-unread-this-command-keys) + (setq this-command 'evil-collection-corfu-insert-exact))) + + (mapc #'evil-declare-ignore-repeat + '(corfu-next + corfu-previous + corfu-first + corfu-last)) + + (mapc #'evil-declare-change-repeat + '(evil-collection-corfu-insert-exact + corfu-insert + corfu-complete))) + +(provide 'evil-collection-corfu) +;;; evil-collection-corfu.el ends here |
