summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--emacs-init.org510
1 files changed, 178 insertions, 332 deletions
diff --git a/emacs-init.org b/emacs-init.org
index af95022..82f5a2b 100644
--- a/emacs-init.org
+++ b/emacs-init.org
@@ -1,5 +1,5 @@
# -*- coding: utf-8-unix -*-
-#+PROPERTY: header-args:emacs-lisp :tangle tangle/emacs-10-init.el :results silent :noweb yes
+#+PROPERTY: header-args:emacs-lisp :tangle tangle/emacs-10-init.el :results silent :noweb yes :tangle-mode (identity #o444)
* Contents :QUOTE:TOC_2_gh:
#+BEGIN_QUOTE
- [[#overview][Overview]]
@@ -28,6 +28,7 @@
- [[#tramp][Tramp]]
- [[#git][Git]]
- [[#projects][Projects]]
+ - [[#consult][Consult]]
- [[#working-with-buffers][Working with buffers]]
- [[#window-configuration][Window configuration]]
- [[#file-encryption][File encryption]]
@@ -55,6 +56,7 @@
- [[#context-aware-hydra][Context aware hydra]]
- [[#ssh-tunnels][SSH tunnels]]
- [[#minor-utilities][Minor utilities]]
+ - [[#embark][Embark]]
- [[#language-settings][Language settings]]
- [[#spellcheck][Spellcheck]]
- [[#interface][Interface]]
@@ -1904,343 +1906,79 @@ any recursive editing levels."
* Selection and search methods
** Completion frameworks
Having used ido, ivy, icicles and helm in the past, I'm trying to
-settle for something simple and go back to ido. The settings below
-are for now mostly copied from [[https://gitlab.com/protesilaos/dotemacs/][Protesilaos Stavrou]].
-*** Minibuffer settings
-#+begin_src emacs-lisp
-(use-package minibuffer
- :config
-
- ;; Super-powerful completion style for out-of-order groups of matches
- ;; using a comprehensive set of matching styles.
- (use-package orderless
- :straight t
- :config
- (setq orderless-regexp-separator "[/\s_-]+")
- (setq orderless-matching-styles
- '(orderless-flex
- orderless-strict-leading-initialism
- orderless-regexp
- orderless-prefixes
- orderless-literal))
-
- (defun prot/orderless-literal-dispatcher (pattern _index _total)
- (when (string-suffix-p "=" pattern)
- `(orderless-literal . ,(substring pattern 0 -1))))
-
- (defun prot/orderless-initialism-dispatcher (pattern _index _total)
- (when (string-suffix-p "," pattern)
- `(orderless-strict-leading-initialism . ,(substring pattern 0 -1))))
-
- (setq orderless-style-dispatchers '(prot/orderless-literal-dispatcher
- prot/orderless-initialism-dispatcher))
- :bind (:map minibuffer-local-completion-map
- ("SPC" . nil) ; space should never complete
- ("?" . nil))) ; valid regexp character
-
- (setq completion-styles
- '(orderless partial-completion))
- (setq completion-category-defaults nil)
- (setq completion-cycle-threshold 3)
- (setq completion-flex-nospace nil)
- (setq completion-pcm-complete-word-inserts-delimiters t)
- (setq completion-pcm-word-delimiters "-_./:| ")
- (setq completion-show-help t)
- (setq completion-ignore-case t)
- (setq read-buffer-completion-ignore-case t)
- (setq read-file-name-completion-ignore-case t)
- (setq completions-format 'vertical) ; *Completions* buffer
- (setq enable-recursive-minibuffers t)
- (setq read-answer-short t)
- (setq resize-mini-windows t)
-
- (file-name-shadow-mode 1)
- (minibuffer-depth-indicate-mode 1)
- (minibuffer-electric-default-mode 1)
-
- (defun prot/focus-minibuffer ()
- "Focus the active minibuffer.
-
-Bind this to `completion-list-mode-map' to M-v to easily jump
-between the list of candidates present in the \\*Completions\\*
-buffer and the minibuffer (because by default M-v switches to the
-completions if invoked from inside the minibuffer."
- (interactive)
- (let ((mini (active-minibuffer-window)))
- (when mini
- (select-window mini))))
-
- (defun prot/focus-minibuffer-or-completions ()
- "Focus the active minibuffer or the \\*Completions\\*.
-
-If both the minibuffer and the Completions are present, this
-command will first move per invocation to the former, then the
-latter, and then continue to switch between the two.
+settle for something simple.
-The continuous switch is essentially the same as running
-`prot/focus-minibuffer' and `switch-to-completions' in
-succession."
- (interactive)
- (let* ((mini (active-minibuffer-window))
- ;; This could be hardened a bit, but I am okay with it.
- (completions (or (get-buffer-window "*Completions*")
- (get-buffer-window "*Embark Live Occur*"))))
- (cond ((and mini
- (not (minibufferp)))
- (select-window mini nil))
- ((and completions
- (not (eq (selected-window)
- completions)))
- (select-window completions nil)))))
-
- ;; Technically, this is not specific to the minibuffer, but I define
- ;; it here so that you can see how it is also used from inside the
- ;; "Completions" buffer
- (defun prot/describe-symbol-at-point (&optional arg)
- "Get help (documentation) for the symbol at point.
-
-With a prefix argument, switch to the *Help* window. If that is
-already focused, switch to the most recently used window
-instead."
- (interactive "P")
- (let ((symbol (symbol-at-point)))
- (when symbol
- (describe-symbol symbol)))
- (when arg
- (let ((help (get-buffer-window "*Help*")))
- (when help
- (if (not (eq (selected-window) help))
- (select-window help)
- (select-window (get-mru-window)))))))
-
- ;; This will be deprecated in favour of the `embark' package
- (defun prot/completions-kill-save-symbol ()
- "Add symbol-at-point to the kill ring.
-
-Intended for use in the \\*Completions\\* buffer. Bind this to a
-key in `completion-list-mode-map'."
- (interactive)
- (kill-new (thing-at-point 'symbol)))
-
-
-;;;; DEPRECATED in favour of the `embark' package (see further below),
-;;;; which implements the same functionality in a more efficient way.
-;; (defun prot/complete-kill-or-insert-candidate (&optional arg)
-;; "Place the matching candidate to the top of the `kill-ring'.
-;; This will keep the minibuffer session active.
-;;
-;; With \\[universal-argument] insert the candidate in the most
-;; recently used buffer, while keeping focus on the minibuffer.
-;;
-;; With \\[universal-argument] \\[universal-argument] insert the
-;; candidate and immediately exit all recursive editing levels and
-;; active minibuffers.
-;;
-;; Bind this function in `icomplete-minibuffer-map'."
-;; (interactive "*P")
-;; (let ((candidate (car completion-all-sorted-completions)))
-;; (when (and (minibufferp)
-;; (or (bound-and-true-p icomplete-mode)
-;; (bound-and-true-p live-completions-mode))) ; see next section
-;; (cond ((eq arg nil)
-;; (kill-new candidate))
-;; ((= (prefix-numeric-value arg) 4)
-;; (with-minibuffer-selected-window (insert candidate)))
-;; ((= (prefix-numeric-value arg) 16)
-;; (with-minibuffer-selected-window (insert candidate))
-;; (top-level))))))
-
- ;; Defines, among others, aliases for common actions to Super-KEY.
- ;; Normally these should go in individual package declarations, but
- ;; their grouping here makes things easier to understand.
- :bind (("s-f" . find-file)
- ("s-F" . find-file-other-window)
- ("s-d" . dired)
- ("s-D" . dired-other-window)
- ("s-b" . switch-to-buffer)
- ("s-B" . switch-to-buffer-other-window)
- ("s-h" . prot/describe-symbol-at-point)
- ("s-H" . (lambda ()
- (interactive)
- (prot/describe-symbol-at-point '(4))))
- ("s-v" . prot/focus-minibuffer-or-completions)
- :map minibuffer-local-completion-map
- ("<return>" . minibuffer-force-complete-and-exit)
- ("C-j" . exit-minibuffer)
- ;;;; DEPRECATED in favour of the `embark' package
- ;; ("M-o w" . prot/complete-kill-or-insert-candidate)
- ;; ("M-o i" . (lambda ()
- ;; (interactive)
- ;; (prot/complete-kill-or-insert-candidate '(4))))
- ;; ("M-o j" . (lambda ()
- ;; (interactive)
- ;; (prot/complete-kill-or-insert-candidate '(16))))
- :map completion-list-mode-map
- ("h" . prot/describe-symbol-at-point)
- ("w" . prot/completions-kill-save-symbol)
- ("n" . next-line)
- ("p" . previous-line)
- ("f" . next-completion)
- ("b" . previous-completion)
- ("M-v" . prot/focus-minibuffer)))
-#+end_src
-*** Icomplete
-#+begin_src emacs-lisp
-(use-package icomplete
- :demand
- :after minibuffer ; Read that section as well
- :config
- (setq icomplete-delay-completions-threshold 100)
- (setq icomplete-max-delay-chars 2)
- (setq icomplete-compute-delay 0.2)
- (setq icomplete-show-matches-on-no-input t)
- (setq icomplete-hide-common-prefix nil)
- (setq icomplete-prospects-height 1)
- ;; (setq icomplete-separator " · ")
- ;; (setq icomplete-separator " │ ")
- ;; (setq icomplete-separator " ┆ ")
- ;; (setq icomplete-separator " ¦ ")
- (setq icomplete-separator (propertize " ┆ " 'face 'shadow))
- (setq icomplete-with-completion-tables t)
- (setq icomplete-in-buffer t)
- (setq icomplete-tidy-shadowed-file-names nil)
-
- (fido-mode -1) ; Emacs 27.1
- (icomplete-mode 1)
-
- (defun prot/icomplete-minibuffer-truncate ()
- "Truncate minibuffer lines in `icomplete-mode'.
- This should only affect the horizontal layout and is meant to
- enforce `icomplete-prospects-height' being set to 1.
-
- Hook it to `icomplete-minibuffer-setup-hook'."
- (when (and (minibufferp)
- (bound-and-true-p icomplete-mode))
- (setq truncate-lines t)))
-
- ;; Note that the the syntax for `use-package' hooks is controlled by
- ;; the `use-package-hook-name-suffix' variable. The "-hook" suffix is
- ;; not an error of mine.
- :hook (icomplete-minibuffer-setup-hook . prot/icomplete-minibuffer-truncate)
- :bind (:map icomplete-minibuffer-map
- ("<tab>" . icomplete-force-complete)
- ("<return>" . icomplete-force-complete-and-exit) ; exit with completion
- ("C-j" . exit-minibuffer) ; force input unconditionally
- ("C-n" . icomplete-forward-completions)
- ("<right>" . icomplete-forward-completions)
- ("<down>" . icomplete-forward-completions)
- ("C-p" . icomplete-backward-completions)
- ("<left>" . icomplete-backward-completions)
- ("<up>" . icomplete-backward-completions)
- ;; The following command is from Emacs 27.1
- ("<C-backspace>" . icomplete-fido-backward-updir)))
-#+end_src
-*** Icomplete-vertical
-#+begin_src emacs-lisp
-(use-package icomplete-vertical
+For =vertico= use =M-RET= to end repeated minibuffer reads instead of =RET=.
+#+begin_src emacs-lisp
+;; Vertico & Marginalia
+(use-package vertico
+ :straight t
+ :init (vertico-mode 1))
+(use-package vertico-posframe
:straight t
- :demand
- :after (minibuffer icomplete) ; do not forget to check those as well
:config
- (setq icomplete-vertical-prospects-height (/ (frame-height) 6))
- (icomplete-vertical-mode -1)
-
- (defun prot/kill-ring-yank-complete ()
- "Insert the selected `kill-ring' item directly at point.
-When region is active, `delete-region'.
-
-Sorting of the `kill-ring' is disabled. Items appear as they
-normally would when calling `yank' followed by `yank-pop'."
+ (defun fpi/vertico-posframe-toggle ()
(interactive)
- (let ((kills ; do not sort items
- (lambda (string pred action)
- (if (eq action 'metadata)
- '(metadata (display-sort-function . identity)
- (cycle-sort-function . identity))
- (complete-with-action
- action kill-ring string pred)))))
- (icomplete-vertical-do
- (:separator 'dotted-line :height (/ (frame-height) 4))
- (when (use-region-p)
- (delete-region (region-beginning) (region-end)))
- (insert
- (completing-read "Yank from kill ring: " kills nil t)))))
-
- :bind (("s-y" . prot/kill-ring-yank-complete)
- :map icomplete-minibuffer-map
- ("C-v" . icomplete-vertical-toggle)))
-#+end_src
-*** Ido
-:PROPERTIES:
-:header-args:emacs-lisp: :tangle no
-:END:
-#+BEGIN_SRC emacs-lisp
-(use-package ido
- :init
- (setq ido-everywhere t)
- (setq ido-enable-flex-matching t)
- (setq ido-enable-regexp nil)
- (setq ido-enable-prefix nil)
- (setq ido-all-frames nil)
- (setq ido-buffer-disable-smart-matches t)
- (setq ido-completion-buffer "*Ido Completions*")
- (setq ido-completion-buffer-all-completions nil)
- (setq ido-confirm-unique-completion nil)
- (setq ido-create-new-buffer 'prompt)
- (setq ido-default-buffer-method 'selected-window)
- (setq ido-default-file-method 'selected-window)
- (setq ido-enable-last-directory-history t)
- (setq ido-use-filename-at-point nil)
- (setq ido-use-url-at-point nil)
- (setq ido-use-virtual-buffers t)
- (setq ido-use-faces t)
- (setq ido-max-window-height 1)
- (setq ido-decorations
- '(" "
- " "
- " | "
- " | …"
- "["
- "]"
- " [No match]"
- " [Matched]"
- " [Not readable]"
- " [Too big]"
- " [Confirm]"
- " "
- " "))
- (setq ido-auto-merge-work-directories-length -1)
- :config
- (ido-mode 1)
- :hook
- (minibuffer-setup . (lambda ()
- (visual-line-mode 1)
- (setq-local truncate-lines nil)
- (setq-local resize-mini-windows nil)
- (setq-local max-mini-window-height 1))))
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp :tangle no
-(use-package ido-completing-read+
+ (if vertico-posframe-mode
+ (progn
+ (vertico-posframe-cleanup)
+ (vertico-posframe-mode -1))
+ (vertico-posframe-mode 1)))
+ :bind (:map vertico-map
+ ("C-," . fpi/vertico-posframe-toggle))
+ :init (vertico-posframe-mode 1))
+(use-package marginalia
:straight t
- :after ido
- :config
- (ido-ubiquitous-mode 1))
-#+END_SRC
-*** amx
-Ido completion for =M-x=.
-#+BEGIN_SRC emacs-lisp :tangle no
-(use-package amx
+ :bind (:map minibuffer-local-map
+ ("M-A" . marginalia-cycle))
+ :init (marginalia-mode 1))
+
+;; Orderless & minibuffer settings
+(use-package orderless
:straight t
- :after (ido ido-completing-read+)
- :init
- (setq amx-backend 'ido)
- (setq amx-save-file "~/.emacs.d/amx-items")
- (setq amx-history-length 10)
- (setq amx-show-key-bindings nil)
:config
- (amx-mode 1))
-#+END_SRC
+ (setq orderless-matching-styles
+ '(orderless-regexp
+ orderless-initialism))
+ (defmacro fpi/orderless-dispatcher (name suffix style)
+ "Define a orderless dispatcher function NAME using key SUFFIX to
+call STYLE."
+ (backquote
+ (defun ,name (pattern _index _total)
+ (when (string-suffix-p ,suffix pattern)
+ (backquote (,style ,backquote-unquote-symbol(substring pattern 0 -1)))))))
+ (fpi/orderless-dispatcher
+ fpi/orderless-literal-dispatcher "=" orderless-literal)
+ (fpi/orderless-dispatcher
+ fpi/orderless-initialism-dispatcher "," orderless-initialism)
+ (fpi/orderless-dispatcher
+ fpi/orderless-flex-dispatcher "~" orderless-flex)
+ (setq orderless-style-dispatchers
+ '(fpi/orderless-literal-dispatcher
+ fpi/orderless-initialism-dispatcher
+ fpi/orderless-flex-dispatcher)))
+(use-package minibuffer
+ :after (consult orderless)
+ :custom
+ ;; Make tramp host completion work. See vertico documentation.
+ (completion-styles '(orderless basic))
+ (completion-category-overrides '((file (styles basic partial-completion))))
+
+ ;; Make completion-at-point use vertico
+ (completion-in-region-function
+ (lambda (&rest args)
+ (apply (if vertico-mode
+ #'consult-completion-in-region
+ #'completion--in-region)
+ args))))
+
+;; General settings
+(setq enable-recursive-minibuffers t)
+(setq read-answer-short t)
+(file-name-shadow-mode 1)
+(minibuffer-depth-indicate-mode 1)
+(minibuffer-electric-default-mode 1)
+#+end_src
** isearch enhancements
Once again this is mostly taken from [[https://gitlab.com/protesilaos/dotemacs/][Protesilaos Stavrou]].
@@ -2957,6 +2695,88 @@ Projectile should be fully replaceable with =project.el=. Though some packages m
;; (projectile-mode 1)
:bind (("C-c p" . projectile-command-map)))
#+END_SRC
+** Consult
+A bundle of common functions. Mostly drop in replacements for ~find-file~, ~grep~, ~find~, etc.
+#+begin_src emacs-lisp
+(define-prefix-command 'fpi/consult-map nil "consult-map")
+(use-package consult
+ :straight t
+ :bind
+ ;; C-x bindings (ctl-x-map)
+ (("C-x b" . consult-buffer) ;; orig. switch-to-buffer
+ ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
+ ("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
+ ("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
+ ("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
+ )
+ ;; M-g, M-s
+ (("<help> a" . consult-apropos) ;; orig. apropos-command
+ ;; M-g bindings (goto-map)
+ ("M-g e" . consult-compile-error)
+ ("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
+ ("M-g g" . consult-goto-line) ;; orig. goto-line
+ ("M-g M-g" . consult-goto-line) ;; orig. goto-line
+ ("M-g o" . consult-outline) ;; Alternative: consult-org-heading
+ ("M-g m" . consult-mark)
+ ("M-g k" . consult-global-mark)
+ ;; 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 m" . consult-multi-occur)
+ ("M-s u" . consult-focus-lines)
+ ;; Isearch integration
+ ("M-s e" . consult-isearch-history)
+ :map isearch-mode-map
+ ("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
+ ("M-s l" . consult-line) ;; needed by consult-line to detect isearch
+ ("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
+ ;; Minibuffer history
+ :map minibuffer-local-map
+ ("M-s" . consult-history) ;; orig. next-matching-history-element
+ ("M-r" . consult-history)) ;; orig. previous-matching-history-element
+ (:map fpi/consult-map
+ ;; C-c bindings (mode-specific-map)
+ ("h" . consult-history)
+ ("m" . consult-mode-command)
+ )
+ :config
+ ;; Optionally configure preview. The default value
+ ;; is 'any, such that any key triggers the preview.
+ ;; (setq consult-preview-key 'any)
+ ;; (setq consult-preview-key (kbd "M-."))
+ )
+(use-package consult-flyspell
+ :after consult
+ :bind (("M-s s" . consult-flyspell)))
+(use-package consult-org-roam
+ :straight t
+ :after (consult org-roam)
+ :custom
+ (consult-org-roam-grep-func #'consult-ripgrep)
+ :config
+ ;; Eventually suppress previewing for certain functions
+ ;; (consult-customize
+ ;; consult-org-roam-forward-links
+ ;; :preview-key (kbd "M-."))
+ :bind
+ ("C-c n e" . consult-org-roam-file-find)
+ ("C-c n b" . consult-org-roam-backlinks)
+ ("C-c n r" . consult-org-roam-search))
+#+end_src
+
+Fix pdf-tools =goto-page= command:
+#+begin_src emacs-lisp :noweb-ref pdf-tools-config :tangle no
+(define-key pdf-view-mode-map [remap consult-goto-line] 'pdf-view-goto-page)
+#+end_src
+
+#+begin_src emacs-lisp :noweb-ref fpi-bindings :tangle no
+(fpi/define-key fpi-map (kbd ".") #'fpi/consult-map "Consult")
+#+end_src
** Working with buffers
This renames buffers with the same name and uniqifies them using angled
@@ -3167,7 +2987,9 @@ make sure to compile the tex document with the option ~--synctex=1~.
:straight t
:config
(setq pdf-info-epdfinfo-program (concat user-emacs-directory "epdfinfo"))
- (pdf-tools-install))
+ (pdf-tools-install)
+ <<pdf-tools-config>>
+ )
#+END_SRC
Add support for pdf annotations. Rebind ~pdf-annot-minor-mode-map~ to
@@ -6467,6 +6289,27 @@ The =Auto-Insert= package helps inserting header templates upon creating files.
"#!/usr/bin/env bash" \n \n))
(auto-insert-mode -1))
#+end_src
+** Embark
+Do things in the order =selection → action= instead of =action → selection=.
+#+begin_src emacs-lisp
+(use-package embark
+ :straight t
+ :bind (("C-." . embark-act)))
+(use-package embark-consult
+ :straight t
+ :after (embark consult))
+#+end_src
+
+As minor-mode maps would override the global map we have to unset the =C-.= binding in flyspell. We can either do this with an ~eval-after-load~
+#+begin_src emacs-lisp :tangle no :eval never
+(eval-after-load "flyspell"
+ '(define-key flyspell-mode-map (kbd "C-.") nil))
+#+end_src
+
+or by (un-)setting the binding explicitly in the =use-package= call of flyspell.
+#+begin_src emacs-lisp :tangle no :noweb-ref flyspell-bindings
+("C-." . nil)
+#+end_src
* Language settings
End sentences with single spaces.
#+begin_src emacs-lisp
@@ -6487,6 +6330,9 @@ Setup mainly from [[https://github.com/howardabrams/dot-files/blob/master/emacs.
#+begin_src emacs-lisp
(use-package flyspell
:delight
+ :bind (:map flyspell-mode-map
+ <<flyspell-bindings>>
+ )
:init
(add-hook 'prog-mode-hook 'flyspell-prog-mode)
(dolist (hook '(text-mode-hook org-mode-hook))