From 0adf2da1d62addce56afd5fb8866ecce77147bd5 Mon Sep 17 00:00:00 2001
From: jao <jao@gnu.org>
Date: Sun, 4 Apr 2021 21:40:15 +0100
Subject: completion.org and minicomp

---
 attic/counsel.org        |  63 +++++++
 completion.org           | 424 +++++++++++++++++++++++++++++++++++++++++++++++
 consult.org              | 405 --------------------------------------------
 init.org                 |  87 +---------
 lib/themes/jao-themes.el |   2 +
 readme.org               |   2 +-
 6 files changed, 494 insertions(+), 489 deletions(-)
 create mode 100644 completion.org
 delete mode 100644 consult.org

diff --git a/attic/counsel.org b/attic/counsel.org
index 6fbd591..f6814ae 100644
--- a/attic/counsel.org
+++ b/attic/counsel.org
@@ -1,5 +1,68 @@
 #+title: Completion configuration using ivy, counsel and friends
 
+* selectrum
+  #+begin_src emacs-lisp :load no
+    (use-package selectrum
+      :ensure t
+      :init
+      (defun jao-selectrum--ord-refine (&rest args)
+        (let ((completion-styles '(orderless)))
+          (apply #'selectrum-refine-candidates-using-completions-styles args)))
+
+      (defun jao-selectrum-orderless ()
+        (interactive)
+        (setq selectrum-refine-candidates-function #'jao-selectrum--ord-refine)
+        (setq selectrum-highlight-candidates-function #'orderless-highlight-matches)
+        (setq orderless-skip-highlighting (lambda () selectrum-is-active)))
+
+
+      :config
+      ;; https://github.com/raxod502/selectrum/wiki/Ido,-icomplete(fido)-emulation
+      (defun selectrum-fido-backward-updir ()
+        "Delete char before or go up directory, like `ido-mode'."
+        (interactive)
+        (if (and (eq (char-before) ?/)
+                 (eq (selectrum--get-meta 'category) 'file))
+            (save-excursion
+              (goto-char (1- (point)))
+              (when (search-backward "/" (point-min) t)
+                (delete-region (1+ (point)) (point-max))))
+          (call-interactively 'backward-delete-char)))
+
+      (defun selectrum-fido-delete-char ()
+        "Delete char or maybe call `dired', like `ido-mode'."
+        (interactive)
+        (let ((end (point-max)))
+          (if (or (< (point) end) (not (eq (selectrum--get-meta 'category) 'file)))
+              (call-interactively 'delete-char)
+            (dired (file-name-directory (minibuffer-contents)))
+            (exit-minibuffer))))
+
+      (defun selectrum-fido-ret ()
+        "Exit minibuffer or enter directory, like `ido-mode'."
+        (interactive)
+        (let* ((dir (and (eq (selectrum--get-meta 'category) 'file)
+                         (file-name-directory (minibuffer-contents))))
+               (current (selectrum-get-current-candidate))
+               (probe (and dir current
+                           (expand-file-name (directory-file-name current) dir))))
+          (if (and probe (file-directory-p probe) (not (string= current "./")))
+              (selectrum-insert-current-candidate)
+            (selectrum-select-current-candidate))))
+
+      ;; (define-key selectrum-minibuffer-map (kbd "RET") 'selectrum-fido-ret)
+      (define-key selectrum-minibuffer-map (kbd "DEL") 'selectrum-fido-backward-updir)
+      (define-key selectrum-minibuffer-map (kbd "C-d") 'selectrum-fido-delete-char)
+
+      :custom ((selectrum-complete-in-buffer t)
+               ;; (selectrum-display-action '(display-buffer-at-bottom))
+               (selectrum-extend-current-candidate-highlight t)
+               (selectrum-fix-vertical-window-height nil)
+               (selectrum-max-window-height 20)
+               (selectrum-show-indices nil)
+               (selectrum-count-style 'current/matches))
+      :bind (("C-R" . selectrum-repeat)))
+  #+end_src
 * ivy
   #+begin_src emacs-lisp
     (use-package ivy
diff --git a/completion.org b/completion.org
new file mode 100644
index 0000000..37d5bbf
--- /dev/null
+++ b/completion.org
@@ -0,0 +1,424 @@
+#+title: Completion configuration using selectrum, consult and friends
+
+* company
+  #+begin_src emacs-lisp
+    (use-package company
+      :ensure t
+      :custom
+      ((company-global-modes '(clojure-mode
+                               clojurec-mode
+                               emacs-lisp-mode
+                               eshell-mode
+                               lisp-interaction-mode
+                               haskell-mode
+                               message-mode
+                               org-mode
+                               scheme-mode))
+       (company-idle-delay 0.15)
+       (company-lighter "")
+       (company-lighter-base "")
+       (company-show-numbers nil)
+       (company-tooltip-limit 15)
+       (company-tooltip-align-annotations t)
+       (company-transformers '(company-sort-by-occurrence)))
+
+      :config
+      ;; Prevent non-matching input (which will dismiss the completions
+      ;; menu), but only if the user interacts explicitly with Company.
+      (setq company-require-match #'company-explicit-action-p)
+
+      (defun jao-complete-at-point ()
+        "Complete using company unless we're in the minibuffer."
+        (interactive)
+        (if (window-minibuffer-p) (completion-at-point) (company-manual-begin)))
+
+      :bind (([remap completion-at-point] . #'jao-complete-at-point)
+             ([remap complete-symbol] . #'jao-complete-at-point)
+
+             ;; The following are keybindings that take effect whenever
+             ;; the completions menu is visible, even if the user has not
+             ;; explicitly interacted with Company.
+             :map company-active-map
+
+             ([remap scroll-up-command] . nil)
+             ([remap scroll-down-command] . nil)
+
+             ;; Make TAB always complete the current selection, instead of
+             ;; only completing a common prefix.
+             ("<tab>" . #'company-complete-selection)
+             ("TAB" . #'company-complete-selection)
+
+             ("C-h" . #'company-show-doc-buffer)
+             ("M-." . #'company-show-location)
+
+             ;; The following are keybindings that only take effect
+             ;; if not in eshell.  Note that `:map' from above is
+             ;; "sticky", and applies also below.
+             ;; Another interesting :filter  (company-explicit-action-p)
+
+             :filter (or (not (derived-mode-p 'eshell-mode))
+                         (company-explicit-action-p))
+             ("<return>" . #'company-complete-selection)
+             ("RET" . #'company-complete-selection))
+
+      :bind* (;; The default keybinding for `completion-at-point' and
+              ;; `complete-symbol' is M-TAB or equivalently C-M-i. We
+              ;; already remapped those bindings to `company-manual-begin'
+              ;; above. Here we make sure that they definitely invoke
+              ;; `company-manual-begin' even if a minor mode binds M-TAB
+              ;; directly.
+              ("M-TAB" . #'jao-complete-at-point))
+
+    :diminish)
+
+    (use-package company-math :ensure t :after company)
+
+    (global-company-mode 1)
+
+  #+end_src
+
+* orderless
+  #+begin_src emacs-lisp :load no
+    (use-package orderless
+      :ensure t
+      :custom ((orderless-component-separator "[ -/]+")
+               (orderless-matching-styles
+                '(orderless-literal orderless-regexp orderless-initialism)))
+      :bind
+      ((:map minibuffer-local-completion-map ("SPC" . self-insert-command))))
+  #+end_src
+* minicomp
+  #+begin_src emacs-lisp
+    (jao-load-path "minicomp")
+    (use-package minicomp
+      :init (setq minicomp-count 20)
+      :config
+      (defun jao-minicomp--orderless (&rest _)
+        (setq-local completion-styles '(orderless)))
+      (add-hook 'minibuffer-setup-hook #'jao-minicomp--orderless))
+    (minicomp-mode 1)
+  #+end_src
+* marginalia
+  #+begin_src emacs-lisp
+    (use-package marginalia
+      :ensure t
+      :bind (:map minibuffer-local-map ("C-M-a" . marginalia-cycle))
+
+      :custom ((marginalia-align-offset 1)
+               (marginalia-margin-threshold 200)
+               (marginalia-separator-threshold 120)
+               (marginalia-truncate-width 80)
+               (marginalia-annotators
+                '(marginalia-annotators-heavy marginalia-annotators-light nil))))
+    (marginalia-mode 1)
+   #+end_src
+* consult
+  #+begin_src emacs-lisp
+    (use-package consult
+      :ensure t
+      :bind (("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-c b" . project-find-file)
+             ("C-c B" . bookmark-set)
+             ("C-c h" . consult-history)
+             ("C-c i" . consult-imenu)
+             ("C-c k" . consult-ripgrep)
+             ("C-c K" . consult-git-grep)
+             ("C-c l" . consult-locate)
+             ("C-c m" . consult-mode-command)
+             ("C-c s" . consult-line)
+             ("C-x r x" . consult-register)
+             ("C-x r b" . consult-bookmark)
+             ("M-g b" . consult-bookmark)
+             ("M-g g" . consult-goto-line)
+             ("M-g M-g" . consult-goto-line)
+             ("M-g o" . consult-outline)
+             ("M-g s" . consult-line)
+             ("M-g m" . consult-man)
+             ("M-g M" . consult-mark)
+             ("M-g K" . consult-git-grep)
+             ("M-g k" . consult-ripgrep)
+             ("M-g i" . consult-imenu)
+             ("M-g I" . consult-project-imenu)
+             ("M-g e" . consult-error)
+             ("M-s m" . consult-multi-occur)
+             ("M-s o" . consult-outline)
+             ("M-y" . consult-yank-pop)
+             ("C-s" . isearch-forward)
+             ("<help> a" . consult-apropos))
+
+      :custom ((consult-locate-command "locate --ignore-case --regexp ARG OPTS")
+               (consult-preview-key (kbd "`"))
+               (consult-config '((consult-mark :preview-key any))))
+
+      :init
+      (fset 'multi-occur #'consult-multi-occur)
+
+      :config
+      (defun jao-consult-project-root ()
+        (expand-file-name (or (jao-compilation-root) (vc-root-dir) "")))
+
+      (setq consult-project-root-function #'jao-consult-project-root)
+
+      (define-key consult-narrow-map (vconcat consult-narrow-key "?")
+        #'consult-narrow-help))
+   #+end_src
+* consultors
+*** notmuch
+    #+begin_src emacs-lisp
+      (jao-load-path "consult-notmuch")
+      (use-package consult-notmuch
+        :config
+        (add-to-list 'consult-config '(consult-notmuch :preview-key any)))
+    #+end_src
+*** recoll
+    #+begin_src emacs-lisp
+      (jao-load-path "consult-recoll")
+
+      (defun jao-recoll-format (title url mtype)
+        (let* ((u (replace-regexp-in-string "/home/jao/" "" url))
+               (u (replace-regexp-in-string "\\(doc\\|org/doc\\|var/mail\\)/" "" u)))
+          (format "%s (%s, %s)"
+                  title
+                  (propertize u 'face 'jao-themes-f00)
+                  (propertize mtype 'face 'jao-themes-f01))))
+
+      (use-package consult-recoll
+        :init (setq consult-recoll-open-fns
+                    '(("application/pdf" . jao-open-doc)
+                      ("message/rfc822" . jao-org-links-open-mail))
+                    consult-recoll-format-candidate #'jao-recoll-format)
+        :bind (("C-c R" . #'consult-recoll)))
+
+    #+end_src
+*** dh-diff hunks
+    #+begin_src emacs-lisp
+      (defun jao-consult--diff-lines (&optional backward)
+        (let ((candidates)
+              (width (length (number-to-string
+                              (line-number-at-pos (point-max)
+                                                  consult-line-numbers-widen)))))
+          (save-excursion
+            (while (ignore-errors (diff-hl-next-hunk backward))
+              (let* ((str (buffer-substring (line-beginning-position)
+                                            (line-end-position)))
+                     (no (line-number-at-pos (point)))
+                     (no (consult--line-number-prefix (point-marker) no width)))
+                (push (concat no str) candidates))))
+          (if backward candidates (nreverse candidates))))
+
+      (defun jao-consult-hunks ()
+        (interactive)
+        (let ((candidates (append (jao-consult--diff-lines)
+                                  (jao-consult--diff-lines t))))
+          (unless candidates (error "No changes!"))
+          (consult--jump
+           (consult--read "Go to hunk: " candidates
+                          :category 'consult--encode-location
+                          :sort nil
+                          :require-match t
+                          :lookup #'consult--line-match
+                          :preview (consult--preview-position)))))
+
+      (with-eval-after-load "consult"
+        (add-to-list 'consult-config '(jao-consult-hunks :preview-key any)))
+  #+end_src
+* embark
+*** packages
+    #+begin_src emacs-lisp
+      (use-package embark
+        :ensure t
+        :custom ((embark-quit-after-action nil)
+                 (prefix-help-command #'embark-prefix-help-command))
+        :bind (("C-;" . embark-act)
+               ("C-'" . embark-default-action)
+               (:map minibuffer-local-map
+                     (("C-'" . embark-default-action)
+                      ("C-," . embark-become)
+                      ("C-o" . embark-export)))))
+
+      (use-package embark-consult
+        :ensure t
+        :after (embark consult))
+
+      (with-eval-after-load 'consult
+        (with-eval-after-load 'embark
+          (require 'embark-consult)))
+    (require 'embark)
+    #+end_src
+*** embark action indicator
+    #+begin_src emacs-lisp
+      (defvar jao-embark--actions-buffer "*Embark Actions*")
+
+      (defvar jao-embark--default-display
+        `((,(regexp-quote jao-embark--actions-buffer)
+           (display-buffer-at-bottom)
+           (window-parameters (mode-line-format . none))
+           (window-height . fit-window-to-buffer))))
+
+      (setq jao-embark--excluded
+            '(embark-collect-snapshot embark-collect-live embark-export
+              embark-keymap-help embark-become embark-isearch nil))
+
+      (defun jao-embark--key-str (k)
+        (if (numberp k) (single-key-description k) (key-description k)))
+
+      (defun jao-embark--bind-desc (descs x prefix)
+        (let ((k (car x)) (c (cdr x)))
+          (cond ((keymapp c)
+                 (let ((cds (jao-embark--keymap-descs c (jao-embark--key-str k))))
+                   (cons (max (or (car cds) 0) (or (car descs) 0))
+                         (cons (max (or (cadr cds) 0) (or (cadr descs) 0))
+                               (append (cddr descs) (cddr cds))))))
+                ((memq c jao-embark--excluded) descs)
+                ((symbolp c)
+                 (let* ((desc (jao-embark--key-str k))
+                        (desc (format "%s%s" (or prefix "") desc))
+                        (doc (car (split-string
+                                   (or (ignore-errors (documentation c)) "")
+                                   "\n")))
+                        (fun (symbol-name c)))
+                   (cons (max (length desc) (car descs))
+                         (cons (max (length fun) (cadr descs))
+                               (cons (list desc fun doc) (cddr descs))))))
+                (t (message "i've skipped %S" x) descs))))
+
+      (defun jao-embark--keymap-descs (k prefix)
+        (seq-reduce `(lambda (descs x) (jao-embark--bind-desc descs x ,prefix))
+                    (cdr (keymap-canonicalize k)) '(0 0)))
+
+      (defun jao-embark--dstr (d)
+        (let ((s (cadr d))) (if (string-prefix-p "embark" s) "" s)))
+
+      (defun jao-embark--show-keymap (keymap &optional target)
+        (with-current-buffer (get-buffer-create jao-embark--actions-buffer)
+          (read-only-mode -1)
+          (setq-local cursor-type nil)
+          (delete-region (point-min) (point-max))
+          (let* ((descs (jao-embark--keymap-descs keymap ""))
+                 (fmt (format "%%-%ds  %%-%ds   %%s\n" (cadr descs) (car descs))))
+            (seq-each (lambda (desc)
+                        (insert (format fmt
+                                        (propertize (cadr desc) 'face 'jao-themes-f00)
+                                        (propertize (car desc) 'face 'embark-keybinding)
+                                        (propertize (caddr desc) 'face 'italic))))
+                      (seq-sort-by 'jao-embark--dstr 'string-greaterp (cddr descs))))
+          (if target (insert (format "\nAction for '%s'" target)) (delete-char -1))
+          (read-only-mode 1)
+          (let ((display-buffer-alist
+                 (append display-buffer-alist jao-embark--default-display)))
+            (pop-to-buffer (current-buffer) nil t))
+          (lambda ()
+            (embark-kill-buffer-and-window jao-embark--actions-buffer)
+            (when (or (bound-and-true-p selectrum-is-active)
+                      (and (boundp 'minicomp--input)
+                           (stringp minicomp--input)))
+              (select-window (minibuffer-window))))))
+
+      (setq embark-action-indicator  #'jao-embark--show-keymap
+            embark-become-indicator embark-action-indicator)
+
+    #+end_src
+*** org targets
+    #+begin_src emacs-lisp
+      (declare-function org-link-any-re "ol")
+      (declare-function org-open-link-from-string "ol")
+      (declare-function org-in-regexp "org-macs")
+
+      (defun jao-embark-targets--org-link ()
+        (when (derived-mode-p 'org-mode)
+          (when (org-in-regexp org-link-any-re)
+            (let ((lnk (match-string-no-properties 2)))
+              (if (string-match-p "https?://.+" (or lnk ""))
+                  (cons 'url lnk)
+                (cons 'org-link (match-string-no-properties 0)))))))
+
+      (embark-define-keymap jao-embark-targets-org-link-map
+        "Actions for org links"
+        ((kbd "RET") org-open-link-from-string))
+
+      (add-to-list 'embark-target-finders #'jao-embark-targets--org-link)
+      (add-to-list 'embark-keymap-alist '(org-link . jao-embark-targets-org-link-map))
+    #+end_src
+*** url targets
+    #+begin_src emacs-lisp
+      (declare-function w3m-anchor "w3m")
+
+      (defun jao-embark-targets--w3m-anchor ()
+        (when (not (region-active-p))
+          (when-let ((url (or (and (derived-mode-p 'w3m-mode)
+                                   (or (w3m-anchor) w3m-current-url))
+                              (and (derived-mode-p 'eww-mode)
+                                   (or (thing-at-point 'url) (eww-current-url)))
+                              (jao-url-around-point))))
+            (when (string-match-p "^https?.*" url)
+              (cons 'url url)))))
+
+      (add-to-list 'embark-target-finders #'jao-embark-targets--w3m-anchor)
+
+      (defun jao-embark-url (url)
+        "Browse URL, externally if we're already in emacs-w3m"
+        (if (derived-mode-p 'w3m-mode 'eww-mode)
+            (jao-browse-with-external-browser url)
+          (browse-url url)))
+
+      (define-key embark-url-map (kbd "RET") #'jao-embark-url)
+      (define-key embark-url-map (kbd "e") #'jao-eww-browse-url)
+      (define-key embark-url-map (kbd "f") #'browse-url-firefox)
+      (define-key embark-url-map (kbd "m") 'jao-browse-with-external-browser)
+    #+end_src
+*** video url targets
+    #+begin_src emacs-lisp
+      (defvar jao-embark-targets-video-sites
+        '("youtu.be" "youtube.com" "blip.tv" "vimeo.com" "infoq.com"))
+
+      (defun jao-embark--video-url-rx (&optional sites)
+        (format "^https?://\\(?:www\\.\\)?%s/.+"
+                (regexp-opt (or sites jao-embark-targets-video-sites) t)))
+
+      (defvar jao-embark-targets-video-url-rx (jao-embark--video-url-rx)
+        "A regular expression matching URLs that point to video streams")
+
+      (defun jao-embark-targets--refine-url (url)
+        (if (string-match-p jao-embark-targets-video-url-rx url)
+            (cons 'video-url url)
+          (cons 'url url)))
+
+      (defun jao-embark-targets--play-video (player url)
+        (interactive "sURL: ")
+        (let ((cmd (format "%s %s" player (shell-quote-argument url))))
+          (start-process-shell-command player nil cmd)))
+
+      (defun jao-embark-targets-mpv (&optional url)
+        "Play video stream with mpv"
+        (interactive "sURL: ")
+        (jao-embark-targets--play-video "mpv" url))
+
+      (defun jao-embark-targets-vlc (&optional url)
+        "Play video stream with vlc"
+        (interactive "sURL: ")
+        (jao-embark-targets--play-video "vlc" url))
+
+      (embark-define-keymap jao-embark-targets-video-url-map
+        "Actions on URLs pointing to remote video streams."
+        :parent embark-url-map
+        ("RET" jao-embark-targets-mpv)
+        ("v" jao-embark-targets-vlc))
+
+      (add-to-list 'embark-transformer-alist '(url . jao-embark-targets--refine-url))
+      (add-to-list 'embark-keymap-alist '(video-url . jao-embark-targets-video-url-map))
+    #+end_src
+*** spotify
+    #+begin_src emacs-lisp
+      (with-eval-after-load "consult-spotify"
+        (embark-define-keymap spotify-item-keymap
+          "Actions for Spotify search results"
+          ("y" espotify-yank-candidate-url)
+          ("a" espotify-play-candidate-album)
+          ("h" espotify-show-candidate-info))
+
+        (add-to-list 'embark-keymap-alist
+                     '(spotify-search-item . spotify-item-keymap)))
+    #+end_src
diff --git a/consult.org b/consult.org
deleted file mode 100644
index 76ebee7..0000000
--- a/consult.org
+++ /dev/null
@@ -1,405 +0,0 @@
-#+title: Completion configuration using selectrum, consult and friends
-
-* completion styles
-  #+begin_src emacs-lisp
-    (setq completion-styles '(basic partial-completion emacs22))
-  #+end_src
-* orderless
-  #+begin_src emacs-lisp :load no
-    (use-package orderless
-      :ensure t
-      :custom ((orderless-component-separator "[ -/]+")
-               (orderless-matching-styles
-                '(orderless-literal orderless-regexp orderless-initialism)))
-      :bind
-      ((:map minibuffer-local-completion-map ("SPC" . self-insert-command))))
-  #+end_src
-* selectrum
-  #+begin_src emacs-lisp
-    (use-package selectrum
-      :ensure t
-      :init
-      (defun jao-selectrum--ord-refine (&rest args)
-        (let ((completion-styles '(orderless)))
-          (apply #'selectrum-refine-candidates-using-completions-styles args)))
-
-      (defun jao-selectrum-orderless ()
-        (interactive)
-        (setq selectrum-refine-candidates-function #'jao-selectrum--ord-refine)
-        (setq selectrum-highlight-candidates-function #'orderless-highlight-matches)
-        (setq orderless-skip-highlighting (lambda () selectrum-is-active)))
-
-
-      :config
-      ;; https://github.com/raxod502/selectrum/wiki/Ido,-icomplete(fido)-emulation
-      (defun selectrum-fido-backward-updir ()
-        "Delete char before or go up directory, like `ido-mode'."
-        (interactive)
-        (if (and (eq (char-before) ?/)
-                 (eq (selectrum--get-meta 'category) 'file))
-            (save-excursion
-              (goto-char (1- (point)))
-              (when (search-backward "/" (point-min) t)
-                (delete-region (1+ (point)) (point-max))))
-          (call-interactively 'backward-delete-char)))
-
-      (defun selectrum-fido-delete-char ()
-        "Delete char or maybe call `dired', like `ido-mode'."
-        (interactive)
-        (let ((end (point-max)))
-          (if (or (< (point) end) (not (eq (selectrum--get-meta 'category) 'file)))
-              (call-interactively 'delete-char)
-            (dired (file-name-directory (minibuffer-contents)))
-            (exit-minibuffer))))
-
-      (defun selectrum-fido-ret ()
-        "Exit minibuffer or enter directory, like `ido-mode'."
-        (interactive)
-        (let* ((dir (and (eq (selectrum--get-meta 'category) 'file)
-                         (file-name-directory (minibuffer-contents))))
-               (current (selectrum-get-current-candidate))
-               (probe (and dir current
-                           (expand-file-name (directory-file-name current) dir))))
-          (if (and probe (file-directory-p probe) (not (string= current "./")))
-              (selectrum-insert-current-candidate)
-            (selectrum-select-current-candidate))))
-
-      ;; (define-key selectrum-minibuffer-map (kbd "RET") 'selectrum-fido-ret)
-      (define-key selectrum-minibuffer-map (kbd "DEL") 'selectrum-fido-backward-updir)
-      (define-key selectrum-minibuffer-map (kbd "C-d") 'selectrum-fido-delete-char)
-
-      :custom ((selectrum-complete-in-buffer t)
-               ;; (selectrum-display-action '(display-buffer-at-bottom))
-               (selectrum-extend-current-candidate-highlight t)
-               (selectrum-fix-vertical-window-height nil)
-               (selectrum-max-window-height 20)
-               (selectrum-show-indices nil)
-               (selectrum-count-style 'current/matches))
-      :bind (("C-R" . selectrum-repeat)))
-  #+end_src
-* marginalia
-  #+begin_src emacs-lisp
-    (use-package marginalia
-      :ensure t
-      :bind (:map minibuffer-local-map ("C-M-a" . marginalia-cycle))
-
-      :custom ((marginalia-align-offset 1)
-               (marginalia-margin-threshold 200)
-               (marginalia-separator-threshold 120)
-               (marginalia-truncate-width 80)
-               (marginalia-annotators
-                '(marginalia-annotators-heavy marginalia-annotators-light nil))))
-   #+end_src
-* consult
-  #+begin_src emacs-lisp
-    (use-package consult
-      :ensure t
-      :bind (("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-c b" . project-find-file)
-             ("C-c B" . bookmark-set)
-             ("C-c h" . consult-history)
-             ("C-c i" . consult-imenu)
-             ("C-c k" . consult-ripgrep)
-             ("C-c K" . consult-git-grep)
-             ("C-c l" . consult-locate)
-             ("C-c m" . consult-mode-command)
-             ("C-c s" . consult-line)
-             ("C-x r x" . consult-register)
-             ("C-x r b" . consult-bookmark)
-             ("M-g b" . consult-bookmark)
-             ("M-g g" . consult-goto-line)
-             ("M-g M-g" . consult-goto-line)
-             ("M-g o" . consult-outline)
-             ("M-g s" . consult-line)
-             ("M-g m" . consult-man)
-             ("M-g M" . consult-mark)
-             ("M-g K" . consult-git-grep)
-             ("M-g k" . consult-ripgrep)
-             ("M-g i" . consult-imenu)
-             ("M-g I" . consult-project-imenu)
-             ("M-g e" . consult-error)
-             ("M-s m" . consult-multi-occur)
-             ("M-s o" . consult-outline)
-             ("M-y" . consult-yank-pop)
-             ("C-s" . isearch-forward)
-             ("<help> a" . consult-apropos))
-
-      :custom ((consult-locate-command "locate --ignore-case --regexp ARG OPTS")
-               (consult-preview-key (kbd "`"))
-               (consult-config '((consult-mark :preview-key any))))
-
-      :init
-      (fset 'multi-occur #'consult-multi-occur)
-
-      :config
-      (defun jao-consult-project-root ()
-        (expand-file-name (or (jao-compilation-root) (vc-root-dir) "")))
-
-      (setq consult-project-root-function #'jao-consult-project-root)
-
-      (define-key consult-narrow-map (vconcat consult-narrow-key "?")
-        #'consult-narrow-help))
-   #+end_src
-* consultors
-*** notmuch
-    #+begin_src emacs-lisp
-      (jao-load-path "consult-notmuch")
-      (use-package consult-notmuch
-        :config
-        (add-to-list 'consult-config '(consult-notmuch :preview-key any)))
-    #+end_src
-*** recoll
-    #+begin_src emacs-lisp
-      (jao-load-path "consult-recoll")
-
-      (defun jao-recoll-format (title url mtype)
-        (let* ((u (replace-regexp-in-string "/home/jao/" "" url))
-               (u (replace-regexp-in-string "\\(doc\\|org/doc\\|var/mail\\)/" "" u)))
-          (format "%s (%s, %s)"
-                  title
-                  (propertize u 'face 'jao-themes-f00)
-                  (propertize mtype 'face 'jao-themes-f01))))
-
-      (use-package consult-recoll
-        :init (setq consult-recoll-open-fns
-                    '(("application/pdf" . jao-open-doc)
-                      ("message/rfc822" . jao-org-links-open-mail))
-                    consult-recoll-format-candidate #'jao-recoll-format)
-        :bind (("C-c R" . #'consult-recoll)))
-
-    #+end_src
-*** dh-diff hunks
-    #+begin_src emacs-lisp
-      (defun jao-consult--diff-lines (&optional backward)
-        (let ((candidates)
-              (width (length (number-to-string
-                              (line-number-at-pos (point-max)
-                                                  consult-line-numbers-widen)))))
-          (save-excursion
-            (while (ignore-errors (diff-hl-next-hunk backward))
-              (let* ((str (buffer-substring (line-beginning-position)
-                                            (line-end-position)))
-                     (no (line-number-at-pos (point)))
-                     (no (consult--line-number-prefix (point-marker) no width)))
-                (push (concat no str) candidates))))
-          (if backward candidates (nreverse candidates))))
-
-      (defun jao-consult-hunks ()
-        (interactive)
-        (let ((candidates (append (jao-consult--diff-lines)
-                                  (jao-consult--diff-lines t))))
-          (unless candidates (error "No changes!"))
-          (consult--jump
-           (consult--read "Go to hunk: " candidates
-                          :category 'consult--encode-location
-                          :sort nil
-                          :require-match t
-                          :lookup #'consult--line-match
-                          :preview (consult--preview-position)))))
-
-      (with-eval-after-load "consult"
-        (add-to-list 'consult-config '(jao-consult-hunks :preview-key any)))
-  #+end_src
-* embark
-*** packages
-    #+begin_src emacs-lisp
-      (use-package embark
-        :ensure t
-        :custom ((embark-quit-after-action nil)
-                 (prefix-help-command #'embark-prefix-help-command))
-        :bind (("C-;" . embark-act)
-               ("C-'" . embark-default-action)
-               (:map minibuffer-local-map
-                     (("C-'" . embark-default-action)
-                      ("C-," . embark-become)
-                      ("C-o" . embark-export)))))
-
-      (use-package embark-consult
-        :ensure t
-        :after (embark consult))
-
-      (with-eval-after-load 'consult
-        (with-eval-after-load 'embark
-          (require 'embark-consult)))
-    (require 'embark)
-    #+end_src
-*** embark action indicator
-    #+begin_src emacs-lisp
-      (defvar jao-embark--actions-buffer "*Embark Actions*")
-
-      (defvar jao-embark--default-display
-        `((,(regexp-quote jao-embark--actions-buffer)
-           (display-buffer-at-bottom)
-           (window-parameters (mode-line-format . none))
-           (window-height . fit-window-to-buffer))))
-
-      (setq jao-embark--excluded
-            '(embark-collect-snapshot embark-collect-live embark-export
-              embark-keymap-help embark-become embark-isearch nil))
-
-      (defun jao-embark--key-str (k)
-        (if (numberp k) (single-key-description k) (key-description k)))
-
-      (defun jao-embark--bind-desc (descs x prefix)
-        (let ((k (car x)) (c (cdr x)))
-          (cond ((keymapp c)
-                 (let ((cds (jao-embark--keymap-descs c (jao-embark--key-str k))))
-                   (cons (max (or (car cds) 0) (or (car descs) 0))
-                         (cons (max (or (cadr cds) 0) (or (cadr descs) 0))
-                               (append (cddr descs) (cddr cds))))))
-                ((memq c jao-embark--excluded) descs)
-                ((symbolp c)
-                 (let* ((desc (jao-embark--key-str k))
-                        (desc (format "%s%s" (or prefix "") desc))
-                        (doc (car (split-string
-                                   (or (ignore-errors (documentation c)) "")
-                                   "\n")))
-                        (fun (symbol-name c)))
-                   (cons (max (length desc) (car descs))
-                         (cons (max (length fun) (cadr descs))
-                               (cons (list desc fun doc) (cddr descs))))))
-                (t (message "i've skipped %S" x) descs))))
-
-      (defun jao-embark--keymap-descs (k prefix)
-        (seq-reduce `(lambda (descs x) (jao-embark--bind-desc descs x ,prefix))
-                    (cdr (keymap-canonicalize k)) '(0 0)))
-
-      (defun jao-embark--dstr (d)
-        (let ((s (cadr d))) (if (string-prefix-p "embark" s) "" s)))
-
-      (defun jao-embark--show-keymap (keymap &optional target)
-        (with-current-buffer (get-buffer-create jao-embark--actions-buffer)
-          (read-only-mode -1)
-          (setq-local cursor-type nil)
-          (delete-region (point-min) (point-max))
-          (let* ((descs (jao-embark--keymap-descs keymap ""))
-                 (fmt (format "%%-%ds  %%-%ds   %%s\n" (cadr descs) (car descs))))
-            (seq-each (lambda (desc)
-                        (insert (format fmt
-                                        (propertize (cadr desc) 'face 'jao-themes-f00)
-                                        (propertize (car desc) 'face 'embark-keybinding)
-                                        (propertize (caddr desc) 'face 'italic))))
-                      (seq-sort-by 'jao-embark--dstr 'string-greaterp (cddr descs))))
-          (if target (insert (format "\nAction for '%s'" target)) (delete-char -1))
-          (read-only-mode 1)
-          (let ((display-buffer-alist
-                 (append display-buffer-alist jao-embark--default-display)))
-            (pop-to-buffer (current-buffer) nil t))
-          (lambda ()
-            (embark-kill-buffer-and-window jao-embark--actions-buffer)
-            (when selectrum-is-active (select-window (minibuffer-window))))))
-
-      (setq embark-action-indicator  #'jao-embark--show-keymap
-            embark-become-indicator embark-action-indicator)
-
-    #+end_src
-*** org targets
-    #+begin_src emacs-lisp
-      (declare-function org-link-any-re "ol")
-      (declare-function org-open-link-from-string "ol")
-      (declare-function org-in-regexp "org-macs")
-
-      (defun jao-embark-targets--org-link ()
-        (when (derived-mode-p 'org-mode)
-          (when (org-in-regexp org-link-any-re)
-            (let ((lnk (match-string-no-properties 2)))
-              (if (string-match-p "https?://.+" (or lnk ""))
-                  (cons 'url lnk)
-                (cons 'org-link (match-string-no-properties 0)))))))
-
-      (embark-define-keymap jao-embark-targets-org-link-map
-        "Actions for org links"
-        ((kbd "RET") org-open-link-from-string))
-
-      (add-to-list 'embark-target-finders #'jao-embark-targets--org-link)
-      (add-to-list 'embark-keymap-alist '(org-link . jao-embark-targets-org-link-map))
-    #+end_src
-*** url targets
-    #+begin_src emacs-lisp
-      (declare-function w3m-anchor "w3m")
-
-      (defun jao-embark-targets--w3m-anchor ()
-        (when (not (region-active-p))
-          (when-let ((url (or (and (derived-mode-p 'w3m-mode)
-                                   (or (w3m-anchor) w3m-current-url))
-                              (and (derived-mode-p 'eww-mode)
-                                   (or (thing-at-point 'url) (eww-current-url)))
-                              (jao-url-around-point))))
-            (when (string-match-p "^https?.*" url)
-              (cons 'url url)))))
-
-      (add-to-list 'embark-target-finders #'jao-embark-targets--w3m-anchor)
-
-      (defun jao-embark-url (url)
-        "Browse URL, externally if we're already in emacs-w3m"
-        (if (derived-mode-p 'w3m-mode 'eww-mode)
-            (jao-browse-with-external-browser url)
-          (browse-url url)))
-
-      (define-key embark-url-map (kbd "RET") #'jao-embark-url)
-      (define-key embark-url-map (kbd "e") #'jao-eww-browse-url)
-      (define-key embark-url-map (kbd "f") #'browse-url-firefox)
-      (define-key embark-url-map (kbd "m") 'jao-browse-with-external-browser)
-    #+end_src
-*** video url targets
-    #+begin_src emacs-lisp
-      (defvar jao-embark-targets-video-sites
-        '("youtu.be" "youtube.com" "blip.tv" "vimeo.com" "infoq.com"))
-
-      (defun jao-embark--video-url-rx (&optional sites)
-        (format "^https?://\\(?:www\\.\\)?%s/.+"
-                (regexp-opt (or sites jao-embark-targets-video-sites) t)))
-
-      (defvar jao-embark-targets-video-url-rx (jao-embark--video-url-rx)
-        "A regular expression matching URLs that point to video streams")
-
-      (defun jao-embark-targets--refine-url (url)
-        (if (string-match-p jao-embark-targets-video-url-rx url)
-            (cons 'video-url url)
-          (cons 'url url)))
-
-      (defun jao-embark-targets--play-video (player url)
-        (interactive "sURL: ")
-        (let ((cmd (format "%s %s" player (shell-quote-argument url))))
-          (start-process-shell-command player nil cmd)))
-
-      (defun jao-embark-targets-mpv (&optional url)
-        "Play video stream with mpv"
-        (interactive "sURL: ")
-        (jao-embark-targets--play-video "mpv" url))
-
-      (defun jao-embark-targets-vlc (&optional url)
-        "Play video stream with vlc"
-        (interactive "sURL: ")
-        (jao-embark-targets--play-video "vlc" url))
-
-      (embark-define-keymap jao-embark-targets-video-url-map
-        "Actions on URLs pointing to remote video streams."
-        :parent embark-url-map
-        ("RET" jao-embark-targets-mpv)
-        ("v" jao-embark-targets-vlc))
-
-      (add-to-list 'embark-transformer-alist '(url . jao-embark-targets--refine-url))
-      (add-to-list 'embark-keymap-alist '(video-url . jao-embark-targets-video-url-map))
-    #+end_src
-*** spotify
-    #+begin_src emacs-lisp
-      (with-eval-after-load "consult-spotify"
-        (embark-define-keymap spotify-item-keymap
-          "Actions for Spotify search results"
-          ("y" espotify-yank-candidate-url)
-          ("a" espotify-play-candidate-album)
-          ("h" espotify-show-candidate-info))
-
-      (add-to-list 'embark-keymap-alist
-                   '(spotify-search-item . spotify-item-keymap)))
-    #+end_src
-* startup
-  #+begin_src emacs-lisp
-    (marginalia-mode 1)
-    (selectrum-mode 1)
-    (jao-selectrum-orderless)
-  #+end_src
diff --git a/init.org b/init.org
index dbf4bff..33b718f 100644
--- a/init.org
+++ b/init.org
@@ -850,89 +850,6 @@
         :bind (("s-n" . jao-hydra-ednc/body)
                ("H-s-n" . jao-hydra-ednc/body)))
     #+end_src
-* Completion
-*** company
-    #+begin_src emacs-lisp
-      (use-package company
-        :ensure t
-        :custom
-        ((company-global-modes '(clojure-mode
-                                 clojurec-mode
-                                 emacs-lisp-mode
-                                 eshell-mode
-                                 lisp-interaction-mode
-                                 haskell-mode
-                                 message-mode
-                                 org-mode
-                                 scheme-mode))
-         (company-idle-delay 0.15)
-         (company-lighter "")
-         (company-lighter-base "")
-         (company-show-numbers nil)
-         (company-tooltip-limit 15)
-         (company-tooltip-align-annotations t)
-         (company-transformers '(company-sort-by-occurrence)))
-
-        :config
-        ;; Prevent non-matching input (which will dismiss the completions
-        ;; menu), but only if the user interacts explicitly with Company.
-        (setq company-require-match #'company-explicit-action-p)
-
-        (defun jao-complete-at-point ()
-          "Complete using company unless we're in the minibuffer."
-          (interactive)
-          (if (window-minibuffer-p) (completion-at-point) (company-manual-begin)))
-
-        :bind (([remap completion-at-point] . #'jao-complete-at-point)
-               ([remap complete-symbol] . #'jao-complete-at-point)
-
-               ;; The following are keybindings that take effect whenever
-               ;; the completions menu is visible, even if the user has not
-               ;; explicitly interacted with Company.
-               :map company-active-map
-
-               ([remap scroll-up-command] . nil)
-               ([remap scroll-down-command] . nil)
-
-               ;; Make TAB always complete the current selection, instead of
-               ;; only completing a common prefix.
-               ("<tab>" . #'company-complete-selection)
-               ("TAB" . #'company-complete-selection)
-
-               ("C-h" . #'company-show-doc-buffer)
-               ("M-." . #'company-show-location)
-
-               ;; The following are keybindings that only take effect
-               ;; if not in eshell.  Note that `:map' from above is
-               ;; "sticky", and applies also below.
-               ;; Another interesting :filter  (company-explicit-action-p)
-
-               :filter (or (not (derived-mode-p 'eshell-mode))
-                           (company-explicit-action-p))
-               ("<return>" . #'company-complete-selection)
-               ("RET" . #'company-complete-selection))
-
-        :bind* (;; The default keybinding for `completion-at-point' and
-                ;; `complete-symbol' is M-TAB or equivalently C-M-i. We
-                ;; already remapped those bindings to `company-manual-begin'
-                ;; above. Here we make sure that they definitely invoke
-                ;; `company-manual-begin' even if a minor mode binds M-TAB
-                ;; directly.
-                ("M-TAB" . #'jao-complete-at-point))
-
-      :diminish)
-
-      (use-package company-math :ensure t :after company)
-
-      (global-company-mode 1)
-
-    #+end_src
-*** completion engine
-    We can load either [[./consult.org][consult.org]] or [[./attic/counsel.org][counsel.org]] to configure
-    completion engines:
-    #+begin_src emacs-lisp
-      (jao-load-org "consult")
-    #+end_src
 * Calendar, diary, weather
 *** Diary
     #+BEGIN_SRC emacs-lisp
@@ -1136,6 +1053,10 @@
 
       #+END_SRC
 * General editing
+*** Completion
+    #+begin_src emacs-lisp
+      (jao-load-org "completion")
+    #+end_src
 *** Long lines
     [[https://200ok.ch/posts/2020-09-29_comprehensive_guide_on_handling_long_lines_in_emacs.html][Comprehensive guide on handling long lines in Emacs - 200ok]]
     #+begin_src emacs-lisp
diff --git a/lib/themes/jao-themes.el b/lib/themes/jao-themes.el
index a78d890..6fa66c0 100644
--- a/lib/themes/jao-themes.el
+++ b/lib/themes/jao-themes.el
@@ -822,6 +822,8 @@
             (mm-uu-extract (p hilite) ex)
             (minibuffer-line (p f00))
             (minibuffer-prompt (p f00))
+            (minicomp-group-title (p dimm))
+            (minicomp-group-separator (p dimm) :strike-through "grey80")
             (mode-line-buffer-id nbf (c nil nil))
             (mode-line-emphasis (p warning))
             (mode-line-highlight (~ mode-line))
diff --git a/readme.org b/readme.org
index 3e621ea..9e2b7fd 100644
--- a/readme.org
+++ b/readme.org
@@ -62,7 +62,7 @@
 - [[./init.org][init.org]]: main configuration as a literate org file; it uses
   (besides lots of packages), many of my libraries in [[./lib][lib]], and loads
   on demand the other org files below.
-- [[./consult.org][consult.org]]: completion setup using selectrum, consult and friends.
+- [[./completion.org][completion.org]]: completion setup using company, consult and friends.
 - [[./org.org][org.org]] org mode configuration.
 - [[./blog.org][blog.org]]: blogging using org-static-blog.
 - [[./gnus.org][gnus.org]]: tangled to gnus.el automatically by init.org, so that it's
-- 
cgit v1.2.3