jao-custom-completion.el 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. ;; -*- lexical-binding: t; -*-
  2. ;;; builtin completion
  3. (setq tab-always-indent 'complete
  4. read-extended-command-predicate #'command-completion-default-include-p
  5. completion-auto-select 'second-tab
  6. completion-auto-help 'always
  7. completion-category-defaults nil
  8. completion-cycle-threshold 4
  9. completions-detailed t
  10. completions-header-format nil
  11. completion-ignore-case t
  12. completion-show-help nil
  13. completion-show-inline-help t
  14. completions-format 'one-column
  15. completion-styles '(basic substring partial-completion emacs22)
  16. completion-category-overrides
  17. '((file (styles partial-completion))
  18. (command (styles initials substring partial-completion))
  19. (symbol (styles initials substring partial-completion))
  20. (variable (styles initials substring partial-completion)))
  21. completion-wrap-movement t)
  22. ;;; crm indicator
  23. (defun jao-completion--crm-indicator (args)
  24. "Add prompt indicator to `completing-read-multiple' filter ARGS."
  25. (cons (concat "[CRM] " (car args)) (cdr args)))
  26. (advice-add #'completing-read-multiple
  27. :filter-args #'jao-completion--crm-indicator)
  28. ;;; orderless
  29. (use-package orderless
  30. :ensure t
  31. :demand t
  32. :config
  33. (orderless-define-completion-style orderless+initialism
  34. (orderless-matching-styles '(orderless-initialism
  35. orderless-prefixes
  36. orderless-literal
  37. orderless-regexp)))
  38. (defvar jao-orderless-overrides
  39. '((file (styles partial-completion orderless))
  40. (command (styles orderless+initialism))))
  41. (setq orderless-matching-styles
  42. '(orderless-literal orderless-regexp orderless-prefixes)))
  43. ;;; marginalia
  44. (use-package marginalia
  45. :ensure t
  46. :bind (:map minibuffer-local-map ("C-M-a" . marginalia-cycle))
  47. :custom ((marginalia-align 'left)
  48. (marginalia-align-offset 1)
  49. (marginalia-field-width 200)
  50. (marginalia-annotators
  51. '(marginalia-annotators-heavy marginalia-annotators-light nil))
  52. (marginalia-separator " ")))
  53. (marginalia-mode 1)
  54. ;;; vertico
  55. (use-package vertico
  56. :ensure t
  57. :init
  58. (defvar jao-vertico-reverse t)
  59. (setq vertico-count 20
  60. vertico-cycle t
  61. vertico-resize t
  62. vertico-multiform-categories nil
  63. vertico-multiform-commands
  64. `((".*"
  65. (completion-styles orderless basic)
  66. (completion-category-overrides . ,jao-orderless-overrides)))
  67. vertico-buffer-display-action
  68. `(display-buffer-below-selected (window-height . 0.5)))
  69. (dolist (c '(completion-at-point complete-symbol indent-for-tab-command))
  70. (let ((s `(,c buffer (vertico-resize) (jao-vertico-reverse))))
  71. (add-to-list 'vertico-multiform-commands s)))
  72. :config
  73. (defun jao-vertico--display (fun lines)
  74. (if (not jao-vertico-reverse)
  75. (funcall fun lines)
  76. (move-overlay vertico--candidates-ov (point-min) (point-min))
  77. (overlay-put vertico--candidates-ov 'after-string (apply #'concat lines))
  78. (vertico--resize-window (length lines))))
  79. (advice-add 'vertico--display-candidates :around #'jao-vertico--display))
  80. (use-package vertico-directory
  81. :after vertico
  82. :bind (:map vertico-map (("RET" . vertico-directory-enter)
  83. ("M-<backspace>" . vertico-directory-delete-word)
  84. ("<backspace>" . vertico-directory-delete-char)
  85. ("DEL" . vertico-directory-delete-char))))
  86. (vertico-mode)
  87. (vertico-multiform-mode)
  88. ;;; consult
  89. ;;;; package
  90. (use-package consult
  91. :ensure t
  92. :bind (("C-x M-:" . consult-complex-command)
  93. ("C-x b" . consult-buffer)
  94. ("C-x C-b" . switch-to-buffer)
  95. ("C-x 4 b" . consult-buffer-other-window)
  96. ("C-c b" . project-find-file)
  97. ("C-c h" . nil)
  98. ("C-c i" . consult-imenu)
  99. ("C-c I" . consult-project-imenu)
  100. ("C-h I" . consult-info)
  101. ;; ("C-c o" . consult-outline)
  102. ("C-c k" . consult-ripgrep)
  103. ("C-c L" . consult-locate)
  104. ("C-c s" . consult-line)
  105. ("C-x r x" . consult-register)
  106. ("C-x r b" . consult-bookmark)
  107. ("C-x C-f" . jao-find-file)
  108. ("M-g b" . consult-bookmark)
  109. ("M-g m" . consult-mark)
  110. ("M-g e" . consult-error)
  111. ("M-s m" . consult-multi-occur)
  112. ("M-y" . consult-yank-pop)
  113. ("C-s" . isearch-forward)
  114. ("<help> a" . consult-apropos))
  115. :custom ((consult-preview-key (kbd "`")))
  116. :init
  117. (fset 'multi-occur #'consult-multi-occur)
  118. (setq org-refile-use-outline-path t
  119. org-imenu-depth 7)
  120. :config
  121. (defun jao-consult--completion-in-region (&rest args)
  122. (apply (if (and (not (bound-and-true-p corfu-mode))
  123. (not (bound-and-true-p company-mode))
  124. (bound-and-true-p vertico-mode))
  125. #'consult-completion-in-region
  126. #'completion--in-region)
  127. args))
  128. (setq completion-in-region-function #'jao-consult--completion-in-region)
  129. (defun jao-find-file (arg)
  130. (interactive "P")
  131. (call-interactively (if arg 'consult-file-externally 'find-file)))
  132. (define-key consult-narrow-map (vconcat consult-narrow-key "?")
  133. #'consult-narrow-help)
  134. (with-eval-after-load "esh-mode"
  135. (define-key eshell-mode-map (kbd "C-c h") #'consult-history))
  136. (with-eval-after-load "comint"
  137. (define-key comint-mode-map (kbd "C-c h") #'consult-history))
  138. (consult-customize consult-mark :preview-key 'any)
  139. (add-hook 'completion-list-mode-hook #'consult-preview-at-point-mode))
  140. ;;;; consult-dir
  141. ;; (use-package consult-dir
  142. ;; :ensure t
  143. ;; :bind (("C-x C-d" . consult-dir)
  144. ;; :map minibuffer-local-completion-map
  145. ;; (("C-x C-d" . consult-dir)
  146. ;; ("C-x C-j" . consult-dir-jump-file))))
  147. ;;;; narrow helpers
  148. (defvar jao-consult-narrow nil)
  149. (defun jao-consult-initial-narrow ()
  150. (when-let (c (cond ((eq this-command #'consult-buffer)
  151. (cdr (assoc (jao-afio-frame-name) jao-consult-narrow)))
  152. ((eq this-command #'consult-mode-command) ?m)))
  153. (setq unread-command-events (append unread-command-events `(,c 32)))))
  154. (add-hook 'minibuffer-setup-hook #'jao-consult-initial-narrow)
  155. (defmacro jao-consult--mode-buffers (&rest modes)
  156. `(lambda ()
  157. (seq-map #'buffer-name
  158. (seq-filter (lambda (b)
  159. (with-current-buffer b
  160. (derived-mode-p ,@modes)))
  161. (buffer-list)))))
  162. (defun jao-consult-add-buffer-source (src &optional aframe key)
  163. (add-to-list 'consult-buffer-sources src t)
  164. (when (and aframe key)
  165. (add-to-list 'jao-consult-narrow (cons aframe key))))
  166. ;;; embark
  167. ;;;; package
  168. (use-package embark
  169. :ensure t
  170. :demand t
  171. :init
  172. (setq embark-quit-after-action nil
  173. embark-indicators '(embark-mixed-indicator
  174. ;; embark-minimal-indicator
  175. embark-highlight-indicator
  176. embark-isearch-highlight-indicator)
  177. embark-mixed-indicator-both t
  178. embark-mixed-indicator-delay 1
  179. embark-verbose-indicator-buffer-sections '(bindings)
  180. embark-verbose-indicator-excluded-commands
  181. '(embark-become embark-export embark-collect)
  182. embark-verbose-indicator-nested t
  183. embark-verbose-indicator-display-action
  184. '((display-buffer-at-bottom)
  185. (window-parameters (mode-line-format . none))
  186. (window-height . fit-window-to-buffer)))
  187. ;; (setq prefix-help-command #'describe-prefix-bindings)
  188. ;; (add-to-list 'vertico-multiform-categories '(embark-keybinding grid))
  189. :bind (("C-;" . embark-act)
  190. ("C-c ;" . embark-act)
  191. ("C-'" . embark-dwim)
  192. ("C-c '" . embark-dwim)
  193. (:map minibuffer-local-map
  194. (("C-'" . embark-dwim)
  195. ("C-c '" . embark-dwim)
  196. ("C-," . embark-become)
  197. ("C-c ," . embark-become)
  198. ("C-o" . embark-export)))))
  199. (use-package embark-consult
  200. :ensure t
  201. :after (embark consult))
  202. (with-eval-after-load 'consult
  203. (with-eval-after-load 'embark
  204. (require 'embark-consult)))
  205. ;;;; randomsig
  206. (defun jao-random-sig-read (_ignored)
  207. "Import region as signature and edit it."
  208. (randomsig-message-read-sig t))
  209. (define-key embark-region-map "m" #'jao-random-sig-read)
  210. (define-key embark-region-map "M" #'apply-macro-to-region-lines)
  211. ;;;; dict/say
  212. (defun jao-say (&optional word)
  213. "Isn't it nice to have a computer that can talk to you?"
  214. (interactive "sWhat? ")
  215. (shell-command-to-string (format "say %s" word))
  216. "")
  217. (define-key embark-identifier-map "D" #'dictionary-search)
  218. (define-key embark-identifier-map "S" #'jao-say)
  219. ;;;; org targets
  220. (declare-function org-link-any-re "ol")
  221. (declare-function org-open-link-from-string "ol")
  222. (declare-function org-in-regexp "org-macs")
  223. (defun jao-embark-targets--org-link ()
  224. (when (derived-mode-p 'org-mode)
  225. (let ((lnk (org-element-property :raw-link (org-element-context))))
  226. (and lnk (cons 'org-link lnk)))))
  227. (defun jao-embark-targets--gl-org-link ()
  228. (when (org-in-regexp org-link-bracket-re)
  229. (cons 'gl-org-link (match-string-no-properties 0))))
  230. (defvar jao-embark-targets-gl-org-link-map
  231. (define-keymap "RET" #'org-open-at-point-global))
  232. (defvar jao-embark-targets-org-link-map
  233. (define-keymap "RET" #'org-open-link-from-string))
  234. (add-to-list 'embark-target-finders #'jao-embark-targets--gl-org-link)
  235. (add-to-list 'embark-keymap-alist
  236. '(gl-org-link . jao-embark-targets-gl-org-link-map))
  237. (add-to-list 'embark-target-finders #'jao-embark-targets--org-link)
  238. (add-to-list 'embark-keymap-alist
  239. '(org-link . jao-embark-targets-org-link-map))
  240. ;;;; url targets
  241. (declare-function w3m-anchor "w3m")
  242. (defun jao-embark-targets--w3m-anchor ()
  243. (when (not (region-active-p))
  244. (when-let ((url (or (jao-url-around-point)
  245. (thing-at-point 'url)
  246. (and (derived-mode-p 'w3m-mode)
  247. (or (w3m-anchor) w3m-current-url))
  248. (and (derived-mode-p 'eww-mode)
  249. (eww-current-url)))))
  250. (when (string-match-p "^https?.*" url)
  251. (cons 'url url)))))
  252. (add-to-list 'embark-target-finders #'jao-embark-targets--w3m-anchor)
  253. (defun jao-embark-url (url)
  254. "Browse URL, externally if we're already in an emacs browser."
  255. (if (derived-mode-p 'w3m-mode 'eww-mode)
  256. (jao-browse-with-external-browser url)
  257. (browse-url url)))
  258. (define-key embark-url-map (kbd "RET") #'jao-embark-url)
  259. (define-key embark-url-map (kbd "f") #'browse-url-firefox)
  260. (define-key embark-url-map (kbd "x") #'jao-rss-subscribe)
  261. (define-key embark-url-map (kbd "m") 'jao-browse-with-external-browser)
  262. (define-key embark-url-map (kbd "p") 'jao-mpc-add-or-play-url)
  263. ;;;; video url targets
  264. (defvar jao-embark-targets-video-sites
  265. '("youtu.be" "youtube.com" "blip.tv" "vimeo.com" "infoq.com"))
  266. (defun jao-embark--video-url-rx (&optional sites)
  267. (format "^https?://\\(?:www\\.\\)?%s/.+"
  268. (regexp-opt (or sites jao-embark-targets-video-sites) t)))
  269. (defvar jao-embark-targets-video-url-rx (jao-embark--video-url-rx)
  270. "A regular expression matching URLs that point to video streams")
  271. (defun jao-embark-targets--refine-url (_ url)
  272. (if (string-match-p jao-embark-targets-video-url-rx url)
  273. (cons 'video-url url)
  274. (cons 'url url)))
  275. (defun jao-embark-targets--play-video (player url)
  276. (interactive "sURL: ")
  277. (let ((cmd (format "%s %s" player (shell-quote-argument url))))
  278. (jao-afio-goto-www)
  279. (start-process-shell-command player nil cmd)))
  280. (defun jao-embark-targets-mpv (&optional url)
  281. "Play video stream with mpv"
  282. (interactive "sURL: ")
  283. (jao-embark-targets--play-video "mpv" url))
  284. (defun jao-embark-targets-vlc (&optional url)
  285. "Play video stream with vlc"
  286. (interactive "sURL: ")
  287. (jao-embark-targets--play-video "vlc" url))
  288. (defvar jao-embark-targets-video-url-map
  289. (define-keymap "v" #'jao-embark-targets-mpv "RET" #'jao-embark-targets-mpv)
  290. "Actions on URLs pointing to remote video streams.")
  291. (add-to-list 'embark-transformer-alist '(url . jao-embark-targets--refine-url))
  292. (add-to-list 'embark-keymap-alist '(video-url . jao-embark-targets-video-url-map))
  293. (define-key embark-url-map "v" #'jao-embark-targets-vlc)
  294. (define-key embark-url-map "V" #'jao-embark-targets-vlc)
  295. ;;;; vc targets
  296. ;;; avy
  297. (use-package avy
  298. :ensure t
  299. :init (setq avy-style 'pre
  300. avy-background t
  301. avy-timeout-seconds 0.6
  302. avy-single-candidate-jump t)
  303. :config
  304. (defun avy-embark-act (pt)
  305. "Use Embark to act on the completion at PT."
  306. (save-excursion
  307. (goto-char pt)
  308. (embark-act)))
  309. (add-to-list 'avy-dispatch-alist '(?\; . avy-embark-act))
  310. :bind (("s-j" . avy-goto-char-timer)
  311. ("C-M-j" . avy-goto-char-timer)))
  312. ;;; link-hint
  313. (use-package link-hint
  314. :ensure t
  315. :init (setq link-hint-avy-style 'pre
  316. link-hint-message nil)
  317. :config
  318. (defun jao-link-hint-open-link-ext ()
  319. (interactive)
  320. (let ((jao-browse-url-function jao-browse-url-external-function))
  321. (link-hint-open-link)))
  322. :bind (("C-l" . link-hint-open-link)
  323. ("C-M-l" . jao-link-hint-open-link-ext)
  324. ("C-S-l" . jao-link-hint-open-link-ext)
  325. ("C-x C-l" . recenter-top-bottom)))
  326. (with-eval-after-load "notmuch"
  327. (defun jao-link-hint--notmuch-next-part (&optional bound)
  328. (when-let (p (next-single-property-change (point) :notmuch-part nil bound))
  329. (and (< p (or bound (point-max))) p)))
  330. (defun jao-link-hint--notmuch-part-p ()
  331. (and (get-text-property (point) :notmuch-part)
  332. (when-let (b (button-at (point))) (button-label b))))
  333. (link-hint-define-type 'notmuch-part
  334. :next #'jao-link-hint--notmuch-next-part
  335. :at-point-p #'jao-link-hint--notmuch-part-p
  336. :vars '(notmuch-show-mode)
  337. :open #'push-button
  338. :open-message "Toggled"
  339. :open-multiple t)
  340. (push 'link-hint-notmuch-part link-hint-types))
  341. ;;; xref
  342. (setq xref-show-definitions-function #'xref-show-definitions-completing-read)
  343. ;; (use-package dumb-jump
  344. ;; :ensure t
  345. ;; :after xref
  346. ;; :config (add-hook 'xref-backend-functions #'dumb-jump-xref-activate))
  347. ;;; .
  348. (provide 'jao-custom-completion)