;; '(not free-vars unresolved noruntime lexical make-local))
#+end_src
+** whoami
+
+#+begin_src emacs-lisp
+(setq user-full-name "Amin Bandali"
+ user-mail-address "amin@aminb.org")
+#+end_src
+
** Package management
*** No =package.el=
#+begin_src emacs-lisp
(require 'use-package)
-(if nil ; set to t when need to debug init
+(if nil ; set to t when need to debug init
(setq use-package-verbose t
use-package-expand-minimally nil
use-package-compute-statistics t
(setq body `(after! ,next ,@body)))
body)
((listp features)
- `(after! (:all ,@features) ,@body)))))
+ `(after! (:all ,@features) ,@body)))))
#+end_src
* Core
version-control t)
#+end_src
+*** Auto revert
+
+Enable automatic reloading of changed buffers and files.
+
+#+begin_src emacs-lisp
+(global-auto-revert-mode 1)
+(setq auto-revert-verbose nil
+ global-auto-revert-non-file-buffers t)
+#+end_src
+
+*** Always use space for indentation
+
+#+begin_src emacs-lisp
+(setq-default
+ indent-tabs-mode nil
+ require-final-newline t
+ tab-width 4)
+#+end_src
+
** Packages
The packages in this section are absolutely essential to my everyday
(auto-compile-on-load-mode)
(auto-compile-on-save-mode)
(setq auto-compile-display-buffer nil
- auto-compile-mode-line-counter t
- auto-compile-source-recreate-deletes-dest t
- auto-compile-toggle-deletes-nonlib-dest t
- auto-compile-update-autoloads t)
+ auto-compile-mode-line-counter t
+ auto-compile-source-recreate-deletes-dest t
+ auto-compile-toggle-deletes-nonlib-dest t
+ auto-compile-update-autoloads t)
(add-hook 'auto-compile-inhibit-compile-hook
'auto-compile-inhibit-compile-detached-git-head))
#+end_src
-*** [[https://github.com/noctuid/general.el][general]]
+*** [[https://github.com/Kungsgeten/ryo-modal][ryo-modal]]
#+begin_quote
Roll your own modal mode
#+end_quote
#+begin_src emacs-lisp
-(use-package general
- :demand t
+(use-package ryo-modal
+ :commands ryo-modal-mode
+ :bind ("M-m" . ryo-modal-mode)
+ :after which-key
:config
- (general-evil-setup t)
-
- (general-override-mode)
-
- (general-create-definer
- ab--mode-leader-keys
- :keymaps 'override
- :states '(emacs normal visual motion insert)
- :non-normal-prefix "C-,"
- :prefix ",")
-
- (general-create-definer
- ab--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)
- :config (evil-mode 1))
-#+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))
+ (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)))
#+end_src
*** [[https://orgmode.org/][Org mode]]
In short, my favourite way of life.
#+begin_src emacs-lisp
-(setq org-src-tab-acts-natively t
- org-src-preserve-indentation nil
- org-edit-src-content-indentation 0
- org-html-doctype "html5"
- org-html-html5-fancy t)
-(add-hook 'org-mode-hook 'org-indent-mode)
-(use-package htmlize)
+(use-package org
+ :ryo ("SPC b t" org-babel-tangle)
+ :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)
+ :hook (org-mode . org-indent-mode))
+(use-package htmlize
+ :after org)
+(use-package org-notmuch
+ :after (:any org notmuch))
#+end_src
*** [[https://magit.vc/][Magit]]
#+begin_src emacs-lisp
(use-package magit
- :general (ab--leader-keys "g s" 'magit-status)
+ :ryo ("SPC" (("g s" magit-status)))
:defer t
:bind (("s-g" . magit-status)
- ("C-x g" . magit-status)
+ ("C-x g" . magit-status)
("C-x M-g" . magit-dispatch-popup))
:config
(magit-add-section-hook 'magit-status-sections-hook
([S-up] . ivy-previous-history-element)
([S-down] . ivy-next-history-element)
("DEL" . ivy-backward-delete-char))
+ :ryo ("SPC ," ivy-switch-buffer)
:config
(setq ivy-wrap t)
(ivy-mode 1))
#+begin_src emacs-lisp
(use-package swiper
- :general (:states 'normal "/" 'swiper)
+ :ryo
+ ("SPC /" swiper)
+ ("s" swiper)
:bind (([remap isearch-forward] . swiper)
- ([remap isearch-backward] . swiper)))
+ ([remap isearch-backward] . swiper)))
#+end_src
**** Counsel
#+begin_src emacs-lisp
(use-package counsel
:defer 1
- :general (ab--leader-keys
- "f r" 'counsel-recentf
- "SPC" 'counsel-M-x
- "." 'counsel-find-file)
+ :ryo
+ ("SPC" (("f r" 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)
:map minibuffer-local-map
- ("C-r" . counsel-minibuffer-history))
+ ("C-r" . counsel-minibuffer-history))
:config
(counsel-mode 1)
(defalias 'locate #'counsel-locate))
(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
(global-undo-tree-mode)
- (setq undo-tree-mode-lighter ""))
+ (setq undo-tree-mode-lighter ""
+ undo-tree-auto-save-history t))
#+end_src
* Editing
:defer 5
:bind
(:map company-active-map
- ([tab] . company-complete-common-or-cycle))
+ ([tab] . company-complete-common-or-cycle))
:custom
(company-idle-delay 0.3)
(company-minimum-prefix-length 1)
(global-company-mode t))
#+end_src
-** Customizations
-
-#+begin_src emacs-lisp
-(ab--leader-keys
- "b s" 'save-buffer
- "b b" 'ivy-switch-buffer
- "," 'ivy-switch-buffer
- "b k" 'kill-this-buffer
- "q q" 'evil-save-and-quit)
-#+end_src
-
* Syntax and spell checking
#+begin_src emacs-lisp
(use-package flycheck
#+end_src
* Programming modes
-** Alloy
+** [[http://alloytools.org][Alloy]] (with [[https://github.com/dwwmmn/alloy-mode][alloy-mode]])
#+begin_src emacs-lisp
(use-package alloy-mode
:config (setq alloy-basic-offset 2))
#+end_src
-** Coq
+** [[https://coq.inria.fr][Coq]] (with [[https://github.com/ProofGeneral/PG][Proof General]])
#+begin_src emacs-lisp
(use-package proof-site ; Proof General
:load-path "lib/proof-site/generic/")
#+end_src
-** [[https://github.com/leanprover/lean-mode][Lean]]
+** [[https://leanprover.github.io][Lean]] (with [[https://github.com/leanprover/lean-mode][lean-mode]])
#+begin_src emacs-lisp
(use-package lean-mode
:bind (:map lean-mode-map
- ("S-SPC" . company-complete)))
+ ("S-SPC" . company-complete)))
#+end_src
** Haskell
:config
(setq haskell-indentation-layout-offset 4
haskell-indentation-left-offset 4
- flycheck-checker 'haskell-hlint
- flycheck-disabled-checkers '(haskell-stack-ghc haskell-ghc)))
+ flycheck-checker 'haskell-hlint
+ flycheck-disabled-checkers '(haskell-stack-ghc haskell-ghc)))
#+end_src
*** [[https://github.com/jyp/dante][dante]]
#+begin_src emacs-lisp
(use-package hlint-refactor
:bind (:map hlint-refactor-mode-map
- ("C-c l b" . hlint-refactor-refactor-buffer)
- ("C-c l r" . hlint-refactor-refactor-at-point))
+ ("C-c l b" . hlint-refactor-refactor-buffer)
+ ("C-c l r" . hlint-refactor-refactor-at-point))
:hook (haskell-mode . hlint-refactor-mode))
#+end_src
(new-old-code ""))
(save-excursion
(switch-to-buffer (get-file-buffer fname))
- (goto-char (point-min))
- (forward-line (1- fline))
+ (goto-char (point-min))
+ (forward-line (1- fline))
(beginning-of-line)
(setf bline (point))
(when (or hs-lint-replace-without-ask
:config (which-key-mode))
#+end_src
-** doom-modeline
+** [[https://github.com/seagle0128/doom-modeline][doom-modeline]]
#+begin_src emacs-lisp
(use-package doom-modeline
:hook (after-init . doom-modeline-init))
#+end_src
-** tao-theme
+** [[https://github.com/11111000000/tao-theme-emacs][tao-theme]]
-#+begin_src emacs-lisp
+#+begin_src emacs-lisp :tangle no
(use-package tao-theme
:demand t
:config (load-theme 'tao-yang t))
#+end_src
+** [[https://github.com/maio/eink-emacs][eink-theme]]
+
+#+begin_src emacs-lisp
+(load-theme 'eink t)
+#+end_src
+
+** [[https://github.com/bbatsov/crux][crux]]
+
+#+begin_src emacs-lisp
+(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))))
+#+end_src
+
+** [[https://github.com/alezost/mwim.el][mwim]]
+
+#+begin_src emacs-lisp
+(use-package mwim
+ :bind (("C-a" . mwim-beginning-of-code-or-line)
+ ("C-e" . mwim-end-of-code-or-line)
+ ("<home>" . mwim-beginning-of-line-or-code)
+ ("<end>" . 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))
+#+end_src
+
* Email
-** notmuch
+** [[https://notmuchmail.org][notmuch]]
+
+See [[notmuch:id:87muuqsvci.fsf@fencepost.gnu.org][bug follow-up]].
#+begin_src emacs-lisp
(defun ab/notmuch ()
(delete-other-windows)
(notmuch))
-;; (ab--leader-keys
-;; "m" 'ab/notmuch
-;; "s" 'save-buffer
-;; "SPC" 'counsel-M-x)
-
;; (map!
;; :leader
;; :desc "notmuch" :n "m" #'ab/notmuch
;; :ensure nil
:config
(setq sendmail-program "/usr/bin/msmtp"
+ ; message-sendmail-extra-arguments '("-v" "-d")
mail-specify-envelope-from t
mail-envelope-from 'header))
message-send-mail-function 'message-send-mail-with-sendmail
message-sendmail-envelope-from 'header
message-directory "drafts"
- message-user-fqdn "fencepost.gnu.org")
+ message-user-fqdn "aminb.org")
(add-hook 'message-mode-hook
(lambda () (setq fill-column 65
message-fill-column 65)))
#'flyspell-mode)
;; (add-hook 'notmuch-message-mode-hook #'+doom-modeline|set-special-modeline)
;; TODO: is there a way to only run this when replying and not composing?
- (add-hook 'notmuch-message-mode-hook
- (lambda () (progn
- (newline)
- (newline)
- (forward-line -1)
- (forward-line -1))))
+ ;; (add-hook 'notmuch-message-mode-hook
+ ;; (lambda () (progn
+ ;; (newline)
+ ;; (newline)
+ ;; (forward-line -1)
+ ;; (forward-line -1))))
;; (add-hook 'message-setup-hook
;; #'mml-secure-message-sign-pgpmime)
)
mml-secure-openpgp-sign-with-sender t))
(use-package notmuch
- :general (ab--leader-keys "m" 'ab/notmuch)
+ :ryo ("SPC m" ab/notmuch)
:config
(setq notmuch-hello-sections
'(notmuch-hello-insert-header
notmuch-hello-insert-alltags)
notmuch-search-oldest-first nil
notmuch-show-all-tags-list t
+ notmuch-message-headers ; see bug follow-up above
+ '("Subject" "To" "Cc" "Date" "List-Id" "X-RT-Originator")
notmuch-hello-thousands-separator ","
notmuch-fcc-dirs
'(("amin@aminb.org" . "amin/Sent")
("abandali@uwaterloo.ca" . "\"uwaterloo/Sent Items\"")
- ("amin.bandali@uwaterloo.ca" . "\"uwaterloo/Sent Items\"")
+ ("mab@gnu.org" . "gnu/Sent")
("aminb@gnu.org" . "gnu/Sent")
- (".*" . "sent")))
+ (".*" . "sent"))
+ notmuch-search-result-format
+ '(("date" . "%12s ")
+ ("count" . "%-7s ")
+ ("authors" . "%-40s ")
+ ("subject" . "%s ")
+ ("tags" . "(%s)")))
;; (add-hook 'visual-fill-column-mode-hook
;; (lambda ()
;; (when (string= major-mode 'notmuch-message-mode)
;; :override #'kill-this-buffer)
:bind
(:map notmuch-hello-mode-map
- ("g" . notmuch-poll-and-refresh-this-buffer)
- ("i" . (lambda ()
- "Search for `inbox' tagged messages"
- (interactive)
- (notmuch-hello-search "tag:inbox")))
- ("u" . (lambda ()
- "Search for `unread' tagged messages"
- (interactive)
- (notmuch-hello-search "tag:unread")))
- ("M" . (lambda ()
- "Compose new mail and prompt for sender"
- (interactive)
- (let ((current-prefix-arg t))
- (call-interactively #'notmuch-mua-new-mail)))))
+ ("g" . notmuch-poll-and-refresh-this-buffer)
+ ("i" . (lambda ()
+ "Search for `inbox' tagged messages"
+ (interactive)
+ (notmuch-hello-search "tag:inbox")))
+ ("u" . (lambda ()
+ "Search for `unread' tagged messages"
+ (interactive)
+ (notmuch-hello-search "tag:unread")))
+ ("l" . (lambda ()
+ "Search for `latest tagged messages"
+ (interactive)
+ (notmuch-hello-search "tag:latest")))
+ ("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)
- (notmuch-search-tag '("-unread"))
- ;; (notmuch-search-archive-thread)
- (notmuch-search-next-thread)))
- ("u" . (lambda ()
- "Mark message unread"
- (interactive)
- (notmuch-search-tag '("+unread"))
- (notmuch-search-next-thread)))
- ("K" . (lambda ()
- "Mark message deleted"
- (interactive)
- (notmuch-search-tag '("-unread" "-inbox" "+deleted"))
- (notmuch-search-archive-thread)))
- ("S" . (lambda ()
- "Mark message as spam"
- (interactive)
- (notmuch-search-tag '("-unread" "-inbox" "-webmasters" "+spam"))
- (notmuch-search-archive-thread))))
+ ("g" . notmuch-poll-and-refresh-this-buffer)
+ ("k" . (lambda ()
+ "Mark message read"
+ (interactive)
+ (notmuch-search-tag '("-unread"))
+ ;; (notmuch-search-archive-thread)
+ (notmuch-search-next-thread)))
+ ("u" . (lambda ()
+ "Mark message unread"
+ (interactive)
+ (notmuch-search-tag '("+unread"))
+ (notmuch-search-next-thread)))
+ ("K" . (lambda ()
+ "Mark message deleted"
+ (interactive)
+ (notmuch-search-tag '("-unread" "-inbox" "+deleted"))
+ (notmuch-search-archive-thread)))
+ ("S" . (lambda ()
+ "Mark message as spam"
+ (interactive)
+ (notmuch-search-tag '("-unread" "-inbox" "-webmasters" "+spam"))
+ (notmuch-search-archive-thread))))
(:map notmuch-tree-mode-map ; TODO: additional bindings
- ("S" . (lambda ()
- "Mark message as spam"
- (interactive)
- (notmuch-tree-tag '("-unread" "-inbox" "-webmasters" "+spam"))
- (notmuch-tree-archive-thread))))
+ ("S" . (lambda ()
+ "Mark message as spam"
+ (interactive)
+ (notmuch-tree-tag '("-unread" "-inbox" "-webmasters" "+spam"))
+ (notmuch-tree-archive-thread))))
)
;; (use-package counsel-notmuch
(add-to-list 'recentf-exclude (expand-file-name ab-maildir)))
#+end_src
+** supercite
+
+#+begin_src emacs-lisp :tangle no
+(use-package supercite
+ :commands sc-cite-original
+ :init
+ (add-hook 'mail-citation-hook 'sc-cite-original)
+
+ (defun sc-remove-existing-signature ()
+ (save-excursion
+ (goto-char (region-beginning))
+ (when (re-search-forward message-signature-separator (region-end) t)
+ (delete-region (match-beginning 0) (region-end)))))
+
+ (add-hook 'mail-citation-hook 'sc-remove-existing-signature)
+
+ (defun sc-remove-if-not-mailing-list ()
+ (unless (assoc "list-id" sc-mail-info)
+ (setq attribution sc-default-attribution
+ citation (concat sc-citation-delimiter
+ sc-citation-separator))))
+
+ (add-hook 'sc-attribs-postselect-hook 'sc-remove-if-not-mailing-list)
+
+ :config
+ (defun sc-fill-if-different (&optional prefix)
+ "Fill the region bounded by `sc-fill-begin' and point.
+Only fill if optional PREFIX is different than
+`sc-fill-line-prefix'. If `sc-auto-fill-region-p' is nil, do not
+fill region. If PREFIX is not supplied, initialize fill
+variables. This is useful for a regi `begin' frame-entry."
+ (if (not prefix)
+ (setq sc-fill-line-prefix ""
+ sc-fill-begin (line-beginning-position))
+ (if (and sc-auto-fill-region-p
+ (not (string= prefix sc-fill-line-prefix)))
+ (let ((fill-prefix sc-fill-line-prefix))
+ (unless (or (string= fill-prefix "")
+ (save-excursion
+ (goto-char sc-fill-begin)
+ (or (looking-at ">+ +")
+ (< (length
+ (buffer-substring (point)
+ (line-end-position)))
+ 65))))
+ (fill-region sc-fill-begin (line-beginning-position)))
+ (setq sc-fill-line-prefix prefix
+ sc-fill-begin (line-beginning-position)))))
+nil))
+#+end_src
+
+* Blogging
+** [[https://ox-hugo.scripter.co][ox-hugo]]
+
+#+begin_src emacs-lisp
+(use-package ox-hugo
+ :after ox)
+#+end_src
+
* Post initialization
:PROPERTIES:
:CUSTOM_ID: post-initialization