jao-custom-completion.el 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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)))
  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. :custom ((consult-preview-key (kbd "`")))
  115. :init
  116. (fset 'multi-occur #'consult-multi-occur)
  117. (setq org-refile-use-outline-path t
  118. org-imenu-depth 7)
  119. :config
  120. (defun jao-consult--completion-in-region (&rest args)
  121. (apply (if (and (not (bound-and-true-p corfu-mode))
  122. (not (bound-and-true-p company-mode))
  123. (bound-and-true-p vertico-mode))
  124. #'consult-completion-in-region
  125. #'completion--in-region)
  126. args))
  127. (setq completion-in-region-function #'jao-consult--completion-in-region)
  128. (defun jao-find-file (arg)
  129. (interactive "P")
  130. (call-interactively (if arg 'consult-file-externally 'find-file)))
  131. (define-key consult-narrow-map (vconcat consult-narrow-key "?")
  132. #'consult-narrow-help)
  133. (with-eval-after-load "esh-mode"
  134. (define-key eshell-mode-map (kbd "C-c h") #'consult-history))
  135. (with-eval-after-load "comint"
  136. (define-key comint-mode-map (kbd "C-c h") #'consult-history))
  137. (consult-customize consult-mark :preview-key 'any)
  138. (add-hook 'completion-list-mode-hook #'consult-preview-at-point-mode))
  139. ;;;; consult-dir
  140. ;; (use-package consult-dir
  141. ;; :ensure t
  142. ;; :bind (("C-x C-d" . consult-dir)
  143. ;; :map minibuffer-local-completion-map
  144. ;; (("C-x C-d" . consult-dir)
  145. ;; ("C-x C-j" . consult-dir-jump-file))))
  146. ;;;; narrow helpers
  147. (defvar jao-consult-narrow nil)
  148. (defun jao-consult-initial-narrow ()
  149. (when-let (c (cond ((eq this-command #'consult-buffer)
  150. (cdr (assoc (jao-afio-frame-name) jao-consult-narrow)))
  151. ((eq this-command #'consult-mode-command) ?m)))
  152. (setq unread-command-events (append unread-command-events `(,c 32)))))
  153. (add-hook 'minibuffer-setup-hook #'jao-consult-initial-narrow)
  154. (defmacro jao-consult--mode-buffers (&rest modes)
  155. `(lambda ()
  156. (seq-map #'buffer-name
  157. (seq-filter (lambda (b)
  158. (with-current-buffer b
  159. (derived-mode-p ,@modes)))
  160. (buffer-list)))))
  161. (defun jao-consult-add-buffer-source (src &optional aframe key)
  162. (add-to-list 'consult-buffer-sources src t)
  163. (when (and aframe key)
  164. (add-to-list 'jao-consult-narrow (cons aframe key))))
  165. ;;; embark
  166. ;;;; package
  167. (use-package embark
  168. :ensure t
  169. :demand t
  170. :init
  171. (setq embark-quit-after-action nil
  172. embark-indicators '(embark-mixed-indicator
  173. ;; embark-minimal-indicator
  174. embark-highlight-indicator
  175. embark-isearch-highlight-indicator)
  176. embark-mixed-indicator-both t
  177. embark-mixed-indicator-delay 1
  178. embark-verbose-indicator-buffer-sections '(bindings)
  179. embark-verbose-indicator-excluded-commands
  180. '(embark-become embark-export embark-collect)
  181. embark-verbose-indicator-nested t
  182. embark-verbose-indicator-display-action
  183. '((display-buffer-at-bottom)
  184. (window-parameters (mode-line-format . none))
  185. (window-height . fit-window-to-buffer)))
  186. ;; (setq prefix-help-command #'describe-prefix-bindings)
  187. ;; (add-to-list 'vertico-multiform-categories '(embark-keybinding grid))
  188. :bind (("C-;" . embark-act)
  189. ("C-c ;" . embark-act)
  190. ("C-'" . embark-dwim)
  191. ("C-c '" . embark-dwim)
  192. (:map minibuffer-local-map
  193. (("C-'" . embark-dwim)
  194. ("C-c '" . embark-dwim)
  195. ("C-," . embark-become)
  196. ("C-c ," . embark-become)
  197. ("C-o" . embark-export)))))
  198. (use-package embark-consult
  199. :ensure t
  200. :after (embark consult))
  201. (with-eval-after-load 'consult
  202. (with-eval-after-load 'embark
  203. (require 'embark-consult)))
  204. ;;;; randomsig
  205. (defun jao-random-sig-read (_ignored)
  206. "Import region as signature and edit it."
  207. (randomsig-message-read-sig t))
  208. (define-key embark-region-map "m" #'jao-random-sig-read)
  209. (define-key embark-region-map "M" #'apply-macro-to-region-lines)
  210. ;;;; dict/say
  211. (defun jao-say (&optional word)
  212. "Isn't it nice to have a computer that can talk to you?"
  213. (interactive "sWhat? ")
  214. (shell-command-to-string (format "say %s" word))
  215. "")
  216. (define-key embark-identifier-map "D" #'dictionary-search)
  217. (define-key embark-identifier-map "S" #'jao-say)
  218. ;;;; org targets
  219. (declare-function org-link-any-re "ol")
  220. (declare-function org-open-link-from-string "ol")
  221. (declare-function org-in-regexp "org-macs")
  222. (defun jao-embark-targets--org-link ()
  223. (when (derived-mode-p 'org-mode)
  224. (let ((lnk (org-element-property :raw-link (org-element-context))))
  225. (and lnk (cons 'org-link lnk)))))
  226. (defun jao-embark-targets--gl-org-link ()
  227. (when (org-in-regexp org-link-bracket-re)
  228. (cons 'gl-org-link (match-string-no-properties 0))))
  229. (defvar jao-embark-targets-gl-org-link-map
  230. (define-keymap "RET" #'org-open-at-point-global))
  231. (defvar jao-embark-targets-org-link-map
  232. (define-keymap "RET" #'org-open-link-from-string))
  233. (add-to-list 'embark-target-finders #'jao-embark-targets--gl-org-link)
  234. (add-to-list 'embark-keymap-alist
  235. '(gl-org-link . jao-embark-targets-gl-org-link-map))
  236. (add-to-list 'embark-target-finders #'jao-embark-targets--org-link)
  237. (add-to-list 'embark-keymap-alist
  238. '(org-link . jao-embark-targets-org-link-map))
  239. ;;;; url targets
  240. (declare-function w3m-anchor "w3m")
  241. (defun jao-embark-targets--w3m-anchor ()
  242. (when (not (region-active-p))
  243. (when-let ((url (or (jao-url-around-point)
  244. (thing-at-point 'url)
  245. (and (derived-mode-p 'w3m-mode)
  246. (or (w3m-anchor) w3m-current-url))
  247. (and (derived-mode-p 'eww-mode)
  248. (eww-current-url)))))
  249. (when (string-match-p "^https?.*" url)
  250. (cons 'url url)))))
  251. (add-to-list 'embark-target-finders #'jao-embark-targets--w3m-anchor)
  252. (defun jao-embark-url (url)
  253. "Browse URL, externally if we're already in an emacs browser."
  254. (if (derived-mode-p 'w3m-mode 'eww-mode)
  255. (jao-browse-with-external-browser url)
  256. (browse-url url)))
  257. (define-key embark-url-map (kbd "RET") #'jao-embark-url)
  258. (define-key embark-url-map (kbd "f") #'browse-url-firefox)
  259. (define-key embark-url-map (kbd "x") #'jao-rss-subscribe)
  260. (define-key embark-url-map (kbd "m") 'jao-browse-with-external-browser)
  261. (define-key embark-url-map (kbd "p") 'jao-mpc-add-or-play-url)
  262. ;;;; video url targets
  263. (defvar jao-embark-targets-video-sites
  264. '("youtu.be" "youtube.com" "blip.tv" "vimeo.com" "infoq.com"))
  265. (defun jao-embark--video-url-rx (&optional sites)
  266. (format "^https?://\\(?:www\\.\\)?%s/.+"
  267. (regexp-opt (or sites jao-embark-targets-video-sites) t)))
  268. (defvar jao-embark-targets-video-url-rx (jao-embark--video-url-rx)
  269. "A regular expression matching URLs that point to video streams")
  270. (defun jao-embark-targets--refine-url (_ url)
  271. (if (string-match-p jao-embark-targets-video-url-rx url)
  272. (cons 'video-url url)
  273. (cons 'url url)))
  274. (defun jao-embark-targets--play-video (player url)
  275. (interactive "sURL: ")
  276. (let ((cmd (format "%s %s" player (shell-quote-argument url))))
  277. (jao-afio-goto-www)
  278. (start-process-shell-command player nil cmd)))
  279. (defun jao-embark-targets-mpv (&optional url)
  280. "Play video stream with mpv"
  281. (interactive "sURL: ")
  282. (jao-embark-targets--play-video "mpv" url))
  283. (defun jao-embark-targets-vlc (&optional url)
  284. "Play video stream with vlc"
  285. (interactive "sURL: ")
  286. (jao-embark-targets--play-video "vlc" url))
  287. (defvar jao-embark-targets-video-url-map
  288. (define-keymap "v" #'jao-embark-targets-mpv "RET" #'jao-embark-targets-mpv)
  289. "Actions on URLs pointing to remote video streams.")
  290. (add-to-list 'embark-transformer-alist '(url . jao-embark-targets--refine-url))
  291. (add-to-list 'embark-keymap-alist '(video-url . jao-embark-targets-video-url-map))
  292. (define-key embark-url-map "v" #'jao-embark-targets-vlc)
  293. (define-key embark-url-map "V" #'jao-embark-targets-vlc)
  294. ;;;; vc targets
  295. ;;; avy
  296. (use-package avy
  297. :ensure t
  298. :init (setq avy-style 'pre
  299. avy-background t
  300. avy-timeout-seconds 0.6
  301. avy-single-candidate-jump t)
  302. :config
  303. (defun avy-embark-act (pt)
  304. "Use Embark to act on the completion at PT."
  305. (save-excursion
  306. (goto-char pt)
  307. (embark-act)))
  308. (add-to-list 'avy-dispatch-alist '(?\; . avy-embark-act))
  309. :bind (("s-j" . avy-goto-char-timer)
  310. ("C-M-j" . avy-goto-char-timer)))
  311. ;;; link-hint
  312. (use-package link-hint
  313. :ensure t
  314. :init (setq link-hint-avy-style 'pre
  315. link-hint-message nil)
  316. :config
  317. (defun jao-link-hint-open-link-ext ()
  318. (interactive)
  319. (let ((jao-browse-url-function jao-browse-url-external-function))
  320. (link-hint-open-link)))
  321. :bind (("C-l" . link-hint-open-link)
  322. ("C-M-l" . jao-link-hint-open-link-ext)
  323. ("C-S-l" . jao-link-hint-open-link-ext)
  324. ("C-x C-l" . recenter-top-bottom)))
  325. (with-eval-after-load "notmuch"
  326. (defun jao-link-hint--notmuch-next-part (&optional bound)
  327. (when-let (p (next-single-property-change (point) :notmuch-part nil bound))
  328. (and (< p (or bound (point-max))) p)))
  329. (defun jao-link-hint--notmuch-part-p ()
  330. (and (get-text-property (point) :notmuch-part)
  331. (when-let (b (button-at (point))) (button-label b))))
  332. (link-hint-define-type 'notmuch-part
  333. :next #'jao-link-hint--notmuch-next-part
  334. :at-point-p #'jao-link-hint--notmuch-part-p
  335. :vars '(notmuch-show-mode)
  336. :open #'push-button
  337. :open-message "Toggled"
  338. :open-multiple t)
  339. (push 'link-hint-notmuch-part link-hint-types))
  340. ;;; xref
  341. (setq xref-show-definitions-function #'xref-show-definitions-completing-read)
  342. ;; (use-package dumb-jump
  343. ;; :ensure t
  344. ;; :after xref
  345. ;; :config (add-hook 'xref-backend-functions #'dumb-jump-xref-activate))
  346. ;;; .
  347. (provide 'jao-custom-completion)