summary refs log tree commit diff stats
path: root/lisp/+completions.el
blob: 9baaaf8ea79a912ccf19c2c8647b10f3b2190525 (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
;;; +completions.el --- Better default completions  -*- lexical-binding: t; -*-

;; From https://robbmann.io/posts/emacs-29-completions/

(defun minibuffer@bindings ()
  (unless vertico-mode
    ;; Up/down when completing in the minibuffer
    (define-key minibuffer-local-map (kbd "C-p") #'minibuffer-previous-completion)
    (define-key minibuffer-local-map (kbd "C-n") #'minibuffer-next-completion)

    ;; Up/down when competing in a normal buffer
    (define-key completion-in-region-mode-map (kbd "C-p")
                #'minibuffer-previous-completion)
    (define-key completion-in-region-mode-map (kbd "C-n")
                #'minibuffer-next-completion)))

(add-hook 'vertico-mode-hook #'minibuffer@bindings)

(defun renz/sort-by-alpha-length (elems)
  "Sort ELEMS first alphabetically, then by length."
  (sort elems (lambda (c1 c2)
                (or (string-version-lessp c1 c2)
                    (< (length c1) (length c2))))))

(defun renz/sort-by-history (elems)
  "Sort ELEMS by minibuffer history.
Use `mct-sort-sort-by-alpha-length' if no history is available."
  (if-let ((hist (and (not (eq minibuffer-history-variable t))
                      (symbol-value minibuffer-history-variable))))
      (minibuffer--sort-by-position hist elems)
    (renz/sort-by-alpha-length elems)))

(defun renz/completion-category ()
  "Return completion category."
  (when-let ((window (active-minibuffer-window)))
    (with-current-buffer (window-buffer window)
      (completion-metadata-get
       (completion-metadata (buffer-substring-no-properties
                             (minibuffer-prompt-end)
                             (max (minibuffer-prompt-end) (point)))
                            minibuffer-completion-table
                            minibuffer-completion-predicate)
       'category))))

(defun renz/sort-multi-category (elems)
  "Sort ELEMS per completion category."
  (pcase (renz/completion-category)
    ('nil elems) ; no sorting
    ('kill-ring elems)
    ('project-file (renz/sort-by-alpha-length elems))
    (_ (renz/sort-by-history elems))))

(setq completion-auto-help 'always
      completion-auto-select 'second-tab
      completions-max-height 10
      completions-header-format nil
      completion-show-help nil
      completions-format 'one-column
      save-completions-file-name (etc/ "completions")
      completions-sort #'renz/sort-multi-category)

(add-hook 'completion-list-mode-hook #'truncate-lines-local-mode)

(provide '+completions)
;;; +completions.el ends here