X-Git-Url: https://git.shemshak.org/gitweb.cgi/~bandali/configs/blobdiff_plain/e473bc2094947be1b104aad25c3d04400452ed8a..0e2ffd584aafdd4cf256bcdf2473f01c3aaaed55:/init.org?ds=inline diff --git a/init.org b/init.org index 6575a91..2374cac 100644 --- a/init.org +++ b/init.org @@ -105,20 +105,19 @@ file. ** Naming conventions -The conventions below were inspired by [[https://github.com/hlissner/doom-emacs][Doom]]'s conventions, found -[[https://github.com/hlissner/doom-emacs/blob/5dacbb7cb1c6ac246a9ccd15e6c4290def67757c/core/core.el#L3-L17][here]]. Naturally, I use my initials, =ab=, instead of =doom=. +The conventions below were inspired by [[https://github.com/hlissner/doom-emacs][Doom]]'s, found [[https://github.com/hlissner/doom-emacs/blob/5dacbb7cb1c6ac246a9ccd15e6c4290def67757c/core/core.el#L3-L17][here]]. #+begin_src emacs-lisp :comments none ;; Naming conventions: ;; -;; ab-... public variables or non-interactive functions -;; ab--... private anything (non-interactive), not safe for direct use -;; ab/... an interactive function; safe for M-x or keybinding -;; ab:... an evil operator, motion, or command -;; ab|... a hook function -;; ab*... an advising function -;; ab@... a hydra command -;; ...! a macro +;; amin-... public variables or non-interactive functions +;; amin--... private anything (non-interactive), not safe for direct use +;; amin/... an interactive function; safe for M-x or keybinding +;; amin:... an evil operator, motion, or command +;; amin|... a hook function +;; amin*... an advising function +;; amin@... a hydra command +;; ...! a macro #+end_src * Initial setup @@ -137,10 +136,10 @@ let's see how long Emacs takes to start up, before even loading =init.el=, i.e. =user-init-file=: #+begin_src emacs-lisp -(defvar ab--before-user-init-time (current-time) +(defvar amin--before-user-init-time (current-time) "Value of `current-time' when Emacs begins loading `user-init-file'.") (message "Loading Emacs...done (%.3fs)" - (float-time (time-subtract ab--before-user-init-time + (float-time (time-subtract amin--before-user-init-time before-init-time))) #+end_src @@ -150,9 +149,9 @@ frequency. Clearing the ~file-name-handler-alist~ seems to help reduce startup time as well. #+begin_src emacs-lisp -(defvar ab--gc-cons-threshold gc-cons-threshold) -(defvar ab--gc-cons-percentage gc-cons-percentage) -(defvar ab--file-name-handler-alist file-name-handler-alist) +(defvar amin--gc-cons-threshold gc-cons-threshold) +(defvar amin--gc-cons-percentage gc-cons-percentage) +(defvar amin--file-name-handler-alist file-name-handler-alist) (setq gc-cons-threshold (* 400 1024 1024) ; 400 MiB gc-cons-percentage 0.6 file-name-handler-alist nil @@ -167,9 +166,9 @@ done initializing. (add-hook 'after-init-hook (lambda () - (setq gc-cons-threshold ab--gc-cons-threshold - gc-cons-percentage ab--gc-cons-percentage - file-name-handler-alist ab--file-name-handler-alist))) + (setq gc-cons-threshold amin--gc-cons-threshold + gc-cons-percentage amin--gc-cons-percentage + file-name-handler-alist amin--file-name-handler-alist))) #+end_src Increase the number of lines kept in message logs (the =*Messages*= @@ -397,7 +396,7 @@ Font stack with better unicode support, around =Ubuntu Mono= and ** Useful utilities #+begin_src emacs-lisp -(defun ab-enlist (exp) +(defun amin-enlist (exp) "Return EXP wrapped in a list, or as-is if already a list." (if (listp exp) exp (list exp))) @@ -407,7 +406,7 @@ Font stack with better unicode support, around =Ubuntu Mono= and compilation." (declare (indent defun) (debug t)) (list (if (or (not (bound-and-true-p byte-compile-current-file)) - (dolist (next (ab-enlist features)) + (dolist (next (amin-enlist features)) (if (symbolp next) (require next nil :no-error) (load next :no-message :no-error)))) @@ -610,68 +609,138 @@ customizing it. 'auto-compile-inhibit-compile-detached-git-head)) #+end_src -*** [[https://github.com/Kungsgeten/ryo-modal][ryo-modal]] +*** [[https://github.com/noctuid/general.el][general]] -#+begin_quote -Roll your own modal mode -#+end_quote + #+begin_src emacs-lisp +(use-package general + :demand t + :config + (general-evil-setup t) + + (general-override-mode) + + (general-create-definer + amin--mode-leader-keys + :keymaps 'override + :states '(emacs normal visual motion insert) + :non-normal-prefix "C-," + :prefix ",") + + (general-create-definer + amin--leader-keys + :keymaps 'override + :states '(emacs normal visual motion insert) + :non-normal-prefix "M-m" + :prefix "SPC")) +#+end_src + +*** evil + +#+begin_src emacs-lisp +(use-package evil + :demand t + :hook ((view-mode . evil-motion-state) + (org-src-mode . evil-insert-state)) + :init + (setq evil-want-integration nil) + :config (evil-mode 1) + (general-swap-key nil '(normal motion) ";" ":") + (setq evil-want-visual-char-semi-exclusive t)) +#+end_src + +#+begin_src emacs-lisp +(use-package evil-collection + :after evil + :config + (evil-collection-init)) +#+end_src + +#+begin_src emacs-lisp +(use-package evil-escape + :demand t + :init + (setq evil-escape-excluded-states '(normal visual multiedit emacs motion) + evil-escape-excluded-major-modes '(neotree-mode) + evil-escape-key-sequence "jk" + evil-escape-delay 0.25) + :general + (:states '(insert replace visual operator) + "C-g" #'evil-escape) + :config + (evil-escape-mode 1) + ;; no `evil-escape' in minibuffer + (push #'minibufferp evil-escape-inhibit-functions)) +#+end_src + +#+begin_src emacs-lisp +(use-package evil-magit + :after magit + :config + (evil-set-initial-state 'git-commit-mode 'insert)) +#+end_src #+begin_src emacs-lisp -(use-package ryo-modal - :commands ryo-modal-mode - :bind ("M-m" . ryo-modal-mode) - :after which-key +(use-package evil-org + :hook (org-mode . evil-org-mode) + :general + (nvmap evil-org-mode-map + "TAB" 'org-cycle + "S-TAB" 'org-cycle) :config - (push '((nil . "ryo:.*:") . (nil . "")) which-key-replacement-alist) - (ryo-modal-keys - ("," ryo-modal-repeat) - ("b" backward-char) - ("n" next-line) - ("p" previous-line) - ("f" forward-char) - ("/" undo) - ("i" ryo-modal-mode) - ("l" recenter-top-bottom) - ("v" scroll-up-command) - ("V" scroll-down-command) - ("x" delete-forward-char) - ("SPC" (("b" (("b" ibuffer-list-buffers) - ("k" kill-this-buffer) - ("o" other-window) - ("s" save-buffer))) - ("B" (("A" borg-activate) - ("a" borg-assimilate) - ("b" borg-build) - ("c" borg-clone) - ("r" borg-remove))) - ("h" (("c" describe-char) - ("f" describe-function) - ("F" describe-face) - ("i" info) - ("k" describe-key) - ("l" view-lossage) - ("v" describe-variable))) - ("q" (("q" save-buffers-kill-terminal))))) - ("d" (("w" kill-word) - ("b" backward-kill-word))) - ("c w" kill-word :exit t)) - - (ryo-modal-keys - ;; First argyment to ryo-modal-keys may be a list of keywords. - ;; These keywords will be applied to all keybindings. - (:norepeat t) - ("0" "M-0") - ("1" "M-1") - ("2" "M-2") - ("3" "M-3") - ("4" "M-4") - ("5" "M-5") - ("6" "M-6") - ("7" "M-7") - ("8" "M-8") - ("9" "M-9")) - :hook ((text-mode . ryo-modal-mode) - (prog-mode . ryo-modal-mode))) + (evil-org-set-key-theme) + (require 'evil-org-agenda) + (evil-org-agenda-set-keys) + (nmap evil-org-mode-map + [backtab] 'org-shifttab) + (after! org-src + (define-key org-src-mode-map [remap evil-write] 'org-edit-src-save) + (define-key org-src-mode-map [remap evil-save-and-close] + (lambda () (interactive) + (org-edit-src-save) + (org-edit-src-exit))) + (define-key org-src-mode-map [remap evil-save-modified-and-close] + (lambda () (interactive) + (org-edit-src-save) + (org-edit-src-exit))))) +#+end_src + +#+begin_src emacs-lisp +(amin--leader-keys + "/" '(:ignore t :wk "search") + + "B" '(:ignore t :wk "Borg") + "BA" 'borg-activate + "Ba" 'borg-assimilate + "Bb" 'borg-build + "Bc" 'borg-clone + "Bd" 'epkg-describe-package + "Bp" 'epkg-list-packages + "Br" 'borg-remove + "Bu" 'epkg-update + + "b" '(:ignore t :wk "buffers") + "bb" 'ibuffer-list-buffers + "bk" 'kill-this-buffer + "bs" 'save-buffer + + "f" '(:ignore t :wk "files") + + "h" '(:ignore t :wk "help") + "hc" 'describe-char + "hf" 'describe-function + "hF" 'describe-face + "hi" 'info + "hk" 'describe-key + "hl" 'view-lossage + "hv" 'describe-variable + + "o" 'other-window + + "w" '(:ignore t :wk "window") + "wo" 'other-window + + "q" '(:ignore t :wk "quit") + "qq" 'save-buffers-kill-terminal) #+end_src *** [[https://orgmode.org/][Org mode]] @@ -686,20 +755,15 @@ In short, my favourite way of life. #+begin_src emacs-lisp (use-package org - :ryo ("SPC b t" org-babel-tangle) + :general + (amin--leader-keys "bt" 'org-babel-tangle) + (amin--leader-keys org-mode-map "i" 'org-edit-special) :config (setq org-src-tab-acts-natively t org-src-preserve-indentation nil - org-edit-src-content-indentation 0 - org-html-divs '((preamble "header" "preamble") - (content "main" "content") - (postamble "footer" "postamble")) - org-html-doctype "html5" - org-html-html5-fancy t - org-html-postamble nil) + org-edit-src-content-indentation 0) :hook (org-mode . org-indent-mode)) -(use-package htmlize - :after org) + (use-package org-notmuch :after (:any org notmuch)) #+end_src @@ -714,7 +778,21 @@ Not just how I do git, but /the/ way to do git. #+begin_src emacs-lisp (use-package magit - :ryo ("SPC" (("g s" magit-status))) + :general + (amin--leader-keys + "g" '(:ignore t :wk "magit") + "g SPC" 'magit-status + "gs" 'magit-status + "gS" 'magit-status-prefix + "gB" 'magit-blame + "gC" 'magit-clone + "gf" 'magit-fetch + "gF" 'magit-pull + "gP" 'magit-push + "gcc" 'magit-commit + "gca" 'magit-commit-amend + "gbb" 'magit-checkout + "gbc" 'magit-branch) :defer t :bind (("s-g" . magit-status) ("C-x g" . magit-status) @@ -748,7 +826,7 @@ There's no way I could top that, so I won't attempt to. ([S-up] . ivy-previous-history-element) ([S-down] . ivy-next-history-element) ("DEL" . ivy-backward-delete-char)) - :ryo ("SPC ," ivy-switch-buffer) + :general (amin--leader-keys "," 'ivy-switch-buffer) :config (setq ivy-wrap t) (ivy-mode 1)) @@ -758,9 +836,8 @@ There's no way I could top that, so I won't attempt to. #+begin_src emacs-lisp (use-package swiper - :ryo - ("SPC /" swiper) - ("s" swiper) + :general (:states '(normal motion) "/" 'swiper) + (amin--leader-keys "//" 'swiper) :bind (([remap isearch-forward] . swiper) ([remap isearch-backward] . swiper))) #+end_src @@ -770,10 +847,11 @@ There's no way I could top that, so I won't attempt to. #+begin_src emacs-lisp (use-package counsel :defer 1 - :ryo - ("SPC" (("f r" counsel-recentf) - ("SPC" counsel-M-x) - ("." counsel-find-file))) + :general + (amin--leader-keys + "fr" 'counsel-recentf + "SPC" 'counsel-M-x + "." 'counsel-find-file) :bind (([remap execute-extended-command] . counsel-M-x) ([remap find-file] . counsel-find-file) ("s-r" . counsel-recentf) @@ -860,9 +938,6 @@ TODO: break this giant source block down into individual org sections. (list (regexp-quote (system-name)) nil nil))) (use-package undo-tree - :ryo - ("?" undo-tree-undo) - ("_" undo-tree-redo) :bind (("C-?" . undo-tree-undo) ("M-_" . undo-tree-redo)) :config @@ -1153,15 +1228,12 @@ Emacs package that displays available keybindings in popup (use-package crux :bind (("C-c d" . crux-duplicate-current-line-or-region) ("C-c M-d" . crux-duplicate-and-comment-current-line-or-region)) - :ryo - ("o" crux-smart-open-line :exit t) - ("O" crux-smart-open-line-above :exit t) - ("SPC b K" crux-kill-other-buffers) - ("d d" crux-kill-whole-line) - ("c c" crux-kill-whole-line :then '(crux-smart-open-line-above) :exit t) - ("SPC f" (("c" crux-copy-file-preserve-attributes) - ("D" crux-delete-file-and-buffer) - ("R" crux-rename-file-and-buffer)))) + :general + (amin--leader-keys + "bK" 'crux-kill-other-buffers + "fc" 'crux-copy-file-preserve-attributes + "fD" 'crux-delete-file-and-buffer + "fR" 'crux-rename-file-and-buffer)) #+end_src ** [[https://github.com/alezost/mwim.el][mwim]] @@ -1172,21 +1244,9 @@ Emacs package that displays available keybindings in popup ("C-e" . mwim-end-of-code-or-line) ("" . mwim-beginning-of-line-or-code) ("" . mwim-end-of-line-or-code)) - :ryo - ("a" mwim-beginning-of-code-or-line) - ("e" mwim-end-of-code-or-line)) -#+end_src - -** [[https://www.emacswiki.org/emacs/KeyChord][key-chord]] - -#+begin_src emacs-lisp -(use-package key-chord - :demand t - :config - (key-chord-mode 1) - (key-chord-define-global "jk" 'ryo-modal-mode) - (setq key-chord-one-key-delay 0 ; i don't need one-key chords for now - key-chord-two-keys-delay 0.005)) + :general (:states '(normal visual) + "0" 'mwim-beginning-of-code-or-line + "$" 'mwim-end-of-code-or-line)) #+end_src * Email @@ -1195,22 +1255,7 @@ Emacs package that displays available keybindings in popup See [[notmuch:id:87muuqsvci.fsf@fencepost.gnu.org][bug follow-up]]. #+begin_src emacs-lisp -(defun ab/notmuch () - "Delete other windows, then launch `notmuch'." - (interactive) - (require 'notmuch) - (delete-other-windows) - (notmuch)) - -;; (map! -;; :leader -;; :desc "notmuch" :n "m" #'ab/notmuch -;; (:desc "search" :prefix "/" -;; :desc "notmuch" :n "m" #'counsel-notmuch)) -#+end_src - -#+begin_src emacs-lisp -(defvar ab-maildir "~/mail") +(defvar amin-maildir "~/mail") (use-package sendmail ;; :ensure nil @@ -1249,8 +1294,15 @@ See [[notmuch:id:87muuqsvci.fsf@fencepost.gnu.org][bug follow-up]]. (setq mml-secure-openpgp-encrypt-to-self t mml-secure-openpgp-sign-with-sender t)) +(defun amin/notmuch () + "Delete other windows, then launch `notmuch'." + (interactive) + (delete-other-windows) + (notmuch)) + (use-package notmuch - :ryo ("SPC m" ab/notmuch) + :general (amin--leader-keys "m" 'amin/notmuch) + :commands notmuch :config (setq notmuch-hello-sections '(notmuch-hello-insert-header @@ -1263,18 +1315,27 @@ See [[notmuch:id:87muuqsvci.fsf@fencepost.gnu.org][bug follow-up]]. '("Subject" "To" "Cc" "Date" "List-Id" "X-RT-Originator") notmuch-hello-thousands-separator "," notmuch-fcc-dirs - '(("amin@aminb.org" . "amin/Sent") - ("amin@gnu.org" . "gnu/Sent") - ("abandali@uwaterloo.ca" . "\"uwaterloo/Sent Items\"") - ("mab@gnu.org" . "gnu/Sent") - ("aminb@gnu.org" . "gnu/Sent") - (".*" . "sent")) + '(("amin@aminb.org" . "amin/Sent") + ("amin@gnu.org" . "gnu/Sent") + ("abandali@uwaterloo.ca" . "\"uwaterloo/Sent Items\"") + ("mab@gnu.org" . "gnu/Sent") + ("aminb@gnu.org" . "gnu/Sent") + (".*" . "sent")) notmuch-search-result-format - '(("date" . "%12s ") - ("count" . "%-7s ") + '(("date" . "%12s ") + ("count" . "%-7s ") ("authors" . "%-40s ") ("subject" . "%s ") - ("tags" . "(%s)"))) + ("tags" . "(%s)")) + notmuch-saved-searches + '((:name "inbox" :query "tag:inbox" :key "i") + (:name "unread" :query "tag:unread" :key "u") + (:name "latest" :query "tag:latest" :key "l") + (:name "encrypted" :query "tag:encrypted" :key "e") + (:name "flagged" :query "tag:flagged" :key "f") + (:name "sent" :query "tag:sent" :key "s") + (:name "drafts" :query "tag:draft" :key "d") + (:name "all mail" :query "*" :key "a"))) ;; (add-hook 'visual-fill-column-mode-hook ;; (lambda () ;; (when (string= major-mode 'notmuch-message-mode) @@ -1282,32 +1343,14 @@ See [[notmuch:id:87muuqsvci.fsf@fencepost.gnu.org][bug follow-up]]. ;; (set! :evil-state 'notmuch-message-mode 'insert) ;; (advice-add #'notmuch-bury-or-kill-this-buffer ;; :override #'kill-this-buffer) + (evil-collection-define-key 'normal 'notmuch-common-keymap + "c" (lambda () + "Compose new mail and prompt for sender" + (interactive) + (let ((current-prefix-arg t)) + (call-interactively #'notmuch-mua-new-mail)))) :bind - (:map notmuch-hello-mode-map - ("g" . notmuch-poll-and-refresh-this-buffer) - ("u" . (lambda () - "Search for `unread' tagged messages" - (interactive) - (notmuch-hello-search "tag:unread"))) - ("i" . (lambda () - "Search for `inbox' tagged messages" - (interactive) - (notmuch-hello-search "tag:inbox"))) - ("l" . (lambda () - "Search for `latest' tagged messages" - (interactive) - (notmuch-hello-search "tag:latest"))) - ("e" . (lambda () - "Search for `encrypted' tagged messages" - (interactive) - (notmuch-hello-search "tag:encrypted"))) - ("M" . (lambda () - "Compose new mail and prompt for sender" - (interactive) - (let ((current-prefix-arg t)) - (call-interactively #'notmuch-mua-new-mail))))) (:map notmuch-search-mode-map - ("g" . notmuch-poll-and-refresh-this-buffer) ("k" . (lambda () "Mark message read" (interactive) @@ -1337,8 +1380,8 @@ See [[notmuch:id:87muuqsvci.fsf@fencepost.gnu.org][bug follow-up]]. (notmuch-tree-archive-thread)))) ) -;; (use-package counsel-notmuch -;; :commands counsel-notmuch) +(use-package counsel-notmuch + :general (amin--leader-keys "/m" 'counsel-notmuch)) (after! notmuch-crypto (setq notmuch-crypto-process-mime t)) @@ -1350,7 +1393,7 @@ See [[notmuch:id:87muuqsvci.fsf@fencepost.gnu.org][bug follow-up]]. ;; (notmuch-tree-mode . emacs)))) (after! recentf - (add-to-list 'recentf-exclude (expand-file-name ab-maildir))) + (add-to-list 'recentf-exclude (expand-file-name amin-maildir))) #+end_src ** supercite @@ -1422,7 +1465,7 @@ Display how long it took to load the init file. #+begin_src emacs-lisp (message "Loading %s...done (%.3fs)" user-init-file (float-time (time-subtract (current-time) - ab--before-user-init-time))) + amin--before-user-init-time))) #+end_src * Footer