240 lines
8.1 KiB
EmacsLisp
240 lines
8.1 KiB
EmacsLisp
;;; init-completion.el --- Initialize completion configurations. -*- lexical-binding: t -*-
|
|
|
|
;; Copyright (C) 2016-2025 Vincent Zhang
|
|
|
|
;; Author: Vincent Zhang <seagle0128@gmail.com>
|
|
;; URL: https://github.com/seagle0128/.emacs.d
|
|
|
|
;; This file is not part of GNU Emacs.
|
|
;;
|
|
;; 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, 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; see the file COPYING. If not, write to
|
|
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
;; Floor, Boston, MA 02110-1301, USA.
|
|
;;
|
|
|
|
;;; Commentary:
|
|
;;
|
|
;; Modern completion configuration.
|
|
;;
|
|
|
|
|
|
;; Optionally use the `orderless' completion style.
|
|
(use-package orderless
|
|
:custom
|
|
(completion-styles '(orderless basic))
|
|
(completion-category-defaults nil)
|
|
(completion-category-overrides '((file (styles orderless partial-completion))))
|
|
(orderless-component-separator #'orderless-escapable-split-on-space))
|
|
|
|
;; Support Pinyin
|
|
(use-package pinyinlib
|
|
:after orderless
|
|
:functions orderless-regexp
|
|
:autoload pinyinlib-build-regexp-string
|
|
:init
|
|
(defun orderless-regexp-pinyin (str)
|
|
"Match COMPONENT as a pinyin regex."
|
|
(orderless-regexp (pinyinlib-build-regexp-string str)))
|
|
(add-to-list 'orderless-matching-styles 'orderless-regexp-pinyin))
|
|
|
|
;; VERTical Interactive COmpletion
|
|
(use-package vertico
|
|
:custom (vertico-count 15)
|
|
:bind (:map vertico-map
|
|
("RET" . vertico-directory-enter)
|
|
("DEL" . vertico-directory-delete-char)
|
|
("M-DEL" . vertico-directory-delete-word))
|
|
:init
|
|
(vertico-mode t))
|
|
|
|
;; (use-package vertico-posframe
|
|
;; :after vertico
|
|
;; :hook (vertico-mode . vertico-posframe-mode))
|
|
|
|
(use-package vertico-multiform
|
|
:ensure nil
|
|
:hook (vertico-mode . vertico-multiform-mode)
|
|
:config
|
|
(defvar +vertico-transform-functions nil)
|
|
|
|
(cl-defmethod vertico--format-candidate :around
|
|
(cand prefix suffix index start &context ((not +vertico-transform-functions) null))
|
|
(dolist (fun (ensure-list +vertico-transform-functions))
|
|
(setq cand (funcall fun cand)))
|
|
(cl-call-next-method cand prefix suffix index start))
|
|
|
|
(defun +vertico-highlight-directory (file)
|
|
"If FILE ends with a slash, highlight it as a directory."
|
|
(when (string-suffix-p "/" file)
|
|
(add-face-text-property 0 (length file) 'marginalia-file-priv-dir 'append file))
|
|
file)
|
|
|
|
(defun +vertico-highlight-enabled-mode (cmd)
|
|
"If MODE is enabled, highlight it as font-lock-constant-face."
|
|
(let ((sym (intern cmd)))
|
|
(with-current-buffer (nth 1 (buffer-list))
|
|
(if (or (eq sym major-mode)
|
|
(and
|
|
(memq sym minor-mode-list)
|
|
(boundp sym)
|
|
(symbol-value sym)))
|
|
(add-face-text-property 0 (length cmd) 'font-lock-constant-face 'append cmd)))
|
|
cmd))
|
|
|
|
(add-to-list 'vertico-multiform-categories
|
|
'(file
|
|
(+vertico-transform-functions . +vertico-highlight-directory)))
|
|
(add-to-list 'vertico-multiform-commands
|
|
'(execute-extended-command
|
|
(+vertico-transform-functions . +vertico-highlight-enabled-mode))))
|
|
|
|
;; Enrich existing commands with completion annotations
|
|
(use-package marginalia
|
|
:init
|
|
(marginalia-mode))
|
|
|
|
;; Add icons to completion candidates
|
|
(use-package nerd-icons-completion
|
|
:after marginalia
|
|
:config
|
|
(nerd-icons-completion-mode)
|
|
(add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))
|
|
|
|
;; Consulting completing-read
|
|
(use-package consult
|
|
:defines (xref-show-xrefs-function xref-show-definitions-function)
|
|
:defines shr-color-html-colors-alist
|
|
:autoload (consult-register-format consult-register-window consult-xref)
|
|
:autoload (consult--read consult--customize-put)
|
|
:commands (consult-narrow-help)
|
|
:functions (list-colors-duplicates consult-colors--web-list)
|
|
:bind (("C-c ." . consult-imenu)
|
|
("C-c T" . consult-theme)
|
|
|
|
("s-f" . consult-line)
|
|
("C-c s s" . consult-line)
|
|
("C-c p f" . consult-project-buffer)
|
|
("C-c f r" . consult-recent-file)
|
|
("C-x C-b" . consult-buffer)
|
|
("C-c s p" . consult-ripgrep)))
|
|
|
|
|
|
(use-package consult-dir
|
|
:ensure t
|
|
:bind (("C-x C-d" . consult-dir)
|
|
:map minibuffer-local-completion-map
|
|
("C-x C-d" . consult-dir)
|
|
("C-x C-j" . consult-dir-jump-file)))
|
|
|
|
(use-package consult-yasnippet
|
|
:bind ("M-g y" . consult-yasnippet))
|
|
|
|
(use-package embark
|
|
:commands embark-prefix-help-command
|
|
:bind (("C-;" . embark-act)
|
|
("M-." . embark-dwim) ; overrides `xref-find-definitions'
|
|
([remap describe-bindings] . embark-bindings)
|
|
:map minibuffer-local-map
|
|
("M-." . my-embark-preview))
|
|
:init
|
|
;; Optionally replace the key help with a completing-read interface
|
|
(setq prefix-help-command #'embark-prefix-help-command))
|
|
(use-package embark-consult
|
|
:bind (:map minibuffer-mode-map
|
|
("C-c C-o" . embark-export))
|
|
:hook (embark-collect-mode . consult-preview-at-point-mode))
|
|
|
|
;; Auto completion
|
|
(use-package corfu
|
|
:custom
|
|
(corfu-auto t)
|
|
(corfu-auto-prefix 2)
|
|
(corfu-count 12)
|
|
(corfu-preview-current nil)
|
|
(corfu-on-exact-match nil)
|
|
(corfu-auto-delay 0.2)
|
|
(corfu-popupinfo-delay '(0.4 . 0.2))
|
|
(global-corfu-modes '((not erc-mode
|
|
circe-mode
|
|
help-mode
|
|
gud-mode
|
|
vterm-mode)
|
|
t))
|
|
:custom-face
|
|
(corfu-border ((t (:inherit region :background unspecified))))
|
|
:bind ("M-/" . completion-at-point)
|
|
:init
|
|
(global-corfu-mode)
|
|
(corfu-history-mode)
|
|
(corfu-popupinfo-mode)
|
|
:config
|
|
;;Quit completion before saving
|
|
(add-hook 'before-save-hook #'corfu-quit)
|
|
(advice-add #'persistent-scratch-save :before #'corfu-quit))
|
|
|
|
(use-package nerd-icons-corfu
|
|
:init
|
|
(with-eval-after-load 'corfu
|
|
(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)))
|
|
|
|
(use-package wgrep
|
|
:commands wgrep-change-to-wgrep-mode
|
|
:config (setq wgrep-auto-save-buffer t))
|
|
|
|
;; A few more useful configurations...
|
|
(use-package emacs
|
|
:ensure nil
|
|
:custom
|
|
;; TAB cycle if there are only few candidates
|
|
;; (completion-cycle-threshold 3)
|
|
|
|
;; Enable indentation+completion using the TAB key.
|
|
;; `completion-at-point' is often bound to M-TAB.
|
|
(tab-always-indent 'complete)
|
|
|
|
;; Emacs 30 and newer: Disable Ispell completion function. As an alternative,
|
|
;; try `cape-dict'.
|
|
(text-mode-ispell-word-completion nil)
|
|
|
|
;; Emacs 28 and newer: Hide commands in M-x which do not apply to the current
|
|
;; mode. Corfu commands are hidden, since they are not used via M-x. This
|
|
;; setting is useful beyond Corfu.
|
|
(read-extended-command-predicate #'command-completion-default-include-p))
|
|
|
|
(use-package cape
|
|
:init
|
|
;; Add `completion-at-point-functions', used by `completion-at-point'.
|
|
;; (add-to-list 'completion-at-point-functions #'cape-dabbrev)
|
|
(add-to-list 'completion-at-point-functions #'cape-file)
|
|
(add-to-list 'completion-at-point-functions #'cape-elisp-block)
|
|
(add-to-list 'completion-at-point-functions #'cape-keyword)
|
|
;; Make these capfs composable.
|
|
(advice-add 'lsp-completion-at-point :around #'cape-wrap-noninterruptible)
|
|
(advice-add 'lsp-completion-at-point :around #'cape-wrap-nonexclusive)
|
|
(advice-add 'comint-completion-at-point :around #'cape-wrap-nonexclusive)
|
|
(advice-add 'eglot-completion-at-point :around #'cape-wrap-buster)
|
|
(advice-add 'eglot-completion-at-point :around #'cape-wrap-nonexclusive)
|
|
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-nonexclusive))
|
|
|
|
(use-package yasnippet-capf
|
|
:after cape
|
|
:config
|
|
(add-to-list 'completion-at-point-functions #'yasnippet-capf))
|
|
|
|
|
|
(provide 'init-completion)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;; init-completion.el ends here
|