]> git.armaanb.net Git - config.org.git/blob - config.org
spectrwm: add quirk for pinentry
[config.org.git] / config.org
1 #+TITLE: System Configuration
2 #+DESCRIPTION: Personal system configuration in org-mode format.
3 #+AUTHOR: Armaan Bhojwani
4 #+EMAIL: me@armaanb.net
5
6 * Welcome
7 Welcome to my system configuration! This file contains my Emacs configuration, but also my config files for many of the other programs on my system!
8 ** Compatability
9 I am currently using Emacs 27.2 on Linux, so some settings and packages may not be available for older versions of Emacs. This is a purely personal configuration, so while I can guarantee that it works on my setup, it might not work for you.
10 ** Choices
11 I chose to create a powerful, yet not overly heavy Emacs configuration. Things like a fancy modeline, icons, or LSP mode do not increase my productivity, and create visual clutter, and thus have been excluded.
12
13 Another important choice has been to integrate Emacs into a large part of my computing environment (see [[*Emacs OS]]). I use email, IRC, RSS, et cetera, all through Emacs which simplifies my workflow and creates an amazingly integrated environment.
14
15 Lastly, I use Evil mode. Modal keybindings are simpler and more ergonomic than standard Emacs style, and Vim keybindings are what I'm comfortable with and are pervasive throughout computing.
16 ** License
17 Released under the [[https://opensource.org/licenses/MIT][MIT license]] by Armaan Bhojwani, 2021. Note that many snippets are taken from online, and other sources, who are credited for their work near their contributions.
18 * Package management
19 ** Bootstrap straight.el
20 straight.el is really nice for managing package, and it integrates nicely with use-package. It uses the bootstrapping system defined here for installation.
21 #+begin_src emacs-lisp
22   (defvar native-comp-deferred-compilation-deny-list ())
23   (defvar bootstrap-version)
24   (let ((bootstrap-file
25          (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
26         (bootstrap-version 5))
27     (unless (file-exists-p bootstrap-file)
28       (with-current-buffer
29           (url-retrieve-synchronously
30            "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
31            'silent 'inhibit-cookies)
32         (goto-char (point-max))
33         (eval-print-last-sexp)))
34     (load bootstrap-file nil 'nomessage))
35 #+end_src
36 ** Replace package.el with straight
37 #+begin_src emacs-lisp
38   (straight-use-package 'use-package)
39   (setq straight-use-package-by-default t)
40 #+end_src
41 * Visual options
42 ** Theme
43 Use the Modus Operandi theme by Protesilaos Stavrou. Its the best theme for Emacs by far, because how clear and readable it is. It is highly customizable, but I just set a few options here.
44 #+begin_src emacs-lisp
45   (use-package modus-themes
46     :custom
47     (modus-themes-slanted-constructs t)
48     (modus-themes-bold-constructs t)
49     (modus-themes-mode-line '3d)
50     (modus-themes-scale-headings t)
51     (modus-themes-diffs 'desaturated)
52     :config (load-theme 'modus-vivendi t))
53 #+end_src
54 ** Typography
55 *** Font
56 JetBrains Mono is a great programming font with ligatures. The "NF" means that it has been patched with the [[https://www.nerdfonts.com/][Nerd Fonts]].
57 #+begin_src emacs-lisp
58   (add-to-list 'default-frame-alist '(font . "JetBrainsMonoNF-12"))
59 #+end_src
60 *** Ligatures
61 #+begin_src emacs-lisp
62   (use-package ligature
63     :straight (ligature :type git :host github :repo "mickeynp/ligature.el")
64     :config
65     (ligature-set-ligatures
66      '(prog-mode text-mode)
67      '("-|" "-~" "---" "-<<" "-<" "--" "->" "->>" "-->" "/=" "/=="
68        "/>" "//" "/*" "*>" "*/" "<-" "<<-" "<=>" "<=" "<|" "<||"
69        "<|||" "<|>" "<:" "<>" "<-<" "<<<" "<==" "<<=" "<=<" "<==>"
70        "<-|" "<<" "<~>" "<=|" "<~~" "<~" "<$>" "<$" "<+>" "<+" "</>"
71        "</" "<*" "<*>" "<->" "<!--" ":>" ":<" ":::" "::" ":?" ":?>"
72        ":=" "::=" "=>>" "==>" "=/=" "=!=" "=>" "===" "=:=" "==" "!=="
73        "!!" "!=" ">]" ">:" ">>-" ">>=" ">=>" ">>>" ">-" ">=" "&&&"
74        "&&" "|||>" "||>" "|>" "|]" "|}" "|=>" "|->" "|=" "||-" "|-"
75        "||=" "||" ".." ".?" ".=" ".-" "..<" "..." "+++" "+>" "++"
76        "[||]" "[<" "[|" "{|" "?." "?=" "?:" "##" "###" "####" "#["
77        "#{" "#=" "#!" "#:" "#_(" "#_" "#?" "#(" ";;" "_|_" "__" "~~"
78        "~~>" "~>" "~-" "~@" "$>" "^=" "]#"))
79     (global-ligature-mode t))
80 #+end_src
81 ** Line numbers
82 Display relative line numbers except in certain modes.
83 #+begin_src emacs-lisp
84   (global-display-line-numbers-mode)
85   (setq display-line-numbers-type 'relative)
86   (dolist (no-line-num '(term-mode-hook
87                          pdf-view-mode-hook
88                          shell-mode-hook
89                          org-mode-hook
90                          circe-mode-hook
91                          eshell-mode-hook))
92     (add-hook no-line-num (lambda () (display-line-numbers-mode 0))))
93 #+end_src
94 ** Highlight matching parenthesis
95 #+begin_src emacs-lisp
96   (use-package paren
97     :config (show-paren-mode)
98     :custom (show-paren-style 'parenthesis))
99 #+end_src
100 ** Modeline
101 *** Show current function
102 #+begin_src emacs-lisp
103   (which-function-mode)
104 #+end_src
105 *** Make position in file more descriptive
106 Show current column and file size.
107 #+begin_src emacs-lisp
108   (column-number-mode)
109   (size-indication-mode)
110 #+end_src
111 *** Hide minor modes
112 #+begin_src emacs-lisp
113   (use-package minions
114     :config (minions-mode))
115 #+end_src
116 ** Whitespace mode
117 Highlight whitespace and other bad text practices.
118 #+begin_src emacs-lisp
119   (use-package whitespace
120     :custom (whitespace-style '(face lines-tail)))
121   (dolist (hook '(prog-mode-hook))
122     (add-hook hook (lambda () (whitespace-mode 1))))
123 #+end_src
124 ** Highlight todo items in comments
125 +begin_src emacs-lisp
126   (use-package hl-todo
127     :straight (hl-todo :type git :host github :repo "tarsius/hl-todo")
128     :config (global-hl-todo-mode 1))
129 #+end_src
130 ** Blink cursor
131 #+begin_src emacs-lisp
132   (blink-cursor-mode)
133 #+end_src
134 ** Visual line mode
135 Soft wrap words and do operations by visual lines in some modes.
136 #+begin_src emacs-lisp
137   (dolist (hook '(text-mode-hook
138                   org-mode-hook
139                   markdown-mode-hook
140                   mu4e-view-mode-hook))
141     (add-hook hook (lambda () (visual-line-mode 1))))
142 #+end_src
143 ** Auto fill mode
144 #+begin_src emacs-lisp
145   (dolist (hook '(scdoc-mode-hook
146                   mu4e-compose-mode-hook))
147     (add-hook hook (lambda () (auto-fill-mode 1))))
148 #+end_src
149 ** Display number of matches in search
150 #+begin_src emacs-lisp
151   (use-package anzu
152     :config (global-anzu-mode)
153     :bind
154     ([remap query-replace] . anzu-query-replace)
155     ([remap query-replace-regexp] . anzu-query-replace-regexp))
156 #+end_src
157 *** TODO This config doesn't work right
158 ** Visual bell
159 Invert modeline color instead of audible bell or the standard visual bell.
160 #+begin_src emacs-lisp
161   (setq visible-bell nil
162         ring-bell-function
163         (lambda () (invert-face 'mode-line)
164           (run-with-timer 0.1 nil #'invert-face 'mode-line)))
165 #+end_src
166 * Evil mode
167 ** General
168 #+begin_src emacs-lisp
169   (use-package evil
170     :custom (select-enable-clipboard nil)
171     :config
172     (evil-mode)
173     (fset 'evil-visual-update-x-selection 'ignore) ;; Keep clipboard and register seperate
174     ;; Use visual line motions even outside of visual-line-mode buffers
175     (evil-global-set-key 'motion "j" 'evil-next-visual-line)
176     (evil-global-set-key 'motion "k" 'evil-previous-visual-line)
177     (global-set-key (kbd "<escape>") 'keyboard-escape-quit))
178 #+end_src
179 ** Evil collection
180 Evil bindings for tons of packages.
181 #+begin_src emacs-lisp
182   (use-package evil-collection
183     :after evil
184     :init (evil-collection-init)
185     :custom (evil-collection-setup-minibuffer t))
186 #+end_src
187 ** Surround
188 tpope prevails!
189 #+begin_src emacs-lisp
190   (use-package evil-surround
191     :config (global-evil-surround-mode))
192 #+end_src
193 ** Nerd commenter
194 Makes commenting super easy
195 #+begin_src emacs-lisp
196   (use-package evil-nerd-commenter
197     :bind (:map evil-normal-state-map
198                 ("gc" . evilnc-comment-or-uncomment-lines))
199     :custom (evilnc-invert-comment-line-by-line nil))
200 #+end_src
201 ** Undo redo
202 Fix the oopsies!
203 #+begin_src emacs-lisp
204   (use-package undo-fu
205     :config (evil-set-undo-system 'undo-fu))
206
207   (use-package undo-fu-session
208     :config (global-undo-fu-session-mode))
209 #+end_src
210 ** Number incrementing
211 Add back C-a/C-x bindings.
212 #+begin_src emacs-lisp
213   (use-package evil-numbers
214     :straight (evil-numbers :type git :host github :repo "juliapath/evil-numbers")
215     :bind (:map evil-normal-state-map
216                 ("C-M-a" . evil-numbers/inc-at-pt)
217                 ("C-M-x" . evil-numbers/dec-at-pt)))
218 #+end_src
219 ** Evil org
220 #+begin_src emacs-lisp
221   (use-package evil-org
222     :after org
223     :hook (org-mode . evil-org-mode)
224     :config
225     (evil-org-set-key-theme '(textobjects insert navigation shift todo)))
226
227   (use-package evil-org-agenda
228     :straight (:type built-in)
229     :after evil-org
230     :config (evil-org-agenda-set-keys))
231 #+end_src
232 * Org mode
233 ** General
234 #+begin_src emacs-lisp
235   (use-package org
236     :straight (:type built-in)
237     :commands (org-capture org-agenda)
238     :custom
239     (org-ellipsis " â–¾")
240     (org-agenda-start-with-log-mode t)
241     (org-agenda-files (quote ("~/Org/tasks.org" "~/Org/break.org")))
242     (org-log-done 'time)
243     (org-log-into-drawer t)
244     (org-src-tab-acts-natively t)
245     (org-src-fontify-natively t)
246     (org-startup-indented t)
247     (org-hide-emphasis-markers t)
248     (org-fontify-whole-block-delimiter-line nil)
249     (org-archive-default-command 'org-archive-to-archive-sibling)
250     :bind
251     ("C-c a" . org-agenda)
252     (:map evil-normal-state-map ("ga" . org-archive-subtree-default)))
253 #+end_src
254 ** Tempo
255 Define templates for lots of common structure elements. Mostly just used within this file.
256 #+begin_src emacs-lisp
257   (use-package org-tempo
258     :after org
259     :straight (:type built-in)
260     :config
261     (dolist (addition '(("el" . "src emacs-lisp")
262                         ("el" . "src emacs-lisp")
263                         ("sp" . "src conf :tangle ~/.spectrwm.conf")
264                         ("ash" . "src shell :tangle ~/.config/ash/ashrc")
265                         ("pi" . "src conf :tangle ~/.config/picom/picom.conf")
266                         ("git" . "src conf :tangle ~/.gitconfig")
267                         ("za" . "src conf :tangle ~/.config/zathura/zathurarc")
268                         ("xr" . "src conf :tangle ~/.Xresources")
269                         ("tm" . "src conf :tangle ~/.tmux.conf")
270                         ("gp" . "src conf :tangle ~/.gnupg/gpg.conf")
271                         ("ag" . "src conf :tangle ~/.gnupg/gpg-agent.conf")
272                         ("xm" . "src conf :tangle ~/.config/xmodmap")))
273       (add-to-list 'org-structure-template-alist addition)))
274 #+end_src
275 * Autocompletion
276 ** Ivy
277 A well balanced completion framework.
278 #+begin_src emacs-lisp
279   (use-package ivy
280     :bind (:map ivy-minibuffer-map
281            ("TAB" . ivy-alt-done))
282            (:map ivy-switch-buffer-map
283            ("M-d" . ivy-switch-buffer-kill))
284     :config (ivy-mode))
285 #+end_src
286 ** Ivy-rich
287 #+begin_src emacs-lisp
288   (use-package ivy-rich
289     :after (ivy counsel)
290     :config (ivy-rich-mode))
291 #+end_src
292 ** Counsel
293 Ivy everywhere.
294 #+begin_src emacs-lisp
295   (use-package counsel
296     :bind ("C-M-j" . 'counsel-switch-buffer)
297     :config (counsel-mode))
298 #+end_src
299 ** Remember frequent commands
300 #+begin_src emacs-lisp
301   (use-package ivy-prescient
302     :after counsel
303     :config
304     (prescient-persist-mode)
305     (ivy-prescient-mode))
306 #+end_src
307 * Emacs OS
308 ** RSS
309 Use elfeed for reading RSS. I have another file with all the feeds in it that I'd rather keep private.
310 #+begin_src emacs-lisp
311   (use-package elfeed
312     :bind (("C-c e" . elfeed))
313     :config (load "~/.emacs.d/feeds.el")
314     :bind (:map elfeed-search-mode-map ("C-c C-o" . 'elfeed-show-visit)))
315 #+end_src
316 ** Email
317 Use mu4e for reading emails.
318 Contexts are a not very well known feature of mu4e that makes it super easy to manage multiple accounts. Much better than some of the hacky methods and external packages that I've seen.
319 *** TODO Switch to mbsync
320 =offlineimap= really crappy (slow and requires python2), and I need to replace it with =mbsync=.
321 *** TODO Include mbsync/offlineimap config
322 *** TODO Split up and document this config a bit
323 *** Setup
324 #+begin_src emacs-lisp
325   (use-package smtpmail
326     :straight (:type built-in))
327   (use-package mu4e
328     :load-path "/usr/share/emacs/site-lisp/mu4e"
329     :straight (:build nil)
330     :bind (("C-c m" . mu4e))
331     :config
332     (setq user-full-name "Armaan Bhojwani"
333           smtpmail-local-domain "armaanb.net"
334           smtpmail-stream-type 'ssl
335           smtpmail-smtp-service '465
336           mu4e-change-filenames-when-moving t
337           mu4e-get-mail-command "offlineimap -q"
338           message-citation-line-format "On %a %d %b %Y at %R, %f wrote:\n"
339           message-citation-line-function 'message-insert-formatted-citation-line
340           mu4e-completing-read-function 'ivy-completing-read
341           mu4e-confirm-quit nil
342           mu4e-view-use-gnus t
343           mail-user-agent 'mu4e-user-agent
344           mu4e-context-policy 'pick-first
345           mu4e-contexts
346           `( ,(make-mu4e-context
347                :name "school"
348                :enter-func (lambda () (mu4e-message "Entering school context"))
349                :leave-func (lambda () (mu4e-message "Leaving school context"))
350                :match-func (lambda (msg)
351                              (when msg
352                                (string-match-p "^/school" (mu4e-message-field msg :maildir))))
353                :vars '((user-mail-address . "abhojwani22@nobles.edu")
354                        (mu4e-sent-folder . "/school/Sent")
355                        (mu4e-drafts-folder . "/school/Drafts")
356                        (mu4e-trash-folder . "/school/Trash")
357                        (mu4e-refile-folder . "/school/Archive")
358                        (message-cite-reply-position . above)
359                        (user-mail-address . "abhojwani22@nobles.edu")
360                        (smtpmail-smtp-user . "abhojwani22@nobles.edu")
361                        (smtpmail-smtp-server . "smtp.gmail.com")))
362              ,(make-mu4e-context
363                :name "personal"
364                :enter-func (lambda () (mu4e-message "Entering personal context"))
365                :leave-func (lambda () (mu4e-message "Leaving personal context"))
366                :match-func (lambda (msg)
367                              (when msg
368                                (string-match-p "^/personal" (mu4e-message-field msg :maildir))))
369                :vars '((mu4e-sent-folder . "/personal/Sent")
370                        (mu4e-drafts-folder . "/personal/Drafts")
371                        (mu4e-trash-folder . "/personal/Trash")
372                        (mu4e-refile-folder . "/personal/Archive")
373                        (user-mail-address . "me@armaanb.net")
374                        (message-cite-reply-position . below)
375                        (smtpmail-smtp-user . "me@armaanb.net")
376                        (smtpmail-smtp-server . "smtp.mailbox.org")))))
377     (add-to-list 'mu4e-bookmarks
378                  '(:name "Unified inbox"
379                          :query "maildir:\"/personal/INBOX\" or maildir:\"/school/INBOX\""
380                          :key ?b))
381     :hook ((mu4e-compose-mode . flyspell-mode)
382            (message-send-hook . (lambda () (unless (yes-or-no-p "Ya sure 'bout that?")
383                                              (signal 'quit nil))))))
384 #+end_src
385 *** Discourage Gnus from displaying HTML emails
386 #+begin_src emacs-lisp
387   (with-eval-after-load "mm-decode"
388     (add-to-list 'mm-discouraged-alternatives "text/html")
389     (add-to-list 'mm-discouraged-alternatives "text/richtext"))
390 #+end_src
391 ** Default browser
392 Set EWW as default browser except for multimedia which should open in MPV.
393 #+begin_src emacs-lisp
394   (defun browse-url-mpv (url &optional new-window)
395     "Ask MPV to load URL."
396     (interactive)
397     (start-process "mpv" "*mpv*" "mpv" url))
398
399   (setq browse-url-handlers
400         (quote
401          (("youtu\\.?be" . browse-url-mpv)
402           ("peertube.*" . browse-url-mpv)
403           ("vid.*" . browse-url-mpv)
404           ("vid.*" . browse-url-mpv)
405           ("*.mp4" . browse-url-mpv)
406           ("*.mp3" . browse-url-mpv)
407           ("*.ogg" . browse-url-mpv)
408           ("." . eww-browse-url)
409           )))
410 #+end_src
411 ** EWW
412 Some EWW enhancements.
413 *** Give buffer a useful name
414 #+begin_src emacs-lisp
415   ;; From https://protesilaos.com/dotemacs/
416   (defun prot-eww--rename-buffer ()
417     "Rename EWW buffer using page title or URL.
418         To be used by `eww-after-render-hook'."
419     (let ((name (if (eq "" (plist-get eww-data :title))
420                     (plist-get eww-data :url)
421                   (plist-get eww-data :title))))
422       (rename-buffer (format "*%s # eww*" name) t)))
423
424   (use-package eww
425     :straight (:type built-in)
426     :bind (("C-c w" . eww))
427     :hook (eww-after-render-hook prot-eww--rename-buffer))
428 #+end_src
429 *** Keybinding
430 #+begin_src emacs-lisp
431   (global-set-key (kbd "C-c w") 'eww)
432 #+end_src
433 ** IRC
434 Circe is a really nice IRC client that claims to be above RCIRC and below ERC in terms of features. ERC felt a bit messy and finicky to me, and Circe has all the features that I need. This setup gets the password for my bouncer (Pounce) instances via my =~/.authinfo.gpg= file.
435 #+begin_src emacs-lisp
436   (defun fetch-password (&rest params)
437     (require 'auth-source)
438     (let ((match (car (apply 'auth-source-search params))))
439       (if match
440           (let ((secret (plist-get match :secret)))
441             (if (functionp secret)
442                 (funcall secret)
443               secret))
444         (error "Password not found for %S" params))))
445
446   (use-package circe
447     :config
448     (enable-lui-track)
449     (enable-circe-color-nicks)
450     (setq circe-network-defaults '(("libera"
451                                     :host "irc.armaanb.net"
452                                     :nick "emacs"
453                                     :user "emacs"
454                                     :use-tls t
455                                     :port 6698
456                                     :pass (lambda (null) (fetch-password
457                                                           :login "emacs"
458                                                           :machine "irc.armaanb.net"
459                                                           :port 6698)))
460                                    ("oftc"
461                                     :host "irc.armaanb.net"
462                                     :nick "emacs"
463                                     :user "emacs"
464                                     :use-tls t
465                                     :port 6699
466                                     :pass (lambda (null) (fetch-password
467                                                           :login "emacs"
468                                                           :machine "irc.armaanb.net"
469                                                           :port 6699)))
470                                    ("tilde"
471                                     :host "irc.armaanb.net"
472                                     :nick "emacs"
473                                     :user "emacs"
474                                     :use-tls t
475                                     :port 6696
476                                     :pass (lambda (null) (fetch-password
477                                                           :login "emacs"
478                                                           :machine "irc.armaanb.net"
479                                                           :port 6696)))))
480     :custom (circe-default-part-message "goodbye!")
481     :bind (:map circe-mode-map ("C-c C-r" . circe-reconnect-all)))
482
483   (defun acheam-irc ()
484     "Open circe"
485     (interactive)
486     (if (get-buffer "irc.armaanb.net:6696")
487         (switch-to-buffer "irc.armaanb.net:6696")
488       (progn (switch-to-buffer "*scratch*")
489              (circe "libera")
490              (circe "oftc")
491              (circe "tilde"))))
492
493   (global-set-key (kbd "C-c i") 'acheam-irc)
494 #+end_src
495 ** Calendar
496 Still experimenting with this setup. Not sure if I will keep it, but it works well for seeing my calendar events. I use =vdirsyncer= to sync my calendar events which I'm really not happy with.
497 #+begin_src emacs-lisp
498   (defun sync-calendar ()
499     "Sync calendars with vdirsyncer"
500     (interactive)
501     (async-shell-command "vdirsyncer sync"))
502
503   (use-package calfw
504     :bind (:map cfw:calendar-mode-map ("C-S-u" . sync-calendar)))
505   (use-package calfw-ical)
506   (use-package calfw-org)
507
508   (defun acheam-calendar ()
509     "Open calendars"
510     (interactive)
511     (cfw:open-calendar-buffer
512      :contents-sources (list
513                         (cfw:org-create-source "Green")
514                         (cfw:ical-create-source
515                          "Personal"
516                          "~/.local/share/vdirsyncer/mailbox/Y2FsOi8vMC8zMQ.ics"
517                          "Gray")
518                         (cfw:ical-create-source
519                          "Personal"
520                          "~/.local/share/vdirsyncer/mailbox/Y2FsOi8vMC8zMQ.ics"
521                          "Red")
522                         (cfw:ical-create-source
523                          "School"
524                          "~/.local/share/vdirsyncer/school/abhojwani22@nobles.edu.ics"
525                          "Cyan"))
526      :view 'week))
527
528   (global-set-key (kbd "C-c c") 'acheam-calendar)
529 #+end_src
530 ** PDF reader
531 #+begin_src emacs-lisp
532   (use-package pdf-tools
533     :hook (pdf-view-mode . pdf-view-midnight-minor-mode))
534 #+end_src
535 * Emacs IDE
536 ** Python formatting
537 #+begin_src emacs-lisp
538   (use-package blacken
539     :hook (python-mode . blacken-mode)
540     :custom (blacken-line-length 79))
541
542 #+end_src
543 ** Strip trailing whitespace
544 #+begin_src emacs-lisp
545   (use-package ws-butler
546     :config (ws-butler-global-mode))
547 #+end_src
548 ** Flycheck
549 Automatic linting. I need to look into configuring this more.
550 #+begin_src emacs-lisp
551   (use-package flycheck
552     :config (global-flycheck-mode))
553 #+end_src
554 ** Project management
555 I never use this, but apparently its very powerful. Another item on my todo list.
556 #+begin_src emacs-lisp
557   (use-package projectile
558     :config (projectile-mode)
559     :custom ((projectile-completion-system 'ivy))
560     :bind-keymap
561     ("C-c p" . projectile-command-map)
562     :init
563     (when (file-directory-p "~/src")
564       (setq projectile-project-search-path '("~/src")))
565     (setq projectile-switch-project-action #'projectile-dired))
566
567   (use-package counsel-projectile
568     :after projectile
569     :config (counsel-projectile-mode))
570 #+end_src
571 ** Dired
572 The best file manager!
573 #+begin_src emacs-lisp
574   (use-package dired
575     :straight (:type built-in)
576     :commands (dired dired-jump)
577     :custom ((dired-listing-switches "-agho --group-directories-first"))
578     :config (evil-collection-define-key 'normal 'dired-mode-map
579               "h" 'dired-single-up-directory
580               "l" 'dired-single-buffer))
581
582   (use-package dired-single
583     :commands (dired dired-jump))
584
585   (use-package dired-open
586     :commands (dired dired-jump)
587     :custom (dired-open-extensions '(("png" . "feh")
588                                      ("mkv" . "mpv"))))
589
590   (use-package dired-hide-dotfiles
591     :hook (dired-mode . dired-hide-dotfiles-mode)
592     :config
593     (evil-collection-define-key 'normal 'dired-mode-map
594       "H" 'dired-hide-dotfiles-mode))
595 #+end_src
596 ** Git
597 *** Magit
598 A very good Git interface.
599 #+begin_src emacs-lisp
600   (use-package magit)
601 #+end_src
602 *** Email
603 #+begin_src emacs-lisp
604   (use-package piem)
605   (use-package git-email
606     :straight (git-email :repo "https://git.sr.ht/~yoctocell/git-email")
607     :config (git-email-piem-mode))
608 #+end_src
609 * General text editing
610 ** Indentation
611 Automatically indent after every change. I'm not sure how much I like this. It slows down the editor and code sometimes ends up in a half-indented state meaning I have to manually reformat using "==" anyways.
612 #+begin_src emacs-lisp
613   (use-package aggressive-indent
614     :config (global-aggressive-indent-mode))
615 #+end_src
616 ** Spell checking
617 Spell check in text mode, and in prog-mode comments.
618 #+begin_src emacs-lisp
619   (dolist (hook '(text-mode-hook
620                   markdown-mode-hook
621                   scdoc-mode-hook))
622     (add-hook hook (lambda () (flyspell-mode))))
623   (dolist (hook '(change-log-mode-hook log-edit-mode-hook))
624     (add-hook hook (lambda () (flyspell-mode -1))))
625   (add-hook 'prog-mode (lambda () (flyspell-prog mode)))
626   (setq ispell-silently-savep t)
627 #+end_src
628 ** Sane tab width
629 #+begin_src emacs-lisp
630   (setq-default tab-width 2)
631 #+end_src
632 ** Save place
633 Opens file where you left it.
634 #+begin_src emacs-lisp
635   (save-place-mode)
636 #+end_src
637 ** Writing mode
638 Distraction free writing a la junegunn/goyo.
639 #+begin_src emacs-lisp
640   (use-package olivetti
641     :bind ("C-c o" . olivetti-mode))
642 #+end_src
643 ** Abbreviations
644 Abbreviate things! I just use this for things like my email address and copyright notice.
645 #+begin_src emacs-lisp
646   (setq abbrev-file-name "~/.emacs.d/abbrevs.el")
647   (setq save-abbrevs 'silent)
648   (setq-default abbrev-mode t)
649 #+end_src
650 ** TRAMP
651 #+begin_src emacs-lisp
652   (setq tramp-default-method "ssh")
653 #+end_src
654 ** Follow version controlled symlinks
655 #+begin_src emacs-lisp
656   (setq vc-follow-symlinks t)
657 #+end_src
658 ** Open file as root
659 #+begin_src emacs-lisp
660   (defun doas-edit (&optional arg)
661     "Edit currently visited file as root.
662
663     With a prefix ARG prompt for a file to visit.
664     Will also prompt for a file to visit if current
665     buffer is not visiting a file.
666
667     Modified from Emacs Redux."
668     (interactive "P")
669     (if (or arg (not buffer-file-name))
670         (find-file (concat "/doas:root@localhost:"
671                            (ido-read-file-name "Find file(as root): ")))
672       (find-alternate-file (concat "/doas:root@localhost:" buffer-file-name))))
673
674     (global-set-key (kbd "C-x C-r") #'doas-edit)
675 #+end_src
676 ** Markdown mode
677 #+begin_src emacs-lisp
678   (use-package markdown-mode)
679 #+end_src
680 ** scdoc mode
681 Get it for yourself at https://git.armaanb.net/scdoc
682 #+begin_src emacs-lisp
683   (add-to-list 'load-path "~/src/scdoc-mode")
684   (autoload 'scdoc-mode "scdoc-mode" "Major mode for editing scdoc files" t)
685   (add-to-list 'auto-mode-alist '("\\.scd\\'" . scdoc-mode))
686 #+end_src
687 * Keybindings
688 ** Switch windows
689 #+begin_src emacs-lisp
690   (use-package ace-window
691     :bind ("M-o" . ace-window))
692 #+end_src
693 ** Kill current buffer
694 Makes "C-x k" binding faster.
695 #+begin_src emacs-lisp
696   (substitute-key-definition 'kill-buffer 'kill-buffer-and-window global-map)
697 #+end_src
698 * Other settings
699 ** OpenSCAD syntax
700 #+begin_src emacs-lisp
701   (use-package scad-mode)
702 #+end_src
703 ** Control backup and lock files
704 Stop backup files from spewing everywhere.
705 #+begin_src emacs-lisp
706   (setq backup-directory-alist `(("." . "~/.emacs.d/backups"))
707         create-lockfiles nil)
708 #+end_src
709 ** Make yes/no easier
710 #+begin_src emacs-lisp
711   (defalias 'yes-or-no-p 'y-or-n-p)
712 #+end_src
713 ** Move customize file
714 No more clogging up init.el.
715 #+begin_src emacs-lisp
716   (setq custom-file "~/.emacs.d/custom.el")
717   (load custom-file)
718 #+end_src
719 ** Better help
720 #+begin_src emacs-lisp
721   (use-package helpful
722     :commands (helpful-callable helpful-variable helpful-command helpful-key)
723     :custom
724     (counsel-describe-function-function #'helpful-callable)
725     (counsel-describe-variable-function #'helpful-variable)
726     :bind
727     ([remap describe-function] . counsel-describe-function)
728     ([remap describe-command] . helpful-command)
729     ([remap describe-variable] . counsel-describe-variable)
730     ([remap describe-key] . helpful-key))
731 #+end_src
732 ** GPG
733 #+begin_src emacs-lisp
734   (use-package epa-file
735     :straight (:type built-in)
736     :custom
737     (epa-file-select-keys nil)
738     (epa-file-encrypt-to '("me@armaanb.net"))
739     (password-cache-expiry (* 60 15)))
740
741   (use-package pinentry
742     :config (pinentry-start))
743 #+end_src
744 ** Pastebin
745 #+begin_src emacs-lisp
746   (use-package 0x0
747     :straight (0x0 :type git :repo "https://git.sr.ht/~zge/nullpointer-emacs")
748     :custom (0x0-default-service 'envs))
749 #+end_src
750 *** TODO Replace this with uploading to my own server
751 Similar to the ufile alias in my ashrc
752 ** Automatically clean buffers
753 Automatically close unused buffers (except those of Circe) at midnight.
754 #+begin_src emacs-lisp
755   (midnight-mode)
756   (add-to-list 'clean-buffer-list-kill-never-regexps (lambda (buffer-name)
757                                                        (with-current-buffer buffer-name
758                                                          (derived-mode-p 'lui-mode))))
759 #+end_src
760 * Tangles
761 ** Spectrwm
762 Spectrwm is a really awesome window manager! Would highly recommend.
763 *** General settings
764 #+begin_src conf :tangle ~/.spectrwm.conf
765   workspace_limit = 5
766   warp_pointer = 1
767   modkey = Mod4
768   autorun = ws[1]:/home/armaa/src/bin/autostart
769 #+end_src
770 *** Bar
771 Disable the bar by default (it can still be brought back up with MOD+b). The font just needs to be set to something that you have installed, otherwise spectrwm won't launch.
772 #+begin_src conf :tangle ~/.spectrwm.conf
773   bar_enabled = 0
774   bar_font = xos4 JetBrains Mono:pixelsize=14:antialias=true # any installed font
775 #+end_src
776 *** Keybindings
777 I'm not a huge fan of how spectrwm handles keybindings, probably my biggest gripe with it.
778 **** WM actions
779 #+begin_src conf :tangle ~/.spectrwm.conf
780   program[term] = st -e tmux
781   program[notif] = /home/armaa/src/bin/setter status
782   program[pass] = /home/armaa/src/bin/passmenu
783   program[lock] = slock
784
785   bind[notif] = MOD+n
786   bind[pass] = MOD+Shift+p
787 #+end_src
788 **** Media keys
789 #+begin_src conf :tangle ~/.spectrwm.conf
790   program[paup] = /home/armaa/src/bin/setter audio +5
791   program[padown] = /home/armaa/src/bin/setter audio -5
792   program[pamute] = /home/armaa/src/bin/setter audio
793   program[brigup] = /home/armaa/src/bin/setter brightness +10%
794   program[brigdown] = /home/armaa/src/bin/setter brightness 10%-
795
796   bind[padown] = XF86AudioLowerVolume
797   bind[paup] = XF86AudioRaiseVolume
798   bind[pamute] = XF86AudioMute
799   bind[brigdown] = XF86MonBrightnessDown
800   bind[brigup] = XF86MonBrightnessUp
801 #+end_src
802 **** HJKL
803 #+begin_src conf :tangle ~/.spectrwm.conf
804   program[h] = xdotool keyup h key --clearmodifiers Left
805   program[j] = xdotool keyup j key --clearmodifiers Down
806   program[k] = xdotool keyup k key --clearmodifiers Up
807   program[l] = xdotool keyup l key --clearmodifiers Right
808
809   bind[h] = MOD + Control + h
810   bind[j] = MOD + Control + j
811   bind[k] = MOD + Control + k
812   bind[l] = MOD + Control + l
813 #+end_src
814 **** Programs
815 #+begin_src conf :tangle ~/.spectrwm.conf
816   program[email] = emacsclient -ce '(progn (switch-to-buffer "*scratch*") (mu4e))'
817   program[irc] = emacsclient -ce '(acheam-irc)'
818   program[rss] = emacsclient -ce '(elfeed)'
819   program[calendar] = emacsclient -ce '(acheam-calendar)'
820   program[calc] = emacsclient -ce '(progn (calc) (windmove-up) (delete-window))'
821   program[emacs] = emacsclient -c
822
823   bind[email] = MOD+Control+1
824   bind[irc] = MOD+Control+2
825   bind[rss] = MOD+Control+3
826   bind[calendar] = MOD+Control+4
827   bind[calc] = MOD+Control+5
828   bind[emacs] = MOD+Control+Return
829 #+end_src
830 *** Quirks
831 Float some specific programs by default.
832 #+begin_src conf :tangle ~/.spectrwm.conf
833   quirk[Castle Menu] = FLOAT
834   quirk[momen] = FLOAT
835   quirk[pinentry-fltk] = FLOAT
836 #+end_src
837 ** Ash
838 *** Options
839 Use the vi editing mode. I still haven't found a good way to show visual feedback of the current mode. Ideally the cursor would change to a beam when in insert mode, and a box when in normal mode.
840 #+begin_src conf :tangle ~/.config/ash/ashrc
841   set -o vi
842 #+end_src
843 *** Functions
844 **** Finger
845 #+begin_src shell :tangle ~/.config/ash/ashrc
846   finger() {
847       user=$(echo "$1" | cut -f 1 -d '@')
848       host=$(echo "$1" | cut -f 2 -d '@')
849       echo $user | nc "$host" 79
850   }
851 #+end_src
852 **** Upload to ftp.armaanb.net
853 #+begin_src shell :tangle ~/.config/ash/ashrc
854   _uprint() {
855       echo "https://l.armaanb.net/$(basename "$1")" | tee /dev/tty | xclip -sel c
856   }
857
858   _uup() {
859       rsync "$1" "root@armaanb.net:/var/ftp/pub/$2" --chmod 644
860   }
861
862   ufile() {
863       _uup "$1" "$2"
864       _uprint "$1"
865   }
866
867   uclip() {
868       tmp=$(mktemp)
869       xclip -o -sel c >> "$tmp"
870       basetmp=$(echo "$tmp" | tail -c +5)
871       _uup "$tmp" "$basetmp"
872       _uprint "$basetmp"
873       rm -f "$tmp"
874   }
875 #+end_src
876 *** Exports
877 #+begin_src shell :tangle ~/.config/ash/ashrc
878   export EDITOR="emacsclient -c"
879   export VISUAL="$EDITOR"
880   export TERM=xterm-256color # for compatability
881
882   export GPG_TTY="$(tty)"
883   export MANPAGER='nvim +Man!'
884   export PAGER='less'
885   export GTK_USE_PORTAL=1
886   export CDPATH=:~
887
888   export PATH="/home/armaa/.local/bin:$PATH" # prioritize .local/bin
889   export PATH="/home/armaa/src/bin:$PATH" # prioritize my bin
890   export PATH="//home/armaa/src/bin/bin:$PATH" # prioritize my bins
891   export PATH="$PATH:/usr/sbin"
892
893   export LC_ALL="en_US.UTF-8"
894   export LC_CTYPE="en_US.UTF-8"
895   export LANGUAGE="en_US.UTF-8"
896   export TZ="America/New_York"
897
898   export KISS_PATH=""
899   export KISS_PATH="$KISS_PATH:$HOME/repos/personal"
900   export KISS_PATH="$KISS_PATH:$HOME/repos/bin/bin"
901   export KISS_PATH="$KISS_PATH:$HOME/repos/main/core"
902   export KISS_PATH="$KISS_PATH:$HOME/repos/main/extra"
903   export KISS_PATH="$KISS_PATH:$HOME/repos/main/xorg"
904   export KISS_PATH="$KISS_PATH:$HOME/repos/main/xorg"
905   export KISS_PATH="$KISS_PATH:$HOME/repos/community/community"
906   export KISS_PATH="$KISS_PATH:$HOME/repos/mid/ports"
907
908   export CFLAGS="-O3 -pipe -march=native"
909   export CXXFLAGS="$CFLAGS"
910   export MAKEFLAGS="-j$(nproc)"
911   export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig"
912
913   export XDG_DESKTOP_DIR="/dev/null"
914   export XDG_DOCUMENTS_DIR="$HOME/documents"
915   export XDG_DOWNLOAD_DIR="$HOME/downloads"
916   export XDG_MUSIC_DIR="$HOME/music"
917   export XDG_PICTURES_DIR="$HOME/pictures"
918   export XDG_VIDEOS_DIR="$HOME/videos"
919 #+end_src
920 *** Aliases
921 **** SSH
922 #+begin_src shell :tangle ~/.config/ash/ashrc
923   alias bhoji-drop='ssh -p 23 root@armaanb.net'
924   alias irc='ssh root@armaanb.net -t abduco -A irc catgirl freenode'
925   alias union='ssh 192.168.1.18'
926   alias mine='ssh -p 23 root@pickupserver.cc'
927   alias tcf='ssh root@204.48.23.68'
928   alias ngmun='ssh root@157.245.89.25'
929   alias prox='ssh root@192.168.1.224'
930   alias ncq='ssh root@143.198.123.17'
931   alias envs='ssh acheam@envs.net'
932 #+end_src
933 **** File management
934 #+begin_src shell :tangle ~/.config/ash/ashrc
935   alias ls='LC_COLLATE=C ls -lh --group-directories-first'
936   alias la='ls -A'
937   alias df='df -h / /boot'
938   alias du='du -h'
939   alias free='free -m'
940   alias cp='cp -riv'
941   alias rm='rm -iv'
942   alias mv='mv -iv'
943   alias ln='ln -v'
944   alias grep='grep -in'
945   alias mkdir='mkdir -pv'
946   alias lanex='java -jar ~/.local/share/lxc/lanxchange.jar'
947   emacs() { $EDITOR "$@" & }
948   alias vim="emacs"
949 #+end_src
950 **** System management
951 #+begin_src shell :tangle ~/.config/ash/ashrc
952   alias crontab='crontab-argh'
953   alias sudo='doas'
954   alias pasu='git -C ~/.password-store push'
955   alias yadu='yadm add -u && yadm commit -m "Updated `date -Iseconds`" && \
956     yadm push'
957 #+end_src
958 **** Networking
959 #+begin_src shell :tangle ~/.config/ash/ashrc
960   alias ping='ping -c 10'
961   alias gps='gpg --keyserver keyserver.ubuntu.com --search-keys'
962   alias gpp='gpg --keyserver keyserver.ubuntu.com --recv-key'
963   alias plan='T=$(mktemp) && \
964           rsync root@armaanb.net:/etc/finger/plan.txt "$T" && \
965           TT=$(mktemp) && \
966           head -n -2 $T > $TT && \
967           /bin/nvim $TT && \
968           echo >> "$TT" && \
969           echo "Last updated: $(date -R)" >> "$TT" && \
970           fold -sw 72 "$TT" > "$T"| \
971           rsync "$T" root@armaanb.net:/etc/finger/plan.txt && \
972           rm -f "$T"'
973 #+end_src
974 **** Virtual machines, chroots
975 #+begin_src shell :tangle ~/.config/ash/ashrc
976   alias ckiss="doas chrooter ~/Virtual/kiss"
977   alias cdebian="doas chrooter ~/Virtual/debian bash"
978   alias cwindows='devour qemu-system-x86_64 \
979     -smp 3 \
980     -cpu host \
981     -enable-kvm \
982     -m 3G \
983     -device VGA,vgamem_mb=64 \
984     -device intel-hda \
985     -device hda-duplex \
986     -net nic \
987     -net user,smb=/home/armaa/Public \
988     -drive format=qcow2,file=/home/armaa/Virtual/windows.qcow2'
989 #+end_src
990 **** Latin
991 #+begin_src shell :tangle ~/.config/ash/ashrc
992   alias words='gen-shell -c "words"'
993   alias words-e='gen-shell -c "words ~E"'
994 #+end_src
995 **** Other
996 #+begin_src shell :tangle ~/.config/ash/ashrc
997   alias bigrandomfile='dd if=/dev/urandom of=1GB-urandom bs=1M count=1024 \
998     iflag=fullblock'
999   alias bigboringfile='dd if=/dev/zero of=1GB-zero bs=1M count=1024 \
1000     iflag=fullblock'
1001   alias ytmusic="youtube-dl -x --add-metadata  --audio-format aac \
1002     --restrict-filenames -o '%(title)s.%(ext)s'"
1003   alias bc='bc -l'
1004 #+end_src
1005 ** MPV
1006 Make MPV play a little bit smoother.
1007 #+begin_src conf :tangle ~/.config/mpv/mpv.conf
1008   ytdl-format="bestvideo[height<=?1080]+bestaudio/best"
1009   hwdec=auto-copy
1010 #+end_src
1011 ** Inputrc
1012 This file is used for any GNU Readline programs. I use Emacs editing mode mostly because of one annoyance which is that to clear the screen using ^L, you have to be in normal mode which is a pain. If there is a way to rebind this, I'd love to know!.
1013 #+begin_src conf :tangle ~/.inputrc
1014   set editing-mode emacs
1015 #+end_src
1016 ** Git
1017 *** User
1018 #+begin_src conf :tangle ~/.gitconfig
1019   [user]
1020   name = Armaan Bhojwani
1021   email = me@armaanb.net
1022   signingkey = 0FEB9471E19C49C60CFBEB133C9ED82FFE788E4A
1023 #+end_src
1024 *** Init
1025 #+begin_src conf :tangle ~/.gitconfig
1026   [init]
1027   defaultBranch = main
1028 #+end_src
1029 *** GPG
1030 #+begin_src conf :tangle ~/.gitconfig
1031   [gpg]
1032   program = gpg
1033 #+end_src
1034 *** Sendemail
1035 #+begin_src conf :tangle ~/.gitconfig
1036   [sendemail]
1037   smtpserver = smtp.mailbox.org
1038   smtpuser = me@armaanb.net
1039   smtpencryption = ssl
1040   smtpserverport = 465
1041   confirm = auto
1042 #+end_src
1043 *** Submodule
1044 #+begin_src conf :tangle ~/.gitconfig
1045   [submodule]
1046   recurse = true
1047 #+end_src
1048 *** Aliases
1049 #+begin_src conf :tangle ~/.gitconfig
1050   [alias]
1051   stat = diff --stat
1052   sclone = clone --depth 1
1053   sclean = clean -dfX
1054   a = add
1055   aa = add .
1056   c = commit
1057   quickfix = commit . --amend --no-edit
1058   p = push
1059   subup = submodule update --remote
1060   loc = diff --stat 4b825dc642cb6eb9a060e54bf8d69288fbee4904 # Empty hash
1061   pushnc = push -o skip-ci
1062 #+end_src
1063 *** Commit
1064 #+begin_src conf :tangle ~/.gitconfig
1065   [commit]
1066   gpgsign = true
1067   verbose = true
1068 #+end_src
1069 ** Zathura
1070 The best document reader!
1071 *** Options
1072 #+begin_src conf :tangle ~/.config/zathura/zathurarc
1073   map <C-i> recolor
1074   map <A-b> toggle_statusbar
1075   set selection-clipboard clipboard
1076   set scroll-step 200
1077
1078   set window-title-basename "true"
1079   set selection-clipboard "clipboard"
1080 #+end_src
1081 *** Colors
1082 #+begin_src conf :tangle ~/.config/zathura/zathurarc
1083   set default-bg         "#000000"
1084   set default-fg         "#ffffff"
1085   set render-loading     true
1086   set render-loading-bg  "#000000"
1087   set render-loading-fg  "#ffffff"
1088
1089   set recolor-lightcolor "#000000" # bg
1090   set recolor-darkcolor  "#ffffff" # fg
1091   set recolor            "true"
1092 #+end_src
1093 ** Xresources
1094 Modus operandi theme. No program I use checks for anything beyond foreground and background, but hey, it can't hurt to have all the colors in there.
1095 #+begin_src conf :tangle ~/.Xresources
1096   ! special
1097   ,*.foreground:   #ffffff
1098   ,*.background:   #000000
1099   ,*.cursorColor:  #ffffff
1100
1101   ! black
1102   ,*.color0:       #000000
1103   ,*.color8:       #555555
1104
1105   ! red
1106   ,*.color1:       #ff8059
1107   ,*.color9:       #ffa0a0
1108
1109   ! green
1110   ,*.color2:       #00fc50
1111   ,*.color10:      #88cf88
1112
1113   ! yellow
1114   ,*.color3:       #eecc00
1115   ,*.color11:      #d2b580
1116
1117   ! blue
1118   ,*.color4:       #29aeff
1119   ,*.color12:      #92baff
1120
1121   ! magenta
1122   ,*.color5:       #feacd0
1123   ,*.color13:      #e0b2d6
1124
1125   ! cyan
1126   ,*.color6:       #00d3d0
1127   ,*.color14:      #a0bfdf
1128
1129   ! white
1130   ,*.color7:       #eeeeee
1131   ,*.color15:      #dddddd
1132 #+end_src
1133 ** Tmux
1134 I use tmux in order to keep my st build light. Still learning how it works.
1135 #+begin_src conf :tangle ~/.tmux.conf
1136   set -g status off
1137   set -g mouse on
1138   set-option -g history-limit 50000
1139   set-window-option -g mode-keys vi
1140   bind-key -T copy-mode-vi 'v' send -X begin-selection
1141   bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard'
1142 #+end_src
1143 ** GPG
1144 *** Config
1145 #+begin_src conf :tangle ~/.gnupg/gpg.conf
1146   default-key 3C9ED82FFE788E4A
1147   use-agent
1148 #+end_src
1149 *** Agent
1150 #+begin_src conf :tangle ~/.gnupg/gpg-agent.conf
1151   pinentry-program /sbin/pinentry-fltk
1152   max-cache-ttl 600
1153   default-cache-ttl 600
1154   allow-emacs-pinentry
1155 #+end_src
1156 ** Xmodmap
1157 #+begin_src conf :tangle ~/.config/xmodmap
1158   !
1159   ! Unmap left super
1160   !
1161   clear mod4
1162
1163   !
1164   ! Turn right alt into super
1165   !
1166   remove mod1 = Alt_R
1167   add mod4 = Alt_R
1168 #+end_src
1169 #+begin_src conf (if (eq system-name "frost.armaanb.net") ":tangle ~/.config/xmodmap")
1170   !
1171   ! Swap caps and control
1172   !
1173   remove Lock = Caps_Lock
1174   remove Control = Control_L
1175   remove Lock = Control_L
1176   remove Control = Caps_Lock
1177   keysym Control_L = Caps_Lock
1178   keysym Caps_Lock = Control_L
1179   add Lock = Caps_Lock
1180   add Control = Control_L
1181 #+end_src