Initial commit
authorArmaan Bhojwani <me@armaanb.net>
Sun, 28 Mar 2021 01:27:20 +0000 (21:27 -0400)
committerArmaan Bhojwani <me@armaanb.net>
Sun, 28 Mar 2021 01:27:20 +0000 (21:27 -0400)
Migrating from seperate dotfiles repo

.build.yml [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README [new file with mode: 0644]
config.org [new file with mode: 0644]

diff --git a/.build.yml b/.build.yml
new file mode 100644 (file)
index 0000000..cf387f7
--- /dev/null
@@ -0,0 +1,22 @@
+image: alpine/edge
+secrets:
+  - 5752743f-34af-46a8-aad9-b5d31e305b3b
+packages:
+  - rsync
+  - git
+  - hugo
+sources:
+  - https://git.sr.ht/~armaan/armaanb.net
+triggers:
+  - action: email
+    condition: failure
+    to: me@armaanb.net
+tasks:
+  - get-emacs-config: |
+      cd armaanb.net
+      ./bin/emacs-get
+  - build-http: |
+      cd armaanb.net
+      hugo --minify
+  - deploy: |
+      rsync -azre 'ssh -o StrictHostKeyChecking=no -p 23' armaanb.net/public/config.html web@armaanb.net:/var/www/armaanb.net-http/config.html
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..67ad350
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+config.org
+Copyright © 2021 Armaan Bhojwani <me@armaanb.net>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..2de3cf0
--- /dev/null
+++ b/README
@@ -0,0 +1,5 @@
+My system configuration in org format.
+
+See in rendered format at https://armaanb.net/config.html
+
+Copyright 2021 Armaan Bhojwani, MIT license.
diff --git a/config.org b/config.org
new file mode 100644 (file)
index 0000000..7e6625b
--- /dev/null
@@ -0,0 +1,1438 @@
+#+TITLE: System Configuration
+#+DESCRIPTION: Armaan's system configuration.
+
+* Welcome
+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!
+** Compatability
+I am currently using GCCEmacs 28 from the feature/native-comp branch, so some settings may not be available for older versions of Emacs. This is a purely personal configuration, so while I can garuntee that it works on my setup, I can't for anything else.
+** Choices
+I chose to create a powerful, yet not overly heavy Emacs configuration. Things like LSP mode are important to my workflow and help me be productive, so despite its weight, it is kept. Things like a fancy modeline or icons on the other hand, do not increase my productivity, and create visual clutter, and thus have been excluded.
+
+Another important choice has been to integrate Emacs into a large part of my computing environment (see [[*EmacsOS]]). I use Email, IRC, et cetera, all through Emacs which simplifies my workflow.
+
+Lastly, I use Evil mode. I think modal keybindings are simple and more ergonomic than standard Emacs style, and Vim keybindings are what I'm comfortable with and are pervasive throughout computing.
+** TODOs
+*** TODO Turn keybinding and hook declarations into use-package declarations where possible
+*** TODO Put configs with passwords in here with some kind of authentication
+- Offlineimap
+- irc.el
+** License
+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 at the snippet.
+* Package management
+** Bootstrap straight.el
+straight.el is really nice for managing package, and it integrates nicely with use-package. It uses the bootstrapping system defined here for installation.
+#+begin_src emacs-lisp
+  (defvar bootstrap-version)
+  (let ((bootstrap-file
+         (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
+        (bootstrap-version 5))
+    (unless (file-exists-p bootstrap-file)
+      (with-current-buffer
+          (url-retrieve-synchronously
+           "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
+           'silent 'inhibit-cookies)
+        (goto-char (point-max))
+        (eval-print-last-sexp)))
+    (load bootstrap-file nil 'nomessage))
+#+end_src
+** Replace use-package with straight
+#+begin_src emacs-lisp
+  (straight-use-package 'use-package)
+  (setq straight-use-package-by-default t)
+#+end_src
+* Visual options
+** Theme
+Very nice high contrast theme.
+
+Its fine to set this here because I run Emacs in daemon mode, but if I were not, then putting it in early-init.el would be a better choice to eliminate the window being white before the theme is loaded.
+#+begin_src emacs-lisp
+  (setq modus-themes-slanted-constructs t
+        modus-themes-bold-constructs t
+        modus-themes-org-blocks 'rainbow
+        modus-themes-mode-line '3d
+        modus-themes-scale-headings t
+        modus-themes-region 'no-extend
+        modus-themes-diffs 'desaturated)
+  (load-theme 'modus-vivendi t)
+#+end_src
+** Typography
+*** Font
+Great programming font with ligatures
+#+begin_src emacs-lisp
+  (add-to-list 'default-frame-alist '(font . "JetBrainsMonoNF-12"))
+#+end_src
+*** Ligatures
+#+begin_src emacs-lisp
+  (use-package ligature
+    :straight (ligature :type git :host github :repo "mickeynp/ligature.el")
+    :load-path "path-to-ligature-repo"
+    :config
+    (ligature-set-ligatures 'prog-mode '("-|" "-~" "---" "-<<" "-<" "--" "->" "->>" "-->" "///" "/=" "/=="
+                                         "/>" "//" "/*" "*>" "***" "*/" "<-" "<<-" "<=>" "<=" "<|" "<||"
+                                         "<|||" "<|>" "<:" "<>" "<-<" "<<<" "<==" "<<=" "<=<" "<==>" "<-|"
+                                         "<<" "<~>" "<=|" "<~~" "<~" "<$>" "<$" "<+>" "<+" "</>" "</" "<*"
+                                         "<*>" "<->" "<!--" ":>" ":<" ":::" "::" ":?" ":?>" ":=" "::=" "=>>"
+                                         "==>" "=/=" "=!=" "=>" "===" "=:=" "==" "!==" "!!" "!=" ">]" ">:"
+                                         ">>-" ">>=" ">=>" ">>>" ">-" ">=" "&&&" "&&" "|||>" "||>" "|>" "|]"
+                                         "|}" "|=>" "|->" "|=" "||-" "|-" "||=" "||" ".." ".?" ".=" ".-" "..<"
+                                         "..." "+++" "+>" "++" "[||]" "[<" "[|" "{|" "??" "?." "?=" "?:" "##"
+                                         "###" "####" "#[" "#{" "#=" "#!" "#:" "#_(" "#_" "#?" "#(" ";;" "_|_"
+                                         "__" "~~" "~~>" "~>" "~-" "~@" "$>" "^=" "]#"))
+    (global-ligature-mode t))
+#+end_src
+*** Emoji
+#+begin_src emacs-lisp
+  (use-package emojify
+    :config (global-emojify-mode))
+
+  ;; http://ergoemacs.org/emacs/emacs_list_and_set_font.html
+  (set-fontset-font
+   t
+   '(#x1f300 . #x1fad0)
+   (cond
+    ((member "Twitter Color Emoji" (font-family-list)) "Twitter Color Emoji")
+    ((member "Noto Color Emoji" (font-family-list)) "Noto Color Emoji")
+    ((member "Noto Emoji" (font-family-list)) "Noto Emoji")))
+#+end_src
+** Line numbers
+Display relative line numbers except in some modes
+#+begin_src emacs-lisp
+  (global-display-line-numbers-mode)
+  (setq display-line-numbers-type 'relative)
+  (dolist (no-line-num '(term-mode-hook
+                         pdf-view-mode-hook
+                         shell-mode-hook
+                         org-mode-hook
+                         eshell-mode-hook))
+    (add-hook no-line-num (lambda () (display-line-numbers-mode 0))))
+#+end_src
+** Highlight matching parenthesis
+#+begin_src emacs-lisp
+  (use-package paren
+    :config (show-paren-mode)
+    :custom (show-paren-style 'parenthesis))
+#+end_src
+** Modeline
+*** Show current function
+#+begin_src emacs-lisp
+  (which-function-mode)
+#+end_src
+*** Make position in file more descriptive
+Show current column and file size.
+#+begin_src emacs-lisp
+  (column-number-mode)
+  (size-indication-mode)
+#+end_src
+*** Hide minor modes
+#+begin_src emacs-lisp
+  (use-package minions
+    :config (minions-mode))
+#+end_src
+** Ruler
+Show a ruler at a certain number of chars depending on mode.
+#+begin_src emacs-lisp
+  (global-display-fill-column-indicator-mode)
+#+end_src
+** Keybinding hints
+Whenever starting a key chord, show possible future steps.
+#+begin_src emacs-lisp
+  (use-package which-key
+    :config (which-key-mode)
+    :custom (which-key-idle-delay 0.3))
+#+end_src
+** Visual highlights of changes
+Highlight when changes are made.
+#+begin_src emacs-lisp
+  (use-package evil-goggles
+    :config (evil-goggles-mode)
+    (evil-goggles-use-diff-faces))
+#+end_src
+** Highlight "TODO" comments
+#+begin_src emacs-lisp
+  (use-package hl-todo
+    :straight (hl-todo :type git :host github :repo "tarsius/hl-todo")
+    :config (global-hl-todo-mode))
+#+end_src
+** Don't lose cursor
+#+begin_src emacs-lisp
+  (blink-cursor-mode)
+#+end_src
+** Visual line mode
+Soft wrap words and do operations by visual lines.
+#+begin_src emacs-lisp
+  (add-hook 'text-mode-hook 'turn-on-visual-line-mode)
+#+end_src
+** Display number of matches in search
+#+begin_src emacs-lisp
+  (use-package anzu
+    :config (global-anzu-mode))
+#+end_src
+** Visual bell
+Inverts modeline instead of audible bell or the standard visual bell.
+#+begin_src emacs-lisp
+  (setq visible-bell nil
+        ring-bell-function 'flash-mode-line)
+  (defun flash-mode-line ()
+    (invert-face 'mode-line)
+    (run-with-timer 0.1 nil #'invert-face 'mode-line))
+#+end_src
+* Evil mode
+** General
+#+begin_src emacs-lisp
+  (use-package evil
+    :custom (select-enable-clipboard nil)
+    :config
+    (evil-mode)
+    (fset 'evil-visual-update-x-selection 'ignore) ;; Keep clipboard and register seperate
+    ;; Use visual line motions even outside of visual-line-mode buffers
+    (evil-global-set-key 'motion "j" 'evil-next-visual-line)
+    (evil-global-set-key 'motion "k" 'evil-previous-visual-line)
+    (global-set-key (kbd "<escape>") 'keyboard-escape-quit))
+#+end_src
+** Evil collection
+#+begin_src emacs-lisp
+  (use-package evil-collection
+    :after evil
+    :init (evil-collection-init)
+    :custom (evil-collection-setup-minibuffer t))
+#+end_src
+** Surround
+tpope prevails!
+#+begin_src emacs-lisp
+  (use-package evil-surround
+    :config (global-evil-surround-mode))
+#+end_src
+** Leader key
+#+begin_src emacs-lisp
+  (use-package evil-leader
+    :straight (evil-leader :type git :host github :repo "cofi/evil-leader")
+    :config
+    (evil-leader/set-leader "<SPC>")
+    (global-evil-leader-mode))
+#+end_src
+** Nerd commenter
+#+begin_src emacs-lisp
+  ;; Nerd commenter
+  (use-package evil-nerd-commenter
+    :bind (:map evil-normal-state-map
+                ("gc" . evilnc-comment-or-uncomment-lines))
+    :custom (evilnc-invert-comment-line-by-line nil))
+#+end_src
+** Undo tree
+Fix the oopsies!
+#+begin_src emacs-lisp
+  (use-package undo-tree
+    :custom
+    (undo-tree-auto-save-history t)
+    (undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo-tree")))
+    :config
+    (global-undo-tree-mode)
+    (evil-set-undo-system 'undo-tree))
+#+end_src
+** Number incrementing
+Add back C-a/C-x
+#+begin_src emacs-lisp
+  (use-package evil-numbers
+    :straight (evil-numbers :type git :host github :repo "juliapath/evil-numbers")
+    :bind (:map evil-normal-state-map
+                ("C-M-a" . evil-numbers/inc-at-pt)
+                ("C-M-x" . evil-numbers/dec-at-pt)))
+#+end_src
+** Evil org
+*** Init
+#+begin_src emacs-lisp
+  (use-package evil-org
+    :after org
+    :hook (org-mode . evil-org-mode)
+    :config
+    (evil-org-set-key-theme '(textobjects insert navigation shift todo)))
+  (use-package evil-org-agenda
+    :straight (:type built-in)
+    :after evil-org
+    :config
+    (evil-org-agenda-set-keys))
+#+end_src
+*** Leader maps
+#+begin_src emacs-lisp
+  (evil-leader/set-key-for-mode 'org-mode
+    "T" 'org-show-todo-tree
+    "a" 'org-agenda
+    "c" 'org-archive-subtree)
+#+end_src
+* Org mode
+** General
+#+begin_src emacs-lisp
+  (use-package org
+    :straight (:type built-in)
+    :commands (org-capture org-agenda)
+    :custom
+    (org-ellipsis " ▾")
+    (org-agenda-start-with-log-mode t)
+    (org-log-done 'time)
+    (org-log-into-drawer t)
+    (org-src-tab-acts-natively t)
+    (org-startup-indented t)
+    (org-hide-emphasis-markers t)
+    (org-fontify-whole-block-delimiter-line nil))
+#+end_src
+** Automatically tangle
+#+begin_src emacs-lisp
+  (add-hook 'org-mode-hook
+            (lambda () (add-hook 'after-save-hook #'org-babel-tangle
+                                 :append :local)))
+#+end_src
+** Tempo
+#+begin_src emacs-lisp
+  (use-package org-tempo
+    :after org
+    :straight (:type built-in)
+    :config
+    ;; TODO: There's gotta be a more efficient way to write this
+    (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
+    (add-to-list 'org-structure-template-alist '("sp" . "src conf :tangle ~/.spectrwm.conf"))
+    (add-to-list 'org-structure-template-alist '("zsh" . "src shell :tangle ~/.config/zsh/zshrc"))
+    (add-to-list 'org-structure-template-alist '("al" . "src yml :tangle ~/.config/alacritty/alacritty.yml"))
+    (add-to-list 'org-structure-template-alist '("ipy" . "src python :tangle ~/.ipython/"))
+    (add-to-list 'org-structure-template-alist '("pi" . "src conf :tangle ~/.config/picom/picom.conf"))
+    (add-to-list 'org-structure-template-alist '("git" . "src plain :tangle ~/.gitconfig")))
+#+end_src
+* Autocompletion
+** Ivy
+Simple, but not too simple autocompletion.
+#+begin_src emacs-lisp
+  (use-package ivy
+    :bind (("C-s" . swiper)
+           :map ivy-minibuffer-map
+           ("TAB" . ivy-alt-done)
+           :map ivy-switch-buffer-map
+           ("C-d" . ivy-switch-buffer-kill))
+    :config (ivy-mode))
+#+end_src
+** Ivy-rich
+#+begin_src emacs-lisp
+  (use-package ivy-rich
+    :after ivy
+    :config (ivy-rich-mode))
+#+end_src
+** Counsel
+Ivy everywhere.
+#+begin_src emacs-lisp
+  (use-package counsel
+    :bind (("C-M-j" . 'counsel-switch-buffer)
+           :map minibuffer-local-map
+           ("C-r" . 'counsel-minibuffer-history))
+    :custom (counsel-linux-app-format-function #'counsel-linux-app-format-function-name-only)
+    :config (counsel-mode))
+#+end_src
+** Remember frequent commands
+#+begin_src emacs-lisp
+  (use-package ivy-prescient
+    :after counsel
+    :custom
+    (ivy-prescient-enable-filtering nil)
+    :config
+    (prescient-persist-mode)
+    (ivy-prescient-mode))
+#+end_src
+** Swiper
+Better search utility.
+#+begin_src emacs-lisp
+  (use-package swiper)
+#+end_src
+* EmacsOS
+** RSS
+Use elfeed for RSS. I have another file with all the feeds in it.
+#+begin_src emacs-lisp
+  (use-package elfeed
+    :bind (("C-c e" . elfeed))
+    :config
+    (load "~/.emacs.d/feeds.el")
+    (add-hook 'elfeed-new-entry-hook
+              (elfeed-make-tagger :feed-url "youtube\\.com"
+                                  :add '(youtube)))
+    :bind (:map elfeed-search-mode-map ("C-c C-o" . 'elfeed-show-visit)))
+
+  (use-package elfeed-goodies
+    :after elfeed
+    :config (elfeed-goodies/setup))
+#+end_src
+** Email
+Use mu4e for reading emails.
+
+I use `offlineimap` to sync my maildirs. It is slower than mbsync, but is fast enough for me, especially when ran with the =-q= option.
+
+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.
+#+begin_src emacs-lisp
+  (use-package smtpmail
+    :straight (:type built-in))
+  (use-package mu4e
+    :load-path "/usr/share/emacs/site-lisp/mu4e"
+    :bind (("C-c m" . mu4e))
+    :config
+
+    (setq user-full-name "Armaan Bhojwani"
+          smtpmail-local-domain "armaanb.net"
+          smtpmail-stream-type 'ssl
+          smtpmail-smtp-service '465
+          mu4e-change-filenames-when-moving t
+          message-kill-buffer-on-exit t
+          mu4e-get-mail-command "offlineimap -q"
+          message-citation-line-format "On %a %d %b %Y at %R, %f wrote:\n"
+          message-citation-line-function 'message-insert-formatted-citation-line
+          mu4e-context-policy "pick-first"
+          mu4e-contexts
+          `( ,(make-mu4e-context
+               :name "school"
+               :enter-func (lambda () (mu4e-message "Entering school context"))
+               :leave-func (lambda () (mu4e-message "Leaving school context"))
+               :match-func (lambda (msg)
+                             (when msg
+                               (string-match-p "^/school" (mu4e-message-field msg :maildir))))
+               :vars '( (user-mail-address . "abhojwani22@nobles.edu")
+                        (mu4e-sent-folder . "/school/Sent")
+                        (mu4e-drafts-folder . "/school/Drafts")
+                        (mu4e-trash-folder . "/school/Trash")
+                        (mu4e-refile-folder . "/school/Archive")
+                        (user-mail-address . "abhojwani22@nobles.edu")
+                        (smtpmail-smtp-user . "abhojwani22@nobles.edu")
+                        (smtpmail-smtp-server . "smtp.gmail.com")))
+             ,(make-mu4e-context
+               :name "personal"
+               :enter-func (lambda () (mu4e-message "Entering personal context"))
+               :leave-func (lambda () (mu4e-message "Leaving personal context"))
+               :match-func (lambda (msg)
+                             (when msg
+                               (string-match-p "^/personal" (mu4e-message-field msg :maildir))))
+               :vars '(
+                       (mu4e-sent-folder . "/personal/Sent")
+                       (mu4e-drafts-folder . "/personal/Drafts")
+                       (mu4e-trash-folder . "/personal/Trash")
+                       (mu4e-refile-folder . "/personal/Archive")
+                       (user-mail-address . "me@armaanb.net")
+                       (smtpmail-smtp-user . "me@armaanb.net")
+                       (smtpmail-smtp-server "smtp.mailbox.org")
+                       (mu4e-drafts-folder . "/school/Drafts")
+                       (mu4e-trash-folder . "/school/Trash")))))
+
+    (add-to-list 'mu4e-bookmarks
+                 '(
+                   :name  "Unified inbox"
+                   :query "maildir:\"/personal/INBOX\" or maildir:\"/school/INBOX\""
+                   :key   ?b)))
+#+end_src
+** Calendar
+#+begin_src emacs-lisp
+  (use-package calfw)
+  (use-package calfw-org)
+  (use-package calfw-ical)
+
+  (defun acheam-calendar ()
+    "Open a calendar."
+    (interactive)
+    (shell-command "vdirsyncer sync")
+    (let ((default-directory "~/.local/share/vdirsyncer/"))
+      (cfw:open-calendar-buffer
+       :contents-sources
+       (list
+        (cfw:ical-create-source "School" (expand-file-name "school/abhojwani22@nobles.edu.ics") "Green")
+        (cfw:ical-create-source "Personal" (expand-file-name "mailbox/Y2FsOi8vMC8zMQ.ics") "Blue")
+        (cfw:ical-create-source "Birthdays" (expand-file-name "mailbox/Y2FsOi8vMS8w.ics") "Gray")
+        ))))
+#+end_src
+** IRC
+Another file has more specific network configuration.
+#+begin_src emacs-lisp
+  (use-package circe
+    :config
+    (load "~/.emacs.d/irc.el"))
+  (use-package circe-color-nicks
+    :after circe
+    :straight (:type built-in))
+  (use-package circe-chanop
+    :after circe
+    :straight (:type built-in))
+#+end_src
+** Default browser
+Set EWW as default browser except for videos
+#+begin_src emacs-lisp
+  (defun browse-url-mpv (url &optional new-window)
+    "Open URL in MPV."
+    (start-process "mpv" "*mpv*" "mpv" url))
+
+  (setq browse-url-browser-function
+        (quote
+         (("youtu\\.?be" . browse-url-mpv)
+          ("." . eww-browse-url))))
+#+end_src
+** Emacs Anywhere
+Use Emacs globally. Use the Emacs daemon and bind a key in your wm to
+"emacsclient --eval "(emacs-everywhere)".
+#+begin_src emacs-lisp
+  (use-package emacs-everywhere)
+#+end_src
+* Emacs IDE
+** LSP
+*** General
+#+begin_src emacs-lisp
+  (use-package lsp-mode
+    :commands (lsp lsp-deferred)
+    :custom (lsp-keymap-prefix "C-c l")
+    :hook ((lsp-mode . lsp-enable-which-key-integration)))
+
+  (use-package lsp-ivy)
+
+  (use-package lsp-ui
+    :commands lsp-ui-mode
+    :custom (lsp-ui-doc-position 'bottom))
+  (use-package lsp-ui-flycheck
+    :after lsp-ui
+    :straight (:type built-in))
+#+end_src
+*** Company
+Company-box adds icons.
+#+begin_src emacs-lisp
+  (use-package company
+    :after lsp-mode
+    :hook (lsp-mode . company-mode)
+    :bind (:map company-active-map
+                ("<tab>" . company-complete-selection))
+    (:map lsp-mode-map
+          ("<tab>" . company-indent-or-complete-common))
+    :custom
+    (company-minimum-prefix-length 1)
+    (setq company-dabbrev-downcase 0)
+    (company-idle-delay 0.0))
+
+  (use-package company-box
+    :hook (company-mode . company-box-mode))
+#+end_src
+*** Language servers
+**** Python
+#+begin_src emacs-lisp
+  (use-package lsp-pyright
+    :hook (python-mode . (lambda ()
+                           (use-package lsp-pyright
+                             :straight (:type built-in))
+                           (lsp-deferred))))
+#+end_src
+** Code cleanup
+#+begin_src emacs-lisp
+  (use-package blacken
+    :hook (python-mode . blacken-mode)
+    :config
+    (setq blacken-line-length 79))
+
+  ;; Purge whitespace
+  (use-package ws-butler
+    :config
+    (ws-butler-global-mode))
+#+end_src
+** Flycheck
+#+begin_src emacs-lisp
+  (use-package flycheck
+    :config
+    (global-flycheck-mode))
+#+end_src
+** Project management
+#+begin_src emacs-lisp
+  (use-package projectile
+    :config (projectile-mode)
+    :custom ((projectile-completion-system 'ivy))
+    :bind-keymap
+    ("C-c p" . projectile-command-map)
+    :init
+    (when (file-directory-p "~/Code")
+      (setq projectile-project-search-path '("~/Code")))
+    (setq projectile-switch-project-action #'projectile-dired))
+
+  (use-package counsel-projectile
+    :after projectile
+    :config (counsel-projectile-mode))
+#+end_src
+** Dired
+#+begin_src emacs-lisp
+  (use-package dired
+    :straight (:type built-in)
+    :commands (dired dired-jump)
+    :custom ((dired-listing-switches "-agho --group-directories-first"))
+    :config
+    (evil-collection-define-key 'normal 'dired-mode-map
+      "h" 'dired-single-up-directory
+      "l" 'dired-single-buffer))
+
+  (use-package dired-single
+    :commands (dired dired-jump))
+
+  (use-package dired-open
+    :commands (dired dired-jump)
+    :custom
+    (dired-open-extensions '(("png" . "feh")
+                             ("mkv" . "mpv"))))
+
+  (use-package dired-hide-dotfiles
+    :hook (dired-mode . dired-hide-dotfiles-mode)
+    :config
+    (evil-collection-define-key 'normal 'dired-mode-map
+      "H" 'dired-hide-dotfiles-mode))
+#+end_src
+** Git
+*** Magit
+#+begin_src emacs-lisp
+  (use-package magit
+    :hook (git-commit-setup-hook . pinentry-start))
+#+end_src
+*** Colored diff in line number area
+#+begin_src emacs-lisp
+  (use-package diff-hl
+    :straight (diff-hl :type git :host github :repo "dgutov/diff-hl")
+    :config (global-diff-hl-mode))
+#+end_src
+* Functions
+** Easily convert splits
+Converts splits from horizontal to vertical and vice versa. Lifted from EmacsWiki.
+#+begin_src emacs-lisp
+  (defun toggle-window-split ()
+    (interactive)
+    (if (= (count-windows) 2)
+        (let* ((this-win-buffer (window-buffer))
+               (next-win-buffer (window-buffer (next-window)))
+               (this-win-edges (window-edges (selected-window)))
+               (next-win-edges (window-edges (next-window)))
+               (this-win-2nd (not (and (<= (car this-win-edges)
+                                           (car next-win-edges))
+                                       (<= (cadr this-win-edges)
+                                           (cadr next-win-edges)))))
+               (splitter
+                (if (= (car this-win-edges)
+                       (car (window-edges (next-window))))
+                    'split-window-horizontally
+                  'split-window-vertically)))
+          (delete-other-windows)
+          (let ((first-win (selected-window)))
+            (funcall splitter)
+            (if this-win-2nd (other-window 1))
+            (set-window-buffer (selected-window) this-win-buffer)
+            (set-window-buffer (next-window) next-win-buffer)
+            (select-window first-win)
+            (if this-win-2nd (other-window 1))))))
+
+  (define-key ctl-x-4-map "t" 'toggle-window-split)
+#+end_src
+** Insert date
+#+begin_src emacs-lisp
+  (defun insert-date ()
+    (interactive)
+    (insert (format-time-string "%Y-%m-%d")))
+#+end_src
+* Keybindings
+** Switch windows
+#+begin_src emacs-lisp
+  (use-package ace-window
+    :bind ("M-o" . ace-window))
+#+end_src
+** Kill current buffer
+Makes "C-x k" binding faster.
+#+begin_src emacs-lisp
+  (substitute-key-definition 'kill-buffer 'kill-buffer-and-window global-map)
+#+end_src
+* Other settings
+** Save place
+Opens file where you left it.
+#+begin_src emacs-lisp
+  (save-place-mode)
+#+end_src
+** OpenSCAD
+Render OpenSCAD files, and add a preview window.
+
+Personal fork just merges a PR.
+#+begin_src emacs-lisp
+  (use-package scad-mode)
+  (use-package scad-preview
+    :straight (scad-preview :type git :host github :repo "Armaanb/scad-preview"))
+#+end_src
+** Writing mode
+Distraction free writing a la junegunn/goyo.
+#+begin_src emacs-lisp
+  (use-package olivetti
+    :config
+    (evil-leader/set-key "o" 'olivetti-mode))
+#+end_src
+** Control backup files
+Stop backup files from spewing everywhere.
+#+begin_src emacs-lisp
+  (setq backup-directory-alist `(("." . "~/.emacs.d/backups")))
+#+end_src
+** Abbreviations
+Abbreviate things!
+#+begin_src emacs-lisp
+  (setq abbrev-file-name "~/.emacs.d/abbrevs")
+  (setq save-abbrevs 'silent)
+  (setq-default abbrev-mode t)
+#+end_src
+** Expand tabs to spaces
+#+begin_src emacs-lisp
+  (setq-default tab-width 2)
+#+end_src
+** Make yes/no easier
+#+begin_src emacs-lisp
+  (defalias 'yes-or-no-p 'y-or-n-p)
+#+end_src
+** Move customize file
+No more clogging up init.el.
+#+begin_src emacs-lisp
+  (setq custom-file "~/.emacs.d/custom.el")
+  (load custom-file)
+#+end_src
+** Better help
+#+begin_src emacs-lisp
+  (use-package helpful
+    :commands (helpful-callable helpful-variable helpful-command helpful-key)
+    :custom
+    (counsel-describe-function-function #'helpful-callable)
+    (counsel-describe-variable-function #'helpful-variable)
+    :bind
+    ([remap describe-function] . counsel-describe-function)
+    ([remap describe-command] . helpful-command)
+    ([remap describe-variable] . counsel-describe-variable)
+    ([remap describe-key] . helpful-key))
+#+end_src
+** GPG
+#+begin_src emacs-lisp
+  (use-package epa-file
+    :straight (:type built-in))
+  (setq epa-file-select-keys nil
+        epa-file-encrypt-to '("me@armaanb.net")
+        password-cache-expiry (* 60 15))
+
+  (use-package pinentry)
+#+end_src
+** Pastebin
+#+begin_src emacs-lisp
+  (use-package 0x0
+    :straight (0x0 :type git :repo "https://git.sr.ht/~zge/nullpointer-emacs")
+    :custom (0x0-default-service 'envs)
+    :config (evil-leader/set-key
+              "00" '0x0-upload
+              "0f" '0x0-upload-file
+              "0s" '0x0-upload-string
+              "0c" '0x0-upload-kill-ring
+              "0p" '0x0-upload-popup))
+#+end_src
+** Copy kill ring to clipboard
+#+begin_src emacs-lisp
+  (setq x-select-enable-clipboard t)
+  (defun copy-kill-ring-to-xorg ()
+    "Copy the current kill ring to the xorg clipboard."
+    (interactive)
+    (x-select-text (current-kill 0)))
+#+end_src
+** Browse kill ring
+#+begin_src emacs-lisp
+  (use-package browse-kill-ring)
+#+end_src
+* Tangles
+** Spectrwm
+*** General settings
+#+begin_src conf :tangle ~/.spectrwm.conf
+  workspace_limit = 5
+  warp_pointer = 1
+  modkey = Mod4
+  border_width = 4
+  tile_gap = 10
+  autorun = ws[1]:/home/armaa/Code/scripts/autostart
+#+end_src
+*** Apprearance
+Gruvbox colors
+#+begin_src conf :tangle ~/.spectrwm.conf
+  color_focus = rgb:83/a5/98
+  color_focus_maximized = rgb:d6/5d/0e
+  color_unfocus = rgb:58/58/58
+
+  bar_enabled = 0
+  bar_font = xos4 Fira Code:pixelsize=14:antialias=true # any installed font
+#+end_src
+*** Keybindings
+**** WM actions
+#+begin_src conf :tangle ~/.spectrwm.conf
+  program[lock] = i3lock -c 000000 -ef
+  program[term] = alacritty
+  program[screenshot_all] = flameshot gui
+  program[menu] = rofi -show run # `rofi-dmenu` handles the rest
+  program[switcher] = rofi -show window
+  program[notif] = /home/armaa/Code/scripts/setter status
+
+  bind[notif] = MOD+n
+  bind[switcher] = MOD+Tab
+#+end_src
+**** Media keys
+#+begin_src conf :tangle ~/.spectrwm.conf
+  program[paup] = /home/armaa/Code/scripts/setter audio +5
+  program[padown] = /home/armaa/Code/scripts/setter audio -5
+  program[pamute] = /home/armaa/Code/scripts/setter audio
+  program[brigup] = /home/armaa/Code/scripts/setter brightness +10%
+  program[brigdown] = /home/armaa/Code/scripts/setter brightness 10%-
+  program[next] = playerctl next
+  program[prev] = playerctl previous
+  program[pause] = playerctl play-pause
+
+  bind[padown] = XF86AudioLowerVolume
+  bind[paup] = XF86AudioRaiseVolume
+  bind[pamute] = XF86AudioMute
+  bind[brigdown] = XF86MonBrightnessDown
+  bind[brigup] = XF86MonBrightnessUp
+  bind[pause] = XF86AudioPlay
+  bind[next] = XF86AudioNext
+  bind[prev] = XF86AudioPrev
+#+end_src
+**** HJKL
+#+begin_src conf :tangle ~/.spectrwm.conf
+  program[h] = xdotool keyup h key --clearmodifiers Left
+  program[j] = xdotool keyup j key --clearmodifiers Down
+  program[k] = xdotool keyup k key --clearmodifiers Up
+  program[l] = xdotool keyup l key --clearmodifiers Right
+
+  bind[h] = MOD + Control + h
+  bind[j] = MOD + Control + j
+  bind[k] = MOD + Control + k
+  bind[l] = MOD + Control + l
+#+end_src
+**** Programs
+#+begin_src conf :tangle ~/.spectrwm.conf
+  program[aerc] = alacritty -e aerc
+  program[weechat] = alacritty --hold -e sh -c "while : ; do ssh -p 23 -t root@armaanb.net tmux attach-session -t weechat; sleep 2; done"
+  program[emacs] = emacsclient -c
+  program[emacs-anywhere] = emacsclient --eval "(emacs-everywhere)"
+  program[firefox] = firefox
+  program[thunderbird] = thunderbird
+  program[slack] = slack
+
+  bind[aerc] = MOD+Control+s
+  bind[weechat] = MOD+Control+d
+  bind[emacs] = MOD+Control+f
+  bind[emacs-anywhere] = MOD+f
+  bind[firefox] = MOD+Control+u
+  bind[thunderbird] = MOD+Control+i
+  bind[slack] = MOD+Control+o
+#+end_src
+** Zsh
+*** Settings
+**** Completions
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  autoload -Uz compinit
+  compinit
+
+  setopt no_case_glob
+  unsetopt glob_complete
+#+end_src
+**** Vim bindings
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  bindkey -v
+  KEYTIMEOUT=1
+
+  bindkey -M vicmd "^[[3~" delete-char
+  bindkey "^[[3~" delete-char
+
+  autoload edit-command-line
+  zle -N edit-command-line
+  bindkey -M vicmd ^e edit-command-line
+  bindkey ^e edit-command-line
+#+end_src
+**** History
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  setopt extended_history
+  setopt share_history
+  setopt inc_append_history
+  setopt hist_ignore_dups
+  setopt hist_reduce_blanks
+
+  HISTSIZE=10000
+  SAVEHIST=10000
+  HISTFILE=~/.local/share/zsh/history
+#+end_src
+*** Plugins
+I manage plugins using my own plugin manager, ZPE. https://git.sr.ht/~armaan/zpe
+**** ZPE
+#+begin_src plain :tangle ~/.config/zpe/repositories
+    https://github.com/Aloxaf/fzf-tab
+    https://github.com/zdharma/fast-syntax-highlighting
+    https://github.com/rupa/z
+#+end_src
+**** Zshrc
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  source ~/Code/zpe/zpe.sh
+  source ~/Code/admone/admone.zsh
+  source ~/.config/zsh/fzf-bindings.zsh
+
+  zpe-source fzf-tab/fzf-tab.zsh
+  zstyle ':completion:*:descriptions' format '[%d]'
+  zstyle ':fzf-tab:complete:cd:*' fzf-preview 'exa -1 --color=always $realpath'
+  zstyle ':completion:*' completer _complete
+  zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' \
+         'm:{a-zA-Z}={A-Za-z} l:|=* r:|=*'
+  enable-fzf-tab
+  zpe-source fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh
+  export _Z_DATA="/home/armaa/.local/share/z"
+  zpe-source z/z.sh
+#+end_src
+*** Functions
+**** Alert after long command
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alert() {
+      notify-send --urgency=low -i ${(%):-%(?.terminal.error)} \
+                  ${history[$HISTCMD]%[;&|][[:space:]]##alert}
+  }
+#+end_src
+**** Time Zsh startup
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  timezsh() {
+      for i in $(seq 1 10); do
+          time "zsh" -i -c exit;
+      done
+  }
+#+end_src
+**** Update all packages
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  color=$(tput setaf 5)
+  reset=$(tput sgr0)
+
+  apu() {
+      sudo echo "${color}== upgrading with yay ==${reset}"
+      yay
+      echo ""
+      echo "${color}== checking for pacnew files ==${reset}"
+      sudo pacdiff
+      echo
+      echo "${color}== upgrading flatpaks ==${reset}"
+      flatpak update
+      echo ""
+      echo "${color}== upgrading zsh plugins ==${reset}"
+      zpe-pull
+      echo ""
+      echo "${color}== updating nvim plugins ==${reset}"
+      nvim +PlugUpdate +PlugUpgrade +qall
+      echo "Updated nvim plugins"
+      echo ""
+      echo "${color}You are entirely up to date!${reset}"
+  }
+#+end_src
+**** Clean all packages
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  apap() {
+      sudo echo "${color}== cleaning pacman orphans ==${reset}"
+      (pacman -Qtdq | sudo pacman -Rns - 2> /dev/null) || echo "No orphans"
+      echo ""
+      echo "${color}== cleaning flatpaks ==${reset}"
+      flatpak remove --unused
+      echo ""
+      echo "${color}== cleaning zsh plugins ==${reset}"
+      zpe-clean
+      echo ""
+      echo "${color}== cleaning nvim plugins ==${reset}"
+      nvim +PlugClean +qall
+      echo "Cleaned nvim plugins"
+      echo ""
+      echo "${color}All orphans cleaned!${reset}"
+  }
+#+end_src
+**** ls every cd
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  chpwd() {
+      emulate -L zsh
+      exa -lh --icons --git --group-directories-first
+  }
+#+end_src
+**** Setup anaconda
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  zconda() {
+      __conda_setup="$('/opt/anaconda/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
+      if [ $? -eq 0 ]; then
+          eval "$__conda_setup"
+      else
+          if [ -f "/opt/anaconda/etc/profile.d/conda.sh" ]; then
+              . "/opt/anaconda/etc/profile.d/conda.sh"
+          else
+              export PATH="/opt/anaconda/bin:$PATH"
+          fi
+      fi
+      unset __conda_setup
+  }
+#+end_src
+**** Interact with 0x0
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  zxz="https://envs.sh"
+  0file() { curl -F"file=@$1" "$zxz" ; }
+  0pb() { curl -F"file=@-;" "$zxz" ; }
+  0url() { curl -F"url=$1" "$zxz" ; }
+  0short() { curl -F"shorten=$1" "$zxz" ; }
+  0clip() { xclip -out | curl -F"file=@-;" "$zxz" ; }
+#+end_src
+**** Swap two files
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  sw() {
+      mv $1 $1.tmp
+      mv $2 $1
+      mv $1.tmp $2
+  }
+#+end_src
+*** Aliases
+**** SSH
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias bhoji-drop='ssh -p 23 root@armaanb.net'
+  alias weechat='ssh -p 23 -t root@armaanb.net tmux attach-session -t weechat'
+  alias tcf='ssh root@204.48.23.68'
+  alias ngmun='ssh root@157.245.89.25'
+  alias prox='ssh root@192.168.1.224'
+  alias dock='ssh root@192.168.1.225'
+  alias jenkins='ssh root@192.168.1.226'
+  alias envs='ssh acheam@envs.net'
+#+end_src
+**** File management
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias ls='exa -lh --icons --git --group-directories-first'
+  alias la='exa -lha --icons --git --group-directories-first'
+  alias df='df -h / /boot'
+  alias du='du -h'
+  alias free='free -h'
+  alias cp='cp -riv'
+  alias rm='rm -Iv'
+  alias mv='mv -iv'
+  alias ln='ln -iv'
+  alias grep='grep -in --exclude-dir=.git --color=auto'
+  alias mkdir='mkdir -pv'
+  alias unar='atool -x'
+  alias wget='wget -e robots=off'
+  alias lanex='~/.local/share/lxc/lxc'
+#+end_src
+**** Dotfiles
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias padm='yadm --yadm-repo ~/Code/dotfiles/repo.git'
+  alias yadu='yadm add -u && yadm commit -m "Updated `date -Iseconds`" && \
+    yadm push'
+  alias padu='padm add -u && padm commit && padm push && yadu'
+#+end_src
+**** Editing
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias v='nvim'
+  alias vim='nvim'
+  alias vw="nvim ~/Documents/vimwiki/index.md"
+#+end_src
+**** System management
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias jctl='journalctl -p 3 -xb'
+  alias pkill='pkill -i'
+  alias cx='chmod +x'
+  alias please='sudo $(fc -ln -1)'
+  alias sudo='sudo ' # allows aliases to be run with sudo
+#+end_src
+**** Networking
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias ping='ping -c 10'
+  alias speed='speedtest-cli'
+  alias ip='ip --color=auto'
+  alias cip='curl https://armaanb.net/ip'
+  alias gps='gpg --keyserver keyserver.ubuntu.com --search-keys'
+  alias gpp='gpg --keyserver keyserver.ubuntu.com --recv-key'
+#+end_src
+**** Docker
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias dc='docker-compose'
+  alias dcdu='docker-compose down && docker-compose up -d'
+#+end_src
+**** Other
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias bigrandomfile='dd if=/dev/urandom of=1GB-urandom bs=1M count=1024 \
+    iflag=fullblock status=progress'
+  alias bigboringfile='dd if=/dev/zero of=1GB-zero bs=1M count=1024 \
+    iflag=fullblock status=progress'
+  alias ts='gen-shell -c task'
+  alias ts='gen-shell -c task'
+  alias tetris='autoload -Uz tetriscurses && tetriscurses'
+  alias news='newsboat'
+  alias tilderadio="\mpv https://radio.tildeverse.org/radio/8000/radio.ogg"
+  alias ytmusic="youtube-dl -x --add-metadata  --audio-format aac \
+    --restrict-filenames -o '%(title)s.%(ext)s'"
+  alias cal="cal -3 --color=auto"
+#+end_src
+**** Virtual machines, chroots
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias ckiss="sudo chrooter ~/Virtual/kiss"
+  alias cdebian="sudo chrooter ~/Virtual/debian bash"
+  alias cwindows='devour qemu-system-x86_64 \
+    -smp 3 \
+    -cpu host \
+    -enable-kvm \
+    -m 3G \
+    -device VGA,vgamem_mb=64 \
+    -device intel-hda \
+    -device hda-duplex \
+    -net nic \
+    -net user,smb=/home/armaa/Public \
+    -drive format=qcow2,file=/home/armaa/Virtual/windows.qcow2'
+#+end_src
+**** Python
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias ipy="ipython"
+  alias zpy="zconda && ipython"
+  alias math="ipython --profile=math"
+  alias pypi="python setup.py sdist && twine upload dist/*"
+  alias pip="python -m pip"
+  alias black="black -l 79"
+#+end_src
+**** Latin
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias words='gen-shell -c "words"'
+  alias words-e='gen-shell -c "words ~E"'
+#+end_src
+**** Devour
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias zathura='devour zathura'
+  alias mpv='devour mpv'
+  alias sql='devour sqlitebrowser'
+  alias cad='devour openscad'
+  alias feh='devour feh'
+#+end_src
+**** Package management (Pacman)
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  alias aps='yay -Ss'
+  alias api='yay -Syu'
+  alias app='yay -Rns'
+  alias apc='yay -Sc'
+  alias apo='yay -Qttd'
+  alias azf='pacman -Q | fzf'
+  alias favorites='pacman -Qe | cut -d " " -f 1 > ~/Documents/favorites'
+  alias ufetch='ufetch-arch'
+  alias reflect='reflector --verbose --sort rate --save \
+    ~/.local/etc/pacman.d/mirrorlist --download-timeout 60' # Takes ~45m to run
+#+end_src
+*** Exports
+#+begin_src shell :tangle ~/.config/zsh/zshrc
+  export EDITOR="emacsclient -c"                  # $EDITOR opens in terminal
+  export VISUAL="emacsclient -c -a emacs"         # $VISUAL opens in GUI mode
+  export TERM=xterm-256color # for compatability
+
+  export GPG_TTY="$(tty)"
+  export MANPAGER='nvim +Man!'
+  export PAGER='less'
+
+  # generated with "vivid generate gruvbox"
+  export LS_COLORS="$(cat ~/.local/share/zsh/gruvbox)"
+
+  export GTK_USE_PORTAL=1
+
+  export PATH="/home/armaa/.local/bin:$PATH" # prioritize .local/bin
+  export PATH="$PATH:/home/armaa/Code/scripts"
+  export PATH="$PATH:/home/armaa/.cargo/bin"
+  export PATH="$PATH:/home/armaa/.local/share/gem/ruby/2.7.0/bin"
+  export PATH="$PATH:/usr/sbin"
+  export PATH="$PATH:/opt/FreeTube/freetube"
+
+  export LC_ALL="en_US.UTF-8"
+  export LC_CTYPE="en_US.UTF-8"
+  export LANGUAGE="en_US.UTF-8"
+
+  export KISS_PATH="/home/armaa/kiss/home/armaa/kiss-repo"
+  export KISS_PATH="$KISS_PATH:/home/armaa/Clone/repo-main/core"
+  export KISS_PATH="$KISS_PATH:/home/armaa/Clone/repo-main/extra"
+  export KISS_PATH="$KISS_PATH:/home/armaa/Clone/repo-main/xorg"
+  export KISS_PATH="$KISS_PATH:/home/armaa/Clone/repo-main/testing"
+  export KISS_PATH="$KISS_PATH:/home/armaa/Clone/repo-community/community"
+#+end_src
+** Alacritty
+*** Appearance
+#+begin_src yml :tangle ~/.config/alacritty/alacritty.yml
+font:
+  normal:
+    family: JetBrains Mono Nerd Font
+    style: Medium
+  italic:
+    style: Italic
+  Bold:
+    style: Bold
+  size: 7
+  ligatures: true # Requires ligature patch
+
+window:
+  padding:
+    x: 5
+    y: 5
+
+background_opacity: 0.6
+#+end_src
+*** Keybindings
+Send <RET> + modifier through
+#+begin_src yml :tangle ~/.config/alacritty/alacritty.yml
+key_bindings:
+  - {
+    key: Return,
+    mods: Shift,
+    chars: "\x1b[13;2u"
+  }
+  - {
+    key: Return,
+    mods: Control,
+    chars: "\x1b[13;5u"
+  }
+#+end_src
+*** Color scheme
+Gruvbox
+#+begin_src yml :tangle ~/.config/alacritty/alacritty.yml
+colors:
+  # Default colors
+  primary:
+    background: '#000000'
+    foreground: '#ebdbb2'
+
+  # Normal colors
+  normal:
+    black:   '#282828'
+    red:     '#cc241d'
+    green:   '#98971a'
+    yellow:  '#d79921'
+    blue:    '#458588'
+    magenta: '#b16286'
+    cyan:    '#689d6a'
+    white:   '#a89984'
+
+  # Bright colors
+  bright:
+    black:   '#928374'
+    red:     '#fb4934'
+    green:   '#b8bb26'
+    yellow:  '#fabd2f'
+    blue:    '#83a598'
+    magenta: '#d3869b'
+    cyan:    '#8ec07c'
+    white:   '#ebdbb2'
+#+end_src
+** IPython
+*** General
+Symlink profile_default/ipython_config.py to profile_math/ipython_config.py
+#+begin_src python :tangle ~/.ipython/profile_default/ipython_config.py
+  c.TerminalInteractiveShell.editing_mode = 'vi'
+  c.InteractiveShell.colors = 'linux'
+  c.TerminalInteractiveShell.confirm_exit = False
+#+end_src
+*** Math
+#+begin_src python :tangle ~/.ipython/profile_math/startup.py
+  from math import *
+
+  def deg(x):
+      return x * (180 /  pi)
+
+  def rad(x):
+      return x * (pi / 180)
+
+  def rad(x, unit):
+      return (x * (pi / 180)) / unit
+
+  def csc(x):
+      return 1 / sin(x)
+
+  def sec(x):
+      return 1 / cos(x)
+
+  def cot(x):
+      return 1 / tan(x)
+#+end_src
+** MPV
+Make MPV play a little bit smoother.
+#+begin_src conf :tangle ~/.config/mpv/mpv.conf
+  ytdl-format="bestvideo[height<=?1080]+bestaudio/best"
+  hwdec=auto-copy
+#+end_src
+** Picom
+*** Shadows
+#+begin_src conf :tangle ~/.config/picom/picom.conf
+  shadow = true;
+  shadow-radius = 10;
+  shadow-offset-x = -5;
+  shadow-offset-y = -5;
+#+end_src
+*** Fading
+#+begin_src conf :tangle ~/.config/picom/picom.conf
+  fading = true
+  fade-delta = 5
+#+end_src
+*** Blur
+#+begin_src conf :tangle ~/.config/picom/picom.conf
+  blur:
+  {
+  method = "gaussian";
+  size = 5;
+  deviation = 5;
+  };
+#+end_src
+*** Backend
+Needs picom to be run with "--experimental-backends"
+#+begin_src conf :tangle ~/.config/picom/picom.conf
+  backend = "glx";
+#+end_src
+** Inputrc
+For any GNU Readline programs
+#+begin_src plain :tangle ~/.inputrc
+  set editing-mode vi
+#+end_src
+** Vivid
+https://github.com/sharkdp/vivid
+*** Colors
+#+begin_src yml :tangle ~/.config/vivid/gruvbox.yml
+  colors:
+    background_color: '282A36'
+    black: '21222C'
+    orange: 'd65d0e'
+    purple: 'b16286'
+    red: 'cc241d'
+    blue: '458588'
+    pink: 'd3869b'
+    lime: '689d6a'
+
+    gray: '928374'
+#+end_src
+*** Core
+#+begin_src yml :tangle ~/.config/vivid/gruvbox.yml
+  core:
+    regular_file: {}
+
+    directory:
+      foreground: blue
+
+    executable_file:
+      foreground: red
+      font-style: bold
+
+    symlink:
+      foreground: pink
+
+    broken_symlink:
+      foreground: black
+      background: red
+    missing_symlink_target:
+      foreground: black
+      background: red
+
+    fifo:
+      foreground: black
+      background: blue
+
+    socket:
+      foreground: black
+      background: pink
+
+    character_device:
+      foreground: black
+      background: lime
+
+    block_device:
+      foreground: black
+      background: red
+
+    normal_text:
+      {}
+
+    sticky:
+      {}
+
+    sticky_other_writable:
+      {}
+
+    other_writable:
+      {}
+
+  text:
+    special:
+      foreground: black
+      background: orange
+
+    todo:
+      font-style: bold
+
+    licenses:
+      foreground: gray
+
+    configuration:
+      foreground: orange
+
+    other:
+      foreground: orange
+
+  markup:
+    foreground: orange
+
+  programming:
+    source:
+      foreground: purple
+
+    tooling:
+      foreground: purple
+
+      continuous-integration:
+        foreground: purple
+
+  media:
+    foreground: pink
+
+  office:
+    foreground: red
+
+  archives:
+    foreground: lime
+    font-style: underline
+
+  executable:
+    foreground: red
+    font-style: bold
+
+  unimportant:
+    foreground: gray
+#+end_src
+** Git
+*** User
+#+begin_src plain :tangle ~/.gitconfig
+[user]
+       name = Armaan Bhojwani
+       email = me@armaanb.net
+       signingkey = 0FEB9471E19C49C60CFBEB133C9ED82FFE788E4A
+#+end_src
+*** Init
+#+begin_src plain :tangle ~/.gitconfig
+[init]
+       defaultBranch = main
+#+end_src
+*** GPG
+#+begin_src plain :tangle ~/.gitconfig
+[gpg]
+       program = gpg
+#+end_src
+*** Sendemail
+#+begin_src plain :tangle ~/.gitconfig
+[sendemail]
+       smtpserver = smtp.mailbox.org
+       smtpuser = me@armaanb.net
+       smtpencryption = ssl
+       smtpserverport = 465
+       confirm = auto
+#+end_src
+*** Submodules
+#+begin_src plain :tangle ~/.gitconfig
+[submodule]
+       recurse = true
+#+end_src
+*** Aliases
+#+begin_src plain :tangle ~/.gitconfig
+[alias]
+       stat = diff --stat
+       sclone = clone --depth 1
+       sclean = clean -dfX
+       a = add
+       aa = add .
+       c = commit
+       p = push
+       subup = submodule update --remote
+       loc = diff --stat 4b825dc642cb6eb9a060e54bf8d69288fbee4904 # Empty hash
+       mirror = git config --global alias.mirrormirror
+#+end_src
+*** Commits
+#+begin_src plain :tangle ~/.gitconfig
+[commit]
+       gpgsign = true
+#+end_src