diff options
Diffstat (limited to '.emacs.d/lisp/init-completion.el')
-rw-r--r-- | .emacs.d/lisp/init-completion.el | 184 |
1 files changed, 114 insertions, 70 deletions
diff --git a/.emacs.d/lisp/init-completion.el b/.emacs.d/lisp/init-completion.el index cac9c0a..16eca6b 100644 --- a/.emacs.d/lisp/init-completion.el +++ b/.emacs.d/lisp/init-completion.el @@ -4,75 +4,103 @@ ;; Most of it is taken from the READMEs and wikis of those packages ;;; Code: +(defun +elpaca-unload-dabbrev (e) + (and (featurep 'dabbrev) (unload-feature 'dabbrev t)) + (elpaca--continue-build e)) + +(defun +elpaca-dabbrev-build-steps () + (append (butlast (if (file-exists-p (expand-file-name "dabbrev" elpaca-builds-directory)) + elpaca--pre-built-steps elpaca-build-steps)) + (list '+elpaca-unload-dabbrev 'elpaca--activate-package))) + (use-feature dabbrev - :diminish :custom (dabbrev-case-distinction nil) (dabbrev-case-fold-search t) (dabbrev-case-replace nil)) -(use-feature hippie-expand +(use-package mono-complete :config - (setq hippie-expand-try-functions-list - '(;yas-hippie-try-expand - try-expand-dabbrev - try-expand-all-abbrevs - try-expand-dabbrev-all-buffers - try-expand-dabbrev-from-kill - try-complete-file-name-partially - try-complete-file-name - try-expand-list - try-expand-line - try-complete-lisp-symbol-partially - try-complete-lisp-symbol)) - ;; https://www.emacswiki.org/emacs/HippieExpand#h5o-9 - (defadvice he-substitute-string (after he-paredit-fix) - "Remove extra paren when expanding line in paredit." - (if (and (or smartparens-mode paredit-mode) (equal (substring str -1) ")")) - (progn (backward-delete-char 1) (forward-char)))) + (setq mono-complete-preview-delay 0.15 + mono-complete-backends '(dabbrev filesystem whole-line) + mono-complete-project-root 'persp-current-project-root) + (append-to-list* 'mono-complete-self-insert-commands 'sp-backward-delete-char 'sp-delete-char 'delete-indentation 'backward-delete-char 'delete-char) + (defun mono-complete-expand-or-complete () + (interactive) + (if (eq 'mono-complete-expand-or-complete real-last-command) + (let ((corfu-preselect 'prompt)) + (progn + (primitive-undo 2 buffer-undo-list) + (completion-at-point))) + (mono-complete-expand-or-fallback))) + :hook ((text-mode prog-mode) . mono-complete-mode) :bind - ("C-M-/" . hippie-expand)) + (:map mono-complete-mode-map ("M-/" . mono-complete-expand-or-complete))) -(use-package fancy-dabbrev - :diminish - :config - (global-fancy-dabbrev-mode) - (defun fancy-dabbrev-popup-advice (_next) - (local-set-key (kbd "C-M-/") #'fancy-dabbrev-backward)) - (defun fancy-dabbrev-popup-exit-advice () - (local-unset-key (kbd "C-M-/"))) - (advice-add #'fancy-dabbrev--expand-again :before #'fancy-dabbrev-popup-advice) - (advice-add #'fancy-dabbrev--on-exit :after #'fancy-dabbrev-popup-exit-advice) - :bind ("M-/" . fancy-dabbrev-expand)) +(use-feature hippie-expand + :custom + (hippie-expand-try-functions-list '(try-expand-dabbrev + try-expand-all-abbrevs + try-expand-dabbrev-all-buffers + try-expand-dabbrev-from-kill + try-complete-file-name-partially + try-complete-file-name + try-expand-list + try-expand-line + try-complete-lisp-symbol-partially + try-complete-lisp-symbol)) + :hook (elpaca-after-init . (lambda () + ;; Modified from https://www.emacswiki.org/emacs/HippieExpand#h5o-9 + (define-advice he-substitute-string (:after (str &optional trans-case) he-paredit-fix) + "Remove extra bracket when expanding line in paredit/smartparents mode." + (if (and (or smartparens-mode paredit-mode) (string-match "[]})]$" str)) + (progn (backward-delete-char 1) (forward-char)))))) + :bind + ("C-M-/" . hippie-expand)) (use-feature emacs :config - (setq completion-cycle-threshold 3) + (setq completion-cycle-threshold 2) (setq tab-always-indent 'complete) (setq read-buffer-completion-ignore-case t read-file-name-completion-ignore-case t completion-ignore-case t)) (use-package orderless - :defer 2 - :bind (:map minibuffer-local-map - ("C-l" . my/orderless-match-components-literally)) + :bind + (:map minibuffer-local-map + ("C-l" . orderless-toggle-literal-matching)) + (:map corfu-map + ("C-l" . orderless-toggle-literal-matching)) :custom (orderless-component-separator 'orderless-escapable-split-on-space) (completion-styles '(orderless partial-completion basic)) (completion-category-defaults nil) - (completion-category-overrides '((file (styles . (partial-completion orderless))))) (orderless-matching-styles '(orderless-literal orderless-regexp orderless-strict-initialism)) - (orderless-style-dispatchers '(+orderless-dispatch)) + (orderless-style-dispatchers (list #'+orderless-consult-dispatch + #'orderless-affix-dispatch)) :config - (defun my/orderless-match-components-literally () - "Components match literally for the rest of the session." + ;; Inspired by https://github.com/oantolin/orderless/blob/ac4aeb66f331f4c4a430d5556071e33177304c37/README.org#interactively-changing-the-configuration + (defun orderless-toggle-literal-matching () + "Toggle matching components literally for the rest of the session." (interactive) - (setq-local orderless-matching-styles '(orderless-literal) - orderless-style-dispatchers nil)) + (if orderless-style-dispatchers + (progn + (setq-local +saved-orderless-matching-styles orderless-matching-styles + +saved-orderless-style-dispatchers orderless-style-dispatchers) + (setq-local orderless-matching-styles '(orderless-literal) + orderless-style-dispatchers nil)) + (setq-local orderless-matching-styles +saved-orderless-matching-styles + orderless-style-dispatchers +saved-orderless-style-dispatchers)) + (when vertico--input + (setq vertico--input t) + (vertico--update)) + (when corfu--input + (setq corfu--input t) + (corfu--update))) (defun orderless-strict-initialism (component &optional leading) - "Match a component as a strict leading initialism. + "Match a component as a strict initialism. This means the characters in COMPONENT must occur in the candidate, in that order, at the beginning of words, with no words in between. If LEADING is non-nil, anchor to the @@ -88,68 +116,84 @@ candidate, in that order, at the beginning of words, with no words in between, beginning with the first word." (orderless-strict-initialism component t)) - ;; based on https://github.com/minad/consult/wiki#minads-orderless-configuration - (defvar +orderless-dispatch-alist - '((?% . char-fold-to-regexp) - (?! . orderless-without-literal) - (?` . orderless-strict-leading-initialism) - (?= . orderless-literal) - (?_ . orderless-prefix) - (?~ . orderless-flex))) + ;; Replace initialism (,) with strict-leading-initialism, and also add strict initialism + (setf (alist-get ?, orderless-affix-dispatch-alist) #'orderless-strict-leading-initialism) + (add-to-list 'orderless-affix-dispatch-alist '(?` . orderless-strict-initialism) t) - (defun +orderless--suffix-regexp () + ;; Copied from https://github.com/minad/consult/wiki#minads-orderless-configuration + (defun +orderless--consult-suffix () + "Regexp which matches the end of string with Consult tofu support." (if (and (boundp 'consult--tofu-char) (boundp 'consult--tofu-range)) (format "[%c-%c]*$" consult--tofu-char (+ consult--tofu-char consult--tofu-range -1)) "$")) + ;; Copied from https://github.com/minad/consult/wiki#minads-orderless-configuration ;; Recognizes the following patterns: - ;; * ~flex flex~ - ;; * =literal literal= - ;; * _prefix prefix_ - ;; * %char-fold char-fold% - ;; * `strict-leading-initialism strict-leading-initialism` - ;; * !without-literal without-literal! ;; * .ext (file extension) ;; * regexp$ (regexp matching at end) - (defun +orderless-dispatch (word _index _total) + (defun +orderless-consult-dispatch (word _index _total) (cond ;; Ensure that $ works with Consult commands, which add disambiguation suffixes ((string-suffix-p "$" word) - `(orderless-regexp . ,(concat (substring word 0 -1) (+orderless--suffix-regexp)))) + `(orderless-regexp . ,(concat (substring word 0 -1) (+orderless--consult-suffix)))) ;; File extensions ((and (or minibuffer-completing-file-name (derived-mode-p 'eshell-mode)) (string-match-p "\\`\\.." word)) - `(orderless-regexp . ,(concat "\\." (substring word 1) (+orderless--suffix-regexp)))) - ;; Ignore single ! - ((equal "!" word) `(orderless-literal . "")) - ;; Prefix and suffix - ((if-let (x (assq (aref word 0) +orderless-dispatch-alist)) - (cons (cdr x) (substring word 1)) - (when-let (x (assq (aref word (1- (length word))) +orderless-dispatch-alist)) - (cons (cdr x) (substring word 0 -1)))))))) + `(orderless-regexp . ,(concat "\\." (substring word 1) (+orderless--consult-suffix)))))) + + ;; Based on https://github.com/minad/consult/wiki#minads-orderless-configuration + (orderless-define-completion-style +orderless-with-strict-leading-initialism + (orderless-matching-styles '(orderless-literal orderless-regexp orderless-strict-leading-initialism))) + + (setopt completion-category-overrides '((file (styles partial-completion orderless)) + (command (styles +orderless-with-strict-leading-initialism)) + (variable (styles +orderless-with-strict-leading-initialism)) + (symbol (styles +orderless-with-strict-leading-initialism))))) ;; code completion - corfu (use-package corfu :ensure (corfu :files (:defaults "extensions/*")) :custom (corfu-cycle t) + (corfu-preselect 'first) :bind (:map corfu-map + ("SPC" . corfu-insert) ("TAB" . corfu-next) ([tab] . corfu-next) + ("M-/" . corfu-next) ("S-TAB" . corfu-previous) - ([backtab] . corfu-previous)) + ([backtab] . corfu-previous) + ("C-M-/" . corfu-previous)) :hook (elpaca-after-init . global-corfu-mode)) (use-extension corfu corfu-indexed - :config (corfu-indexed-mode 1)) + :config + (defmacro define-corfu-complete (n) + `(defun ,(intern (format "corfu-indexed-complete-%s" n)) () + ,(format "Complete with candidate %s." n) + (interactive) + (let ((corfu--index ,n)) + (funcall-interactively 'corfu-complete)))) + (defmacro define-corfu-insert (n) + `(defun ,(intern (format "corfu-indexed-insert-%s" n)) () + ,(format "Insert candidate %s." n) + (interactive) + (let ((corfu--index ,n)) + (funcall-interactively 'corfu-insert)))) + (dotimes (n 10) + (eval `(define-corfu-complete ,n)) + (eval `(define-corfu-insert ,n)) + (define-key corfu-map (kbd (format "C-%s" n)) (intern (format "corfu-indexed-complete-%s" n))) + (define-key corfu-map (kbd (format "M-%s" n)) (intern (format "corfu-indexed-insert-%s" n)))) + (corfu-indexed-mode 1)) (use-extension corfu corfu-quick :bind (:map corfu-map ("M-;" . corfu-quick-insert) - ("M-'" . corfu-quick-exit))) + ("M-'" . corfu-quick-complete))) (use-extension corfu corfu-history :after savehist |