]> git.armaanb.net Git - config.org.git/blob - config.org
xmodmap: only tangle on frost
[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/community/community"
905   export KISS_PATH="$KISS_PATH:$HOME/repos/mid/ports"
906
907   export CFLAGS="-O3 -pipe -march=native"
908   export CXXFLAGS="$CFLAGS"
909   export MAKEFLAGS="-j$(nproc)"
910   export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig"
911
912   export XDG_DESKTOP_DIR="/dev/null"
913   export XDG_DOCUMENTS_DIR="$HOME/documents"
914   export XDG_DOWNLOAD_DIR="$HOME/downloads"
915   export XDG_MUSIC_DIR="$HOME/music"
916   export XDG_PICTURES_DIR="$HOME/pictures"
917   export XDG_VIDEOS_DIR="$HOME/videos"
918 #+end_src
919 *** Aliases
920 **** SSH
921 #+begin_src shell :tangle ~/.config/ash/ashrc
922   alias bhoji-drop='ssh -p 23 root@armaanb.net'
923   alias irc='ssh root@armaanb.net -t abduco -A irc catgirl freenode'
924   alias union='ssh 192.168.1.18'
925   alias mine='ssh -p 23 root@pickupserver.cc'
926   alias tcf='ssh root@204.48.23.68'
927   alias ngmun='ssh root@157.245.89.25'
928   alias prox='ssh root@192.168.1.224'
929   alias ncq='ssh root@143.198.123.17'
930   alias envs='ssh acheam@envs.net'
931 #+end_src
932 **** File management
933 #+begin_src shell :tangle ~/.config/ash/ashrc
934   alias ls='LC_COLLATE=C ls -lh --group-directories-first'
935   alias la='ls -A'
936   alias df='df -h / /boot'
937   alias du='du -h'
938   alias free='free -m'
939   alias cp='cp -riv'
940   alias rm='rm -iv'
941   alias mv='mv -iv'
942   alias ln='ln -v'
943   alias grep='grep -in'
944   alias mkdir='mkdir -pv'
945   alias lanex='java -jar ~/.local/share/lxc/lanxchange.jar'
946   emacs() { $EDITOR "$@" & }
947   alias vim="emacs"
948 #+end_src
949 **** System management
950 #+begin_src shell :tangle ~/.config/ash/ashrc
951   alias crontab='crontab-argh'
952   alias sudo='doas'
953   alias pasu='git -C ~/.password-store push'
954   alias yadu='yadm add -u && yadm commit -m "Updated `date -Iseconds`" && \
955     yadm push'
956 #+end_src
957 **** Networking
958 #+begin_src shell :tangle ~/.config/ash/ashrc
959   alias ping='ping -c 10'
960   alias gps='gpg --keyserver keyserver.ubuntu.com --search-keys'
961   alias gpp='gpg --keyserver keyserver.ubuntu.com --recv-key'
962   alias plan='T=$(mktemp) && \
963           rsync root@armaanb.net:/etc/finger/plan.txt "$T" && \
964           TT=$(mktemp) && \
965           head -n -2 $T > $TT && \
966           /bin/nvim $TT && \
967           echo >> "$TT" && \
968           echo "Last updated: $(date -R)" >> "$TT" && \
969           fold -sw 72 "$TT" > "$T"| \
970           rsync "$T" root@armaanb.net:/etc/finger/plan.txt && \
971           rm -f "$T"'
972 #+end_src
973 **** Virtual machines, chroots
974 #+begin_src shell :tangle ~/.config/ash/ashrc
975   alias ckiss="doas chrooter ~/Virtual/kiss"
976   alias cdebian="doas chrooter ~/Virtual/debian bash"
977   alias cwindows='devour qemu-system-x86_64 \
978     -smp 3 \
979     -cpu host \
980     -enable-kvm \
981     -m 3G \
982     -device VGA,vgamem_mb=64 \
983     -device intel-hda \
984     -device hda-duplex \
985     -net nic \
986     -net user,smb=/home/armaa/Public \
987     -drive format=qcow2,file=/home/armaa/Virtual/windows.qcow2'
988 #+end_src
989 **** Latin
990 #+begin_src shell :tangle ~/.config/ash/ashrc
991   alias words='gen-shell -c "words"'
992   alias words-e='gen-shell -c "words ~E"'
993 #+end_src
994 **** Other
995 #+begin_src shell :tangle ~/.config/ash/ashrc
996   alias bigrandomfile='dd if=/dev/urandom of=1GB-urandom bs=1M count=1024 \
997     iflag=fullblock'
998   alias bigboringfile='dd if=/dev/zero of=1GB-zero bs=1M count=1024 \
999     iflag=fullblock'
1000   alias ytmusic="youtube-dl -x --add-metadata  --audio-format aac \
1001     --restrict-filenames -o '%(title)s.%(ext)s'"
1002   alias bc='bc -l'
1003 #+end_src
1004 ** MPV
1005 Make MPV play a little bit smoother.
1006 #+begin_src conf :tangle ~/.config/mpv/mpv.conf
1007   ytdl-format="bestvideo[height<=?1080]+bestaudio/best"
1008   hwdec=auto-copy
1009 #+end_src
1010 ** Inputrc
1011 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!.
1012 #+begin_src conf :tangle ~/.inputrc
1013   set editing-mode emacs
1014 #+end_src
1015 ** Git
1016 *** User
1017 #+begin_src conf :tangle ~/.gitconfig
1018   [user]
1019   name = Armaan Bhojwani
1020   email = me@armaanb.net
1021   signingkey = 0FEB9471E19C49C60CFBEB133C9ED82FFE788E4A
1022 #+end_src
1023 *** Init
1024 #+begin_src conf :tangle ~/.gitconfig
1025   [init]
1026   defaultBranch = main
1027 #+end_src
1028 *** GPG
1029 #+begin_src conf :tangle ~/.gitconfig
1030   [gpg]
1031   program = gpg
1032 #+end_src
1033 *** Sendemail
1034 #+begin_src conf :tangle ~/.gitconfig
1035   [sendemail]
1036   smtpserver = smtp.mailbox.org
1037   smtpuser = me@armaanb.net
1038   smtpencryption = ssl
1039   smtpserverport = 465
1040   confirm = auto
1041 #+end_src
1042 *** Submodule
1043 #+begin_src conf :tangle ~/.gitconfig
1044   [submodule]
1045   recurse = true
1046 #+end_src
1047 *** Aliases
1048 #+begin_src conf :tangle ~/.gitconfig
1049   [alias]
1050   stat = diff --stat
1051   sclone = clone --depth 1
1052   sclean = clean -dfX
1053   a = add
1054   aa = add .
1055   c = commit
1056   quickfix = commit . --amend --no-edit
1057   p = push
1058   subup = submodule update --remote
1059   loc = diff --stat 4b825dc642cb6eb9a060e54bf8d69288fbee4904 # Empty hash
1060   pushnc = push -o skip-ci
1061 #+end_src
1062 *** Commit
1063 #+begin_src conf :tangle ~/.gitconfig
1064   [commit]
1065   gpgsign = true
1066   verbose = true
1067 #+end_src
1068 ** Zathura
1069 The best document reader!
1070 *** Options
1071 #+begin_src conf :tangle ~/.config/zathura/zathurarc
1072   map <C-i> recolor
1073   map <A-b> toggle_statusbar
1074   set selection-clipboard clipboard
1075   set scroll-step 200
1076
1077   set window-title-basename "true"
1078   set selection-clipboard "clipboard"
1079 #+end_src
1080 *** Colors
1081 #+begin_src conf :tangle ~/.config/zathura/zathurarc
1082   set default-bg         "#000000"
1083   set default-fg         "#ffffff"
1084   set render-loading     true
1085   set render-loading-bg  "#000000"
1086   set render-loading-fg  "#ffffff"
1087
1088   set recolor-lightcolor "#000000" # bg
1089   set recolor-darkcolor  "#ffffff" # fg
1090   set recolor            "true"
1091 #+end_src
1092 ** Xresources
1093 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.
1094 #+begin_src conf :tangle ~/.Xresources
1095   ! special
1096   ,*.foreground:   #ffffff
1097   ,*.background:   #000000
1098   ,*.cursorColor:  #ffffff
1099
1100   ! black
1101   ,*.color0:       #000000
1102   ,*.color8:       #555555
1103
1104   ! red
1105   ,*.color1:       #ff8059
1106   ,*.color9:       #ffa0a0
1107
1108   ! green
1109   ,*.color2:       #00fc50
1110   ,*.color10:      #88cf88
1111
1112   ! yellow
1113   ,*.color3:       #eecc00
1114   ,*.color11:      #d2b580
1115
1116   ! blue
1117   ,*.color4:       #29aeff
1118   ,*.color12:      #92baff
1119
1120   ! magenta
1121   ,*.color5:       #feacd0
1122   ,*.color13:      #e0b2d6
1123
1124   ! cyan
1125   ,*.color6:       #00d3d0
1126   ,*.color14:      #a0bfdf
1127
1128   ! white
1129   ,*.color7:       #eeeeee
1130   ,*.color15:      #dddddd
1131 #+end_src
1132 ** Tmux
1133 I use tmux in order to keep my st build light. Still learning how it works.
1134 #+begin_src conf :tangle ~/.tmux.conf
1135   set -g status off
1136   set -g mouse on
1137   set-option -g history-limit 50000
1138   set-window-option -g mode-keys vi
1139   bind-key -T copy-mode-vi 'v' send -X begin-selection
1140   bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard'
1141 #+end_src
1142 ** GPG
1143 *** Config
1144 #+begin_src conf :tangle ~/.gnupg/gpg.conf
1145   default-key 3C9ED82FFE788E4A
1146   use-agent
1147 #+end_src
1148 *** Agent
1149 #+begin_src conf :tangle ~/.gnupg/gpg-agent.conf
1150   pinentry-program /sbin/pinentry-fltk
1151   max-cache-ttl 600
1152   default-cache-ttl 600
1153   allow-emacs-pinentry
1154 #+end_src
1155 ** Xmodmap
1156 #+begin_src conf (if (eq system-name "frost.armaanb.net") ":tangle ~/.config/xmodmap")
1157   ! Unmap left super
1158   clear mod4
1159
1160   ! Turn right alt into super
1161   remove mod1 = Alt_R
1162   add mod4 = Alt_R
1163
1164   ! Swap caps and control
1165   remove Lock = Caps_Lock
1166   remove Control = Control_L
1167   remove Lock = Control_L
1168   remove Control = Caps_Lock
1169   keysym Control_L = Caps_Lock
1170   keysym Caps_Lock = Control_L
1171   add Lock = Caps_Lock
1172   add Control = Control_L
1173 #+end_src