about summary refs log tree commit diff stats
path: root/.emacs.d/lisp/init-completion.el
diff options
context:
space:
mode:
Diffstat (limited to '.emacs.d/lisp/init-completion.el')
-rw-r--r--.emacs.d/lisp/init-completion.el184
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