summaryrefslogtreecommitdiff
path: root/modules/selection-framework.el
blob: 9e7e44a3e88076e3d2ef953ae8306da95da1e625 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
;;; selection-framework.el --- Completion and Selection Framework -*- lexical-binding: t; coding: utf-8; -*-
;; author Craig Jennings <c@cjennings.net>

;;; Commentary:
;;
;; This module configures the completion and selection framework using:
;; - Vertico: Vertical completion UI
;; - Marginalia: Rich annotations in minibuffer
;; - Consult: Practical commands based on completing-read
;; - Orderless: Advanced completion style
;; - Embark: Contextual actions
;; - Company: In-buffer completion
;;
;; The configuration provides a modern, fast, and feature-rich completion
;; experience that enhances Emacs' built-in completing-read functionality.
;;
;;; Code:

;; ---------------------------------- Vertico ----------------------------------
;; Vertical completion UI

(use-package vertico
  :demand t
  :custom
  (vertico-cycle t)                ; Cycle through candidates
  (vertico-count 10)               ; Number of candidates to display
  (vertico-resize nil)             ; Don't resize the minibuffer
  (vertico-sort-function #'vertico-sort-history-alpha) ; History first, then alphabetical
  :bind (:map vertico-map
			  ;; Match ivy's C-j C-k behavior
			  ("C-j"   . vertico-next)
			  ("C-k"   . vertico-previous)
			  ("C-l"   . vertico-insert)  ; Insert current candidate
			  ("RET"   . vertico-exit)
			  ("C-RET" . vertico-exit-input)
			  ("M-RET" . minibuffer-force-complete-and-exit)
			  ("TAB"   . minibuffer-complete))
  :init
  (vertico-mode))

(use-package marginalia
  :demand t
  :custom
  (marginalia-max-relative-age 0)
  (marginalia-align 'right)
  :init
  (marginalia-mode))

(use-package nerd-icons-completion
  :demand t
  :hook (marginalia-mode nerd-icons-completion-marginalia-setup)
  :after marginalia
  :init
  (nerd-icons-completion-mode))

;; ---------------------------------- Consult ----------------------------------
;; Practical commands based on completing-read

(use-package consult
  :demand t
  :bind (;; C-c bindings (mode-specific-map)
		 ("C-c h" . consult-history)
		 ;; C-x bindings (ctl-x-map)
		 ("C-x M-:" . consult-complex-command)
		 ("C-x b" . consult-buffer)
		 ("C-x 4 b" . consult-buffer-other-window)
		 ("C-x 5 b" . consult-buffer-other-frame)
		 ("C-x r b" . consult-bookmark)
		 ("C-x p b" . consult-project-buffer)
		 ;; M-g bindings (goto-map)
		 ("M-g e" . consult-compile-error)
		 ("M-g f" . consult-flymake)
		 ("M-g g" . consult-goto-line)
		 ("M-g M-g" . consult-goto-line)
		 ("M-g o" . consult-outline)
		 ("M-g m" . consult-mark)
		 ("M-g k" . consult-global-mark)
		 ("M-g i" . consult-imenu)
		 ("M-g I" . consult-imenu-multi)
		 ;; M-s bindings (search-map)
		 ("M-s d" . consult-find)
		 ("M-s D" . consult-locate)
		 ("M-s g" . consult-grep)
		 ("M-s G" . consult-git-grep)
		 ("M-s r" . consult-ripgrep)
		 ("M-s l" . consult-line)
		 ("M-s L" . consult-line-multi)
		 ("M-s k" . consult-keep-lines)
		 ("M-s u" . consult-focus-lines)
		 ;; Isearch integration
		 ("M-s e" . consult-isearch-history)
		 :map isearch-mode-map
		 ("M-e" . consult-isearch-history)
		 ("M-s e" . consult-isearch-history)
		 ("M-s l" . consult-line)
		 ("M-s L" . consult-line-multi)
		 ;; Minibuffer history
		 :map minibuffer-local-map
		 ("M-s" . consult-history)
		 ("M-r" . consult-history))

  :hook (completion-list-mode . consult-preview-at-point-mode)

  :init
  ;; Optionally configure the register formatting. This improves the register
  ;; preview for =consult-register', =consult-register-load',
  ;; =consult-register-store' and the Emacs built-ins.
  (setq register-preview-delay 0.5
		register-preview-function #'consult-register-format)

  ;; Optionally tweak the register preview window.
  (advice-add #'register-preview :override #'consult-register-window)

  ;; Configure other variables and modes
  (setq xref-show-xrefs-function #'consult-xref
		xref-show-definitions-function #'consult-xref)

  :config
  ;; Configure preview. Default is 'any.
  (setq consult-preview-key 'any)

  ;; Configure narrowing key
  (setq consult-narrow-key "<")

  ;; Reset to defaults to avoid issues
  (setq consult-point-placement 'match-beginning)

  ;; Use Consult for completion-at-point
  (setq completion-in-region-function #'consult-completion-in-region))

(global-unset-key (kbd "C-s"))
(global-set-key (kbd "C-s") 'consult-line)

;; Consult integration with Embark
(use-package embark-consult
  :after (embark consult)
  :hook
  (embark-collect-mode . consult-preview-at-point-mode))

(use-package consult-dir
  :bind (("C-x C-d" . consult-dir)
		 :map vertico-map
		 ("C-x C-d" . consult-dir)
		 ("C-x C-j" . consult-dir-jump-file))
  :config
  (add-to-list 'consult-dir-sources 'consult-dir--source-tramp-ssh t)
  (setq consult-dir-project-list-function #'consult-dir-projectile-dirs))

;; --------------------------------- Orderless ---------------------------------
;; Advanced completion style - provides space-separated, out-of-order matching


(use-package orderless
  :demand t
  :custom
  (completion-styles '(orderless))
  (completion-category-defaults nil)
  (completion-category-overrides '((file (styles partial-completion))
								   (multi-category (styles orderless))))
  (orderless-matching-styles '(orderless-literal
							   orderless-regexp
							   orderless-initialism
							   orderless-prefixes)))

;; ---------------------------------- Embark -----------------------------------
;; Contextual actions - provides right-click like functionality

(use-package embark
  :demand t
  :bind
  (("C-." . embark-act)         ;; pick an action to run
   ("C->" . embark-act-all)     ;; pick an action to run on all candidates
   ("C-," . embark-dwim)        ;; do what I mean
   ("C-h B" . embark-bindings)) ;; alternative for =describe-bindings'

  :init
  ;; Optionally replace the key help with a completing-read interface
  (setq prefix-help-command #'embark-prefix-help-command)

  :config
  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
			   '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
				 nil
				 (window-parameters (mode-line-format . none)))))

;; this typo causes crashes
;; (add-to-list 'display-buffer-alist
;;               '("\\=\\*Embark Collect \\(Live\\|Completions\\)\\*"
;;                 nil
;;                 (window-parameters (mode-line-format . none)))))

;; --------------------------- Consult Integration ----------------------------
;; Additional integrations for specific features

;; Yasnippet integration - replaces ivy-yasnippet
(use-package consult-yasnippet
  :after yasnippet
  :bind ("C-c s i" . consult-yasnippet))

;; Flycheck integration
(use-package consult-flycheck
  :after flycheck
  :bind (:map flycheck-mode-map
			  ("C-c ! c" . consult-flycheck)))

;; ---------------------------------- Company ----------------------------------
;; In-buffer completion (retained from original configuration)

(use-package company
  :demand t
  :hook (after-init . global-company-mode)
  :bind
  (:map company-active-map
		("<tab>" . company-complete-selection)
		("C-n" . company-select-next)
		("C-p" . company-select-previous))
  :custom
  (company-backends '(company-capf company-files company-keywords))
  (company-idle-delay 2)
  (company-minimum-prefix-length 2)
  (company-show-numbers t)
  (company-tooltip-align-annotations t)
  (company-tooltip-flip-when-above t)
  (company-tooltip-limit 10)
  (company-selection-wrap-around t)
  (company-require-match nil)
  :config
  ;; Disable company in mail-related modes
  (setq company-global-modes
		'(not message-mode
			  mu4e-compose-mode
			  org-msg-edit-mode)))


(use-package company-quickhelp
  :after company
  :config
  (company-quickhelp-mode))

;; Icons for company
(use-package company-box
  :after company
  :hook (company-mode . company-box-mode))

;; --------------------------------- Prescient ---------------------------------

(use-package prescient
  :demand t
  :config
  (prescient-persist-mode))

(use-package vertico-prescient
  :demand t
  :config
  (vertico-prescient-mode))

(use-package company-prescient
  :demand t
  :config
  (company-prescient-mode))

(provide 'selection-framework)
;;; selection-framework.el ends here