;; '(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=
'auto-compile-inhibit-compile-detached-git-head))
#+end_src
-*** TODO [[https://github.com/Kungsgeten/ryo-modal][ryo-modal]]
+*** [[https://github.com/noctuid/general.el][general]]
#+begin_quote
Roll your own modal mode
#+end_quote
-*** [[https://github.com/ch11ng/exwm][EXWM]] (window manager)
-
-#+begin_src emacs-lisp :tangle no
-(use-package exwm
+#+begin_src emacs-lisp
+(use-package general
:demand t
:config
- (require 'exwm-config)
-
- ;; Set the initial workspace number.
- (setq exwm-workspace-number 4)
-
- ;; Make class name the buffer name, truncating beyond 50 characters
- (defun exwm-rename-buffer ()
- (interactive)
- (exwm-workspace-rename-buffer
- (concat exwm-class-name ":"
- (if (<= (length exwm-title) 50) exwm-title
- (concat (substring exwm-title 0 49) "...")))))
- (add-hook 'exwm-update-class-hook 'exwm-rename-buffer)
- (add-hook 'exwm-update-title-hook 'exwm-rename-buffer)
-
- ;; 's-R': Reset
- (exwm-input-set-key (kbd "s-R") #'exwm-reset)
- ;; 's-\': Switch workspace
- (exwm-input-set-key (kbd "s-\\") #'exwm-workspace-switch)
- ;; 's-N': Switch to certain workspace
- (dotimes (i 10)
- (exwm-input-set-key (kbd (format "s-%d" i))
- (lambda ()
- (interactive)
- (exwm-workspace-switch-create i))))
- ;; 's-SPC': Launch application
- ;; (exwm-input-set-key
- ;; (kbd "s-SPC")
- ;; (lambda (command)
- ;; (interactive (list (read-shell-command "➜ ")))
- ;; (start-process-shell-command command nil command)))
-
- (exwm-input-set-key (kbd "M-s-SPC") #'counsel-linux-app)
-
- ;; Shorten 'C-c C-q' to 'C-q'
- (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)
-
- ;; Line-editing shortcuts
- (setq exwm-input-simulation-keys
- '(;; movement
- ([?\C-b] . [left])
- ([?\M-b] . [C-left])
- ([?\C-f] . [right])
- ([?\M-f] . [C-right])
- ([?\C-p] . [up])
- ([?\C-n] . [down])
- ([?\C-a] . [home])
- ([?\C-e] . [end])
- ([?\M-v] . [prior])
- ([?\C-v] . [next])
- ([?\C-d] . [delete])
- ([?\C-k] . [S-end delete])
- ;; cut/copy/paste
- ;; ([?\C-w] . [?\C-x])
- ([?\M-w] . [?\C-c])
- ([?\C-y] . [?\C-v])
- ;; search
- ([?\C-s] . [?\C-f])))
-
- ;; Enable EXWM
- (exwm-enable)
-
- (add-hook 'exwm-init-hook #'exwm-config--fix/ido-buffer-window-other-frame)
-
- (require 'exwm-systemtray)
- (exwm-systemtray-enable)
-
- (require 'exwm-randr)
- (exwm-randr-enable)
-
- ;; (exwm-input-set-key
- ;; (kbd "s-<return>")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process "urxvt" nil "urxvt")))
-
- ;; (exwm-input-set-key
- ;; (kbd "s-SPC") ;; rofi doesn't properly launch programs when started from emacs
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process-shell-command "rofi-run" nil "rofi -show run -display-run '> ' -display-window ' 🗔 '")))
-
- ;; (exwm-input-set-key
- ;; (kbd "s-/")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process-shell-command "rofi-win" nil "rofi -show window -display-run '> ' -display-window ' 🗔 '")))
-
- ;; (exwm-input-set-key
- ;; (kbd "M-SPC")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process "rofi-pass" nil "rofi-pass")))
-
- ;; (exwm-input-set-key
- ;; (kbd "<XF86AudioMute>")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process-shell-command "pamixer" nil "pamixer --toggle-mute")))
-
- ;; (exwm-input-set-key
- ;; (kbd "<XF86AudioLowerVolume>")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process-shell-command "pamixer" nil "pamixer --allow-boost --decrease 5")))
-
- ;; (exwm-input-set-key
- ;; (kbd "<XF86AudioRaiseVolume>")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process-shell-command "pamixer" nil "pamixer --allow-boost --increase 5")))
-
- ;; (exwm-input-set-key
- ;; (kbd "<XF86AudioPlay>")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process-shell-command "mpc" nil "mpc toggle")))
-
- ;; (exwm-input-set-key
- ;; (kbd "<XF86AudioPrev>")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process-shell-command "mpc" nil "mpc prev")))
-
- ;; (exwm-input-set-key
- ;; (kbd "<XF86AudioNext>")
- ;; (lambda ()
- ;; (interactive)
- ;; (start-process-shell-command "mpc" nil "mpv next")))
-
- (defun ab--exwm-pasystray ()
- "A command used to start pasystray."
- (interactive)
- (if (executable-find "pasystray")
- (progn
- (message "EXWM: starting pasystray ...")
- (start-process-shell-command "pasystray" nil "pasystray --notify=all"))
- (message "EXWM: pasystray is not installed, abort!")))
-
- (add-hook 'exwm-init-hook #'ab--exwm-pasystray)
-
- (exwm-input-set-key
- (kbd "s-t")
- (lambda ()
- (interactive)
- (exwm-floating-toggle-floating)))
-
- (exwm-input-set-key
- (kbd "s-f")
- (lambda ()
- (interactive)
- (exwm-layout-toggle-fullscreen)))
-
- (exwm-input-set-key
- (kbd "s-w")
- (lambda ()
- (interactive)
- (kill-buffer (current-buffer))))
-
- (exwm-input-set-key
- (kbd "s-q")
- (lambda ()
- (interactive)
- (exwm-manage--kill-client))))
-#+end_src
-
-**** sxhkdrc
-:PROPERTIES:
-:header-args+: :tangle ~/.config/sxhkd/sxhkdrc :mkdirp yes
-:END:
-
-#+begin_src conf :tangle no
-# terminal emulator
-super + Return
- urxvt
-
-# program launcher
-super + space
- rofi -show run -display-run '> ' -display-window ' 🗔 '
-
-# window finder
-super + slash
- rofi -show window -display-run '> ' -display-window ' 🗔 '
-
-# password manager
-alt + space
- rofi-pass
-
-# make sxhkd reload its configuration files:
-super + Escape
- pkill -USR1 -x sxhkd
-
-# volume {up,down}
-XF86Audio{Raise,Lower}Volume
- pamixer --allow-boost --{in,de}crease 5
-
-# mute
-XF86AudioMute
- pamixer --toggle-mute
-
-# playback control
-XF86Audio{Play,Prev,Next}
- mpc {toggle,prev,next}
-
-# Toggle keyboard layout
-# super + F7
-# toggle-layout
+ (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
-# Toggle Xfce presentation mode
-# XF86LaunchB
-# toggle-presentation-mode
+*** evil
-# monitor brightness
-XF86MonBrightness{Up,Down}
- light -{A,U} 5
+#+begin_src emacs-lisp
+(use-package evil
+ :demand t
+ :hook (view-mode . evil-motion-state)
+ :config (evil-mode 1))
+#+end_src
-super + apostrophe
- rofi-light
+#+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
*** [[https://orgmode.org/][Org mode]]
#+begin_src emacs-lisp
(setq org-src-tab-acts-natively t
org-src-preserve-indentation nil
- org-edit-src-content-indentation 0)
+ 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)
+(add-hook 'org-mode-hook 'org-indent-mode)
+(use-package htmlize)
+(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)
:defer t
:bind (("s-g" . magit-status)
("C-x g" . magit-status)
#+begin_src emacs-lisp
(use-package ivy
+ :defer 1
:bind
(:map ivy-minibuffer-map
([escape] . keyboard-escape-quit)
#+begin_src emacs-lisp
(use-package swiper
+ :general (:states 'normal "/" 'swiper)
:bind (([remap isearch-forward] . swiper)
([remap isearch-backward] . swiper)))
#+end_src
#+begin_src emacs-lisp
(use-package counsel
:defer 1
+ :general (ab--leader-keys
+ "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)
(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
-** [[https://github.com/leanprover/lean-mode][Lean]]
+** [[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
+
+** [[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://leanprover.github.io][Lean]] (with [[https://github.com/leanprover/lean-mode][lean-mode]])
#+begin_src emacs-lisp
(use-package lean-mode
:defer 1
:config (which-key-mode))
#+end_src
+
+** [[https://github.com/seagle0128/doom-modeline][doom-modeline]]
+
+#+begin_src emacs-lisp
+(use-package doom-modeline
+ :demand t
+ :config (setq doom-modeline-height 32)
+ :hook (after-init . doom-modeline-init))
+#+end_src
+
+** [[https://github.com/11111000000/tao-theme-emacs][tao-theme]]
+
+#+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
+
* 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
#'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)
: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\"")
("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)
"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)
("S" . (lambda ()
"Mark message as spam"
(interactive)
- (notmuch-search-tag '("-unread" "-inbox" "+spam"))
+ (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" "+spam"))
+ (notmuch-tree-tag '("-unread" "-inbox" "-webmasters" "+spam"))
(notmuch-tree-archive-thread))))
)
(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