]> git.armaanb.net Git - config.org.git/blob - config.org
Xresources: drop config
[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-11"))
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     )
81 #+end_src
82 ** Line numbers
83 Display relative line numbers except in certain modes.
84 #+begin_src emacs-lisp
85   (global-display-line-numbers-mode)
86   (setq display-line-numbers-type 'relative)
87   (dolist (no-line-num '(term-mode-hook
88                          pdf-view-mode-hook
89                          shell-mode-hook
90                          org-mode-hook
91                          circe-mode-hook
92                          eshell-mode-hook))
93     (add-hook no-line-num (lambda () (display-line-numbers-mode 0))))
94 #+end_src
95 ** Highlight matching parenthesis
96 #+begin_src emacs-lisp
97   (use-package paren
98     :config (show-paren-mode)
99     :custom (show-paren-style 'parenthesis))
100 #+end_src
101 ** Modeline
102 *** Show current function
103 #+begin_src emacs-lisp
104   (which-function-mode)
105 #+end_src
106 *** Make position in file more descriptive
107 Show current column and file size.
108 #+begin_src emacs-lisp
109   (column-number-mode)
110   (size-indication-mode)
111 #+end_src
112 *** Hide minor modes
113 #+begin_src emacs-lisp
114   (use-package minions
115     :config (minions-mode))
116 #+end_src
117 ** Whitespace mode
118 Highlight whitespace and other bad text practices.
119 #+begin_src emacs-lisp
120   (use-package whitespace
121     :custom (whitespace-style '(face lines-tail)))
122   (dolist (hook '(prog-mode-hook))
123     (add-hook hook (lambda () (whitespace-mode 1))))
124 #+end_src
125 ** Highlight todo items in comments
126 #+begin_src emacs-lisp
127   (use-package hl-todo
128     :straight (hl-todo :type git :host github :repo "tarsius/hl-todo")
129     :config (global-hl-todo-mode 1))
130 #+end_src
131 ** Blink cursor
132 #+begin_src emacs-lisp
133   (blink-cursor-mode)
134 #+end_src
135 ** Visual line mode
136 Soft wrap words and do operations by visual lines in some modes.
137 #+begin_src emacs-lisp
138   (dolist (hook '(text-mode-hook
139                   org-mode-hook
140                   markdown-mode-hook
141                   mu4e-view-mode-hook))
142     (add-hook hook (lambda () (visual-line-mode 1))))
143 #+end_src
144 ** Auto fill mode
145 #+begin_src emacs-lisp
146   (dolist (hook '(scdoc-mode-hook
147                   mu4e-compose-mode-hook))
148     (add-hook hook (lambda () (auto-fill-mode 1))))
149 #+end_src
150 ** Display number of matches in search
151 #+begin_src emacs-lisp
152   (use-package anzu
153     :after (evil)
154     :config (global-anzu-mode)
155     :bind
156     ([remap isearch-forward] . isearch-forward-regexp)
157     ([remap isearch-backward] . isearch-backward-regexp)
158     ([remap query-replace] . anzu-query-replace)
159     ([remap query-replace] . anzu-query-replace)
160     ([remap query-replace-regexp] . anzu-query-replace-regexp))
161 #+end_src
162 *** TODO This config doesn't work right
163 ** Visual bell
164 Invert modeline color instead of audible bell or the standard visual bell.
165 #+begin_src emacs-lisp
166   (setq visible-bell nil
167         ring-bell-function
168         (lambda () (invert-face 'mode-line)
169           (run-with-timer 0.1 nil #'invert-face 'mode-line)))
170 #+end_src
171 ** GUI
172 #+begin_src emacs-lisp
173   (scroll-bar-mode -1)
174   (tool-bar-mode -1)
175   (menu-bar-mode -1)
176   (setq-default frame-title-format '("%b [%m]"))
177 #+end_src
178 * Evil mode
179 ** General
180 #+begin_src emacs-lisp
181   (use-package evil
182     :custom (select-enable-clipboard nil)
183     :init (setq evil-want-keybinding nil
184                 evil-want-minibuffer t
185                 evil-want-C-d-scroll t
186                 evil-want-C-u-scroll t)
187     :config
188     (evil-mode)
189     (fset 'evil-visual-update-x-selection 'ignore) ;; Keep clipboard and register seperate
190     ;; Use visual line motions even outside of visual-line-mode buffers
191     (evil-global-set-key 'motion "j" 'evil-next-visual-line)
192     (evil-global-set-key 'motion "k" 'evil-previous-visual-line)
193     :bind
194     ("<escape>" . keyboard-escape-quit)
195     ("C-M-u" . universal-argument))
196 #+end_src
197 ** Evil collection
198 Evil bindings for tons of packages.
199 #+begin_src emacs-lisp
200   (use-package evil-collection
201     :after evil
202     :init (evil-collection-init)
203     :custom (evil-collection-setup-minibuffer t))
204 #+end_src
205 ** Surround
206 tpope prevails!
207 #+begin_src emacs-lisp
208   (use-package evil-surround
209     :config (global-evil-surround-mode))
210 #+end_src
211 ** Nerd commenter
212 Makes commenting super easy
213 #+begin_src emacs-lisp
214   (use-package evil-nerd-commenter
215     :bind (:map evil-normal-state-map
216                 ("gc" . evilnc-comment-or-uncomment-lines))
217     :custom (evilnc-invert-comment-line-by-line nil))
218 #+end_src
219 ** Undo redo
220 Fix the oopsies!
221 #+begin_src emacs-lisp
222   (use-package undo-fu
223     :config (evil-set-undo-system 'undo-fu))
224
225   (use-package undo-fu-session
226     :config (global-undo-fu-session-mode))
227 #+end_src
228 ** Number incrementing
229 Add back C-a/C-x bindings.
230 #+begin_src emacs-lisp
231   (use-package evil-numbers
232     :straight (evil-numbers :type git :host github :repo "juliapath/evil-numbers")
233     :bind (:map evil-normal-state-map
234                 ("C-M-a" . evil-numbers/inc-at-pt)
235                 ("C-M-x" . evil-numbers/dec-at-pt)))
236 #+end_src
237 ** Evil org
238 #+begin_src emacs-lisp
239   (use-package evil-org
240     :after org
241     :hook (org-mode . evil-org-mode)
242     :config
243     (evil-org-set-key-theme '(textobjects insert navigation shift todo)))
244
245   (use-package evil-org-agenda
246     :straight (:type built-in)
247     :after evil-org
248     :config (evil-org-agenda-set-keys))
249 #+end_src
250 * Org mode
251 ** General
252 #+begin_src emacs-lisp
253   (use-package org
254     :straight (:type built-in)
255     :commands (org-capture org-agenda)
256     :custom
257     (org-ellipsis " â–¾")
258     (org-agenda-start-with-log-mode t)
259     (org-agenda-files (quote ("~/org/tasks.org")))
260     (org-log-done 'time)
261     (org-log-into-drawer t)
262     (org-src-tab-acts-natively t)
263     (org-src-fontify-natively t)
264     (org-startup-indented t)
265     (org-hide-emphasis-markers t)
266     (org-fontify-whole-block-delimiter-line nil)
267     (org-archive-default-command 'org-archive-to-archive-sibling)
268     :bind
269     ("C-c a" . org-agenda)
270     (:map evil-normal-state-map ("ga" . org-archive-subtree-default)))
271 #+end_src
272 ** Tempo
273 Define templates for lots of common structure elements. Mostly just used within this file.
274 #+begin_src emacs-lisp
275   (use-package org-tempo
276     :after org
277     :straight (:type built-in)
278     :config
279     (dolist (addition '(
280                         ("ash" . "src shell :tangle ~/.config/ash/ashrc")
281                         ("el" . "src emacs-lisp")
282                         ("git" . "src conf :tangle ~/.gitconfig")
283                         ("mb" . "src conf :tangle ~/.mbsyncrc")
284                         ("sp" . "src conf :tangle ~/.spectrwm.conf")
285                         ("tm" . "src conf :tangle ~/.tmux.conf")
286                         ("za" . "src conf :tangle ~/.config/zathura/zathurarc")
287                         ))
288       (add-to-list 'org-structure-template-alist addition)))
289 #+end_src
290 * Autocompletion
291 ** Ivy
292 A well balanced completion framework.
293 #+begin_src emacs-lisp
294   (use-package ivy
295     :bind (:map ivy-minibuffer-map
296            ("TAB" . ivy-alt-done))
297            (:map ivy-switch-buffer-map
298            ("M-d" . ivy-switch-buffer-kill))
299     :config (ivy-mode))
300 #+end_src
301 ** Ivy-rich
302 #+begin_src emacs-lisp
303   (use-package ivy-rich
304     :after (ivy counsel)
305     :config (ivy-rich-mode))
306 #+end_src
307 ** Counsel
308 Ivy everywhere.
309 #+begin_src emacs-lisp
310   (use-package counsel
311     :bind ("C-M-j" . 'counsel-switch-buffer)
312     :config (counsel-mode))
313 #+end_src
314 ** Remember frequent commands
315 #+begin_src emacs-lisp
316   (use-package ivy-prescient
317     :after counsel
318     :config
319     (prescient-persist-mode)
320     (ivy-prescient-mode))
321 #+end_src
322 * Emacs OS
323 ** RSS
324 Use elfeed for reading RSS. I have another file with all the feeds in it that I'd rather keep private.
325 #+begin_src emacs-lisp
326   (use-package elfeed
327     :bind (("C-c e" . elfeed))
328     :config (load "~/.emacs.d/feeds.el")
329     :custom (elfeed-db-directory "~/.emacs.d/elfeed")
330     :bind (:map elfeed-search-mode-map ("C-c C-o" . 'elfeed-show-visit)))
331 #+end_src
332 ** Email
333 Use mu4e and mbsync for reading emails.
334
335 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.
336 *** mbsync
337 **** General
338 #+begin_src conf :tangle ~/.mbsyncrc
339   Create Near
340   Expunge Both
341   SyncState *
342 #+end_src
343 **** Personal
344 #+begin_src conf :tangle ~/.mbsyncrc
345   IMAPStore personal-remote
346   Host imap.mailbox.org
347   User me@armaanb.net
348   PassCmd "pash show login.mailbox.org/me@armaanb.net | head -n 1"
349
350   MaildirStore personal-local
351   Path ~/mail/personal/
352   Inbox ~/mail/personal/Inbox
353   Subfolders Verbatim
354
355   Channel personal-channel
356   Far :personal-remote:
357   Near :personal-local:
358   Patterns "INBOX*" "Drafts" "Archive" "Sent" "Trash"
359
360   Group personal
361   Channel personal-channel
362 #+end_src
363 **** School
364 #+begin_src conf :tangle ~/.mbsyncrc
365   IMAPStore school-remote
366   SSLType IMAPS
367   Host imap.gmail.com
368   User abhojwani22@nobles.edu
369   PassCmd "pash show gmail-otp/abhojwani22@nobles.edu | head -n 1"
370
371   MaildirStore school-local
372   Path ~/mail/school/
373   Inbox ~/mail/school/Inbox
374   Subfolders Verbatim
375
376   Channel school-channel
377   Far :school-remote:
378   Near :school-local:
379   Patterns * ![Gmail]*
380
381   Group school
382   Channel school-channel
383 #+end_src
384 *** mu4e
385 **** Setup
386 #+begin_src emacs-lisp
387   (use-package smtpmail
388     :straight (:type built-in))
389   (use-package mu4e
390     :load-path "/usr/share/emacs/site-lisp/mu4e"
391     :straight (:build nil)
392     :bind (("C-c m" . mu4e))
393     :config
394     (setq user-full-name "Armaan Bhojwani"
395           smtpmail-local-domain "armaanb.net"
396           smtpmail-stream-type 'ssl
397           smtpmail-smtp-service '465
398           mu4e-change-filenames-when-moving t
399           mu4e-get-mail-command "mbsync -a"
400           message-citation-line-format "On %a %d %b %Y at %R, %f wrote:\n"
401           message-citation-line-function 'message-insert-formatted-citation-line
402           mu4e-completing-read-function 'ivy-completing-read
403           mu4e-confirm-quit nil
404           mu4e-view-use-gnus t
405           mail-user-agent 'mu4e-user-agent
406           mu4e-context-policy 'pick-first
407           mu4e-contexts
408           `( ,(make-mu4e-context
409                :name "school"
410                :enter-func (lambda () (mu4e-message "Entering school context"))
411                :leave-func (lambda () (mu4e-message "Leaving school context"))
412                :match-func (lambda (msg)
413                              (when msg
414                                (string-match-p "^/school" (mu4e-message-field msg :maildir))))
415                :vars '((user-mail-address . "abhojwani22@nobles.edu")
416                        (mu4e-sent-folder . "/school/Sent")
417                        (mu4e-drafts-folder . "/school/Drafts")
418                        (mu4e-trash-folder . "/school/Trash")
419                        (mu4e-refile-folder . "/school/Archive")
420                        (message-cite-reply-position . above)
421                        (user-mail-address . "abhojwani22@nobles.edu")
422                        (smtpmail-smtp-user . "abhojwani22@nobles.edu")
423                        (smtpmail-smtp-server . "smtp.gmail.com")))
424              ,(make-mu4e-context
425                :name "personal"
426                :enter-func (lambda () (mu4e-message "Entering personal context"))
427                :leave-func (lambda () (mu4e-message "Leaving personal context"))
428                :match-func (lambda (msg)
429                              (when msg
430                                (string-match-p "^/personal" (mu4e-message-field msg :maildir))))
431                :vars '((mu4e-sent-folder . "/personal/Sent")
432                        (mu4e-drafts-folder . "/personal/Drafts")
433                        (mu4e-trash-folder . "/personal/Trash")
434                        (mu4e-refile-folder . "/personal/Archive")
435                        (user-mail-address . "me@armaanb.net")
436                        (message-cite-reply-position . below)
437                        (smtpmail-smtp-user . "me@armaanb.net")
438                        (smtpmail-smtp-server . "smtp.mailbox.org")))))
439     (add-to-list 'mu4e-bookmarks
440                  '(:name "Unified inbox"
441                          :query "maildir:\"/personal/Inbox\" or maildir:\"/school/Inbox\""
442                          :key ?b))
443     :hook ((mu4e-compose-mode . flyspell-mode)
444            (message-send-hook . (lambda () (unless (yes-or-no-p "Ya sure 'bout that?")
445                                              (signal 'quit nil))))))
446 #+end_src
447 **** Discourage Gnus from displaying HTML emails
448 #+begin_src emacs-lisp
449   (with-eval-after-load "mm-decode"
450     (add-to-list 'mm-discouraged-alternatives "text/html")
451     (add-to-list 'mm-discouraged-alternatives "text/richtext"))
452 #+end_src
453 ** Default browser
454 Set EWW as default browser except for multimedia which should open in MPV.
455 #+begin_src emacs-lisp
456   (defun browse-url-mpv (url &optional new-window)
457     "Ask MPV to load URL."
458     (interactive)
459     (start-process "mpv" "*mpv*" "mpv" url))
460
461   (setq browse-url-handlers
462         (quote
463          (("youtu\\.?be" . browse-url-mpv)
464           ("peertube.*" . browse-url-mpv)
465           ("vid.*" . browse-url-mpv)
466           ("vid.*" . browse-url-mpv)
467           ("*.mp4" . browse-url-mpv)
468           ("*.mp3" . browse-url-mpv)
469           ("*.ogg" . browse-url-mpv)
470           ("." . eww-browse-url)
471           )))
472 #+end_src
473 ** EWW
474 Some EWW enhancements.
475 *** Give buffer a useful name
476 #+begin_src emacs-lisp
477   ;; From https://protesilaos.com/dotemacs/
478   (defun prot-eww--rename-buffer ()
479     "Rename EWW buffer using page title or URL.
480         To be used by `eww-after-render-hook'."
481     (let ((name (if (eq "" (plist-get eww-data :title))
482                     (plist-get eww-data :url)
483                   (plist-get eww-data :title))))
484       (rename-buffer (format "*%s # eww*" name) t)))
485
486   (use-package eww
487     :straight (:type built-in)
488     :bind (("C-c w" . eww))
489     :hook (eww-after-render-hook prot-eww--rename-buffer))
490 #+end_src
491 *** Keybinding
492 #+begin_src emacs-lisp
493   (global-set-key (kbd "C-c w") 'eww)
494 #+end_src
495 ** IRC
496 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.
497 #+begin_src emacs-lisp
498   (defun fetch-password (&rest params)
499     (require 'auth-source)
500     (let ((match (car (apply 'auth-source-search params))))
501       (if match
502           (let ((secret (plist-get match :secret)))
503             (if (functionp secret)
504                 (funcall secret)
505               secret))
506         (error "Password not found for %S" params))))
507
508   (use-package circe
509     :config
510     (enable-lui-track)
511     (enable-circe-color-nicks)
512     (setq circe-network-defaults '(("libera"
513                                     :host "irc.armaanb.net"
514                                     :nick "emacs"
515                                     :user "emacs"
516                                     :use-tls t
517                                     :port 6698
518                                     :pass (lambda (null) (fetch-password
519                                                           :login "emacs"
520                                                           :machine "irc.armaanb.net"
521                                                           :port 6698)))
522                                    ("oftc"
523                                     :host "irc.armaanb.net"
524                                     :nick "emacs"
525                                     :user "emacs"
526                                     :use-tls t
527                                     :port 6699
528                                     :pass (lambda (null) (fetch-password
529                                                           :login "emacs"
530                                                           :machine "irc.armaanb.net"
531                                                           :port 6699)))
532                                    ("tilde"
533                                     :host "irc.armaanb.net"
534                                     :nick "emacs"
535                                     :user "emacs"
536                                     :use-tls t
537                                     :port 6696
538                                     :pass (lambda (null) (fetch-password
539                                                           :login "emacs"
540                                                           :machine "irc.armaanb.net"
541                                                           :port 6696)))))
542     :custom (circe-default-part-message "goodbye!")
543     :bind (:map circe-mode-map ("C-c C-r" . circe-reconnect-all)))
544
545   (defun acheam-irc ()
546     "Open circe"
547     (interactive)
548     (if (get-buffer "irc.armaanb.net:6696")
549         (switch-to-buffer "irc.armaanb.net:6696")
550       (progn (switch-to-buffer "*scratch*")
551              (circe "libera")
552              (circe "oftc")
553              (circe "tilde"))))
554
555   (global-set-key (kbd "C-c i") 'acheam-irc)
556 #+end_src
557 ** Calendar
558 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.
559 #+begin_src emacs-lisp
560   (defun sync-calendar ()
561     "Sync calendars with vdirsyncer"
562     (interactive)
563     (async-shell-command "vdirsyncer sync"))
564
565   (use-package calfw
566     :bind (:map cfw:calendar-mode-map ("C-S-u" . sync-calendar)))
567   (use-package calfw-ical)
568   (use-package calfw-org)
569
570   (defun acheam-calendar ()
571     "Open calendars"
572     (interactive)
573     (cfw:open-calendar-buffer
574      :contents-sources (list
575                         (cfw:org-create-source "Green")
576                         (cfw:ical-create-source
577                          "Personal"
578                          "~/.local/share/vdirsyncer/mailbox/Y2FsOi8vMC8zMQ.ics"
579                          "Gray")
580                         (cfw:ical-create-source
581                          "Personal"
582                          "~/.local/share/vdirsyncer/mailbox/Y2FsOi8vMC8zMQ.ics"
583                          "Red")
584                         (cfw:ical-create-source
585                          "School"
586                          "~/.local/share/vdirsyncer/school/abhojwani22@nobles.edu.ics"
587                          "Cyan"))
588      :view 'week))
589
590   (global-set-key (kbd "C-c c") 'acheam-calendar)
591 #+end_src
592 ** PDF reader
593 #+begin_src emacs-lisp
594   (use-package pdf-tools
595     :hook (pdf-view-mode . pdf-view-midnight-minor-mode))
596 #+end_src
597 * Emacs IDE
598 ** Python formatting
599 #+begin_src emacs-lisp
600   (use-package blacken
601     :hook (python-mode . blacken-mode)
602     :custom (blacken-line-length 79))
603
604 #+end_src
605 ** Strip trailing whitespace
606 #+begin_src emacs-lisp
607   (use-package ws-butler
608     :config (ws-butler-global-mode))
609 #+end_src
610 ** Flycheck
611 Automatic linting. I need to look into configuring this more.
612 #+begin_src emacs-lisp
613   (use-package flycheck
614     :config (global-flycheck-mode))
615 #+end_src
616 ** Project management
617 I never use this, but apparently its very powerful. Another item on my todo list.
618 #+begin_src emacs-lisp
619   (use-package projectile
620     :config (projectile-mode)
621     :custom ((projectile-completion-system 'ivy))
622     :bind-keymap ("C-c p" . projectile-command-map)
623     :init (setq projectile-switch-project-action #'projectile-dired))
624
625   (use-package counsel-projectile
626     :after projectile
627     :config (counsel-projectile-mode))
628 #+end_src
629 ** Dired
630 The best file manager!
631 #+begin_src emacs-lisp
632   (use-package dired
633     :straight (:type built-in)
634     :commands (dired dired-jump)
635     :custom (dired-listing-switches "-agh --group-directories-first")
636     :bind
637     ([remap dired-find-file] . dired-single-buffer)
638     ([remap dired-mouse-find-file-other-window] . dired-single-buffer-mouse)
639     ([remap dired-up-directory] . dired-single-up-directory)
640     ("C-x C-j" . dired-jump))
641
642   (use-package dired-single
643     :commands (dired dired-jump))
644
645   (use-package dired-open
646     :commands (dired dired-jump)
647     :custom (dired-open-extensions '(("png" . "feh")
648                                      ("mkv" . "mpv"))))
649
650   (use-package dired-hide-dotfiles
651     :hook (dired-mode . dired-hide-dotfiles-mode)
652     :config (evil-collection-define-key 'normal 'dired-mode-map
653       "H" 'dired-hide-dotfiles-mode))
654 #+end_src
655 ** Git
656 *** Magit
657 A very good Git interface.
658 #+begin_src emacs-lisp
659   (use-package magit)
660 #+end_src
661 *** Email
662 #+begin_src emacs-lisp
663   (use-package piem)
664   ;; (use-package git-email
665   ;;   :straight (git-email :repo "https://git.sr.ht/~yoctocell/git-email")
666   ;;   :config (git-email-piem-mode))
667 #+end_src
668 ** C
669 Modified from https://eklitzke.org/smarter-emacs-clang-format.
670
671 Style is basically ddevault's style guide but with 4 spaces instead of 8 char tabs.
672 #+begin_src emacs-lisp
673   (use-package clang-format
674     :custom (clang-format-style "{
675         BasedOnStyle: llvm,
676         AlwaysBreakAfterReturnType: AllDefinitions,
677         IndentWidth: 4,
678         }"))
679
680   (defun clang-format-buffer-smart ()
681     "Reformat buffer if .clang-format exists in the projectile root."
682     (when (file-exists-p (expand-file-name ".clang-format" (projectile-project-root)))
683       (when (if (eq major-mode 'c-mode))
684         (message "Formatting with clang-format...")
685         (clang-format-buffer))))
686
687   (add-hook 'before-save-hook 'clang-format-buffer-smart nil)
688 #+end_src
689 * General text editing
690 ** Spell checking
691 Spell check in text mode, and in prog-mode comments.
692 #+begin_src emacs-lisp
693   (dolist (hook '(text-mode-hook
694                   markdown-mode-hook
695                   scdoc-mode-hook))
696     (add-hook hook (lambda () (flyspell-mode))))
697   (dolist (hook '(change-log-mode-hook log-edit-mode-hook))
698     (add-hook hook (lambda () (flyspell-mode -1))))
699   (add-hook 'prog-mode (lambda () (flyspell-prog mode)))
700   (setq ispell-silently-savep t)
701 #+end_src
702 ** Sane tab width
703 #+begin_src emacs-lisp
704   (setq-default tab-width 2)
705 #+end_src
706 ** Save place
707 Opens file where you left it.
708 #+begin_src emacs-lisp
709   (save-place-mode)
710 #+end_src
711 ** Writing mode
712 Distraction free writing a la junegunn/goyo.
713 #+begin_src emacs-lisp
714   (use-package olivetti
715     :bind ("C-c o" . olivetti-mode))
716 #+end_src
717 ** Abbreviations
718 Abbreviate things! I just use this for things like my email address and copyright notice.
719 #+begin_src emacs-lisp
720   (setq abbrev-file-name "~/.emacs.d/abbrevs.el")
721   (setq save-abbrevs 'silent)
722   (setq-default abbrev-mode t)
723 #+end_src
724 ** TRAMP
725 #+begin_src emacs-lisp
726   (setq tramp-default-method "ssh")
727 #+end_src
728 ** Follow version controlled symlinks
729 #+begin_src emacs-lisp
730   (setq vc-follow-symlinks t)
731 #+end_src
732 ** Open file as root
733 #+begin_src emacs-lisp
734   (defun doas-edit (&optional arg)
735     "Edit currently visited file as root.
736
737     With a prefix ARG prompt for a file to visit.  Will also prompt
738     for a file to visit if current buffer is not visiting a file.
739
740     Modified from Emacs Redux."
741     (interactive "P")
742     (if (or arg (not buffer-file-name))
743         (find-file (concat "/doas:root@localhost:"
744                            (ido-read-file-name "Find file(as root): ")))
745       (find-alternate-file (concat "/doas:root@localhost:" buffer-file-name))))
746
747     (global-set-key (kbd "C-x C-r") #'doas-edit)
748 #+end_src
749 ** Markdown mode
750 #+begin_src emacs-lisp
751   (use-package markdown-mode)
752 #+end_src
753 ** scdoc mode
754 Get it for yourself at https://git.armaanb.net/scdoc
755 #+begin_src emacs-lisp
756   (add-to-list 'load-path "~/src/scdoc-mode")
757   (autoload 'scdoc-mode "scdoc-mode" "Major mode for editing scdoc files" t)
758   (add-to-list 'auto-mode-alist '("\\.scd\\'" . scdoc-mode))
759 #+end_src
760 * Keybindings
761 ** Switch windows
762 #+begin_src emacs-lisp
763   (use-package ace-window
764     :bind ("M-o" . ace-window))
765 #+end_src
766 ** Kill current buffer
767 Makes "C-x k" binding faster.
768 #+begin_src emacs-lisp
769   (substitute-key-definition 'kill-buffer 'kill-buffer-and-window global-map)
770 #+end_src
771 * Other settings
772 ** OpenSCAD syntax
773 #+begin_src emacs-lisp
774   (use-package scad-mode)
775 #+end_src
776 ** Control backup and lock files
777 Stop backup files from spewing everywhere.
778 #+begin_src emacs-lisp
779   (setq backup-directory-alist `(("." . "~/.emacs.d/backups"))
780         create-lockfiles nil)
781 #+end_src
782 ** Make yes/no easier
783 #+begin_src emacs-lisp
784   (defalias 'yes-or-no-p 'y-or-n-p)
785 #+end_src
786 ** Move customize file
787 No more clogging up init.el.
788 #+begin_src emacs-lisp
789   (setq custom-file "~/.emacs.d/custom.el")
790   (load custom-file)
791 #+end_src
792 ** Better help
793 #+begin_src emacs-lisp
794   (use-package helpful
795     :commands (helpful-callable helpful-variable helpful-command helpful-key)
796     :custom
797     (counsel-describe-function-function #'helpful-callable)
798     (counsel-describe-variable-function #'helpful-variable)
799     :bind
800     ([remap describe-function] . counsel-describe-function)
801     ([remap describe-command] . helpful-command)
802     ([remap describe-variable] . counsel-describe-variable)
803     ([remap describe-key] . helpful-key))
804 #+end_src
805 ** GPG
806 #+begin_src emacs-lisp
807   (use-package epa-file
808     :straight (:type built-in)
809     :custom
810     (epa-file-select-keys nil)
811     (epa-file-encrypt-to '("me@armaanb.net"))
812     (password-cache-expiry (* 60 15)))
813
814   (use-package pinentry
815     :config (pinentry-start))
816 #+end_src
817 ** Pastebin
818 #+begin_src emacs-lisp
819   (use-package 0x0
820     :straight (0x0 :type git :repo "https://git.sr.ht/~zge/nullpointer-emacs")
821     :custom (0x0-default-service 'envs))
822 #+end_src
823 *** TODO Replace this with uploading to my own server
824 Similar to the ufile alias in my ashrc
825 ** Automatically clean buffers
826 Automatically close unused buffers (except those of Circe) at midnight.
827 #+begin_src emacs-lisp
828   (midnight-mode)
829   (add-to-list 'clean-buffer-list-kill-never-regexps
830                (lambda (buffer-name)
831                  (with-current-buffer buffer-name
832                    (derived-mode-p 'lui-mode))))
833 #+end_src
834 * Tangles
835 ** Ash
836 *** Options
837 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.
838 #+begin_src conf :tangle ~/.config/ash/ashrc
839   set -o vi
840 #+end_src
841 *** Functions
842 **** Finger
843 #+begin_src shell :tangle ~/.config/ash/ashrc
844   finger() {
845       user=$(echo "$1" | cut -f 1 -d '@')
846       host=$(echo "$1" | cut -f 2 -d '@')
847       echo $user | nc "$host" 79
848   }
849 #+end_src
850 **** Upload to ftp.armaanb.net
851 #+begin_src shell :tangle ~/.config/ash/ashrc
852   _uprint() {
853       echo "https://l.armaanb.net/$(basename "$1")" | tee /dev/tty | xclip -sel c
854   }
855
856   _uup() {
857       rsync "$1" "armaa@armaanb.net:/srv/ftp/pub/$2" --chmod 644 --progress
858   }
859
860   ufile() {
861       _uup "$1" "$2"
862       _uprint "$1"
863   }
864
865   uclip() {
866       tmp=$(mktemp)
867       xclip -o -sel c >> "$tmp"
868       basetmp=$(echo "$tmp" | tail -c +5)
869       _uup "$tmp" "$basetmp"
870       _uprint "$basetmp"
871       rm -f "$tmp"
872   }
873 #+end_src
874 *** Exports
875 **** Default programs
876 #+begin_src shell :tangle ~/.config/ash/ashrc
877   export EDITOR="emacsclient -c"
878   export VISUAL="$EDITOR"
879   export TERM=xterm-256color # for compatability
880   #+end_src
881 **** General program configs
882 #+begin_src shell :tangle ~/.config/ash/ashrc
883   export GPG_TTY="$(tty)"
884   export MANPAGER='nvim +Man!'
885   export PAGER='less'
886   export GTK_USE_PORTAL=1
887   export CDPATH=:~
888   export LESSHISTFILE=/dev/null
889   export PASH_KEYID=me@armaanb.net
890   export PASH_LENGTH=20
891 #+end_src
892 **** PATH
893 #+begin_src shell :tangle ~/.config/ash/ashrc
894   export PATH="/home/armaa/src/bin:$PATH"
895   export PATH="/home/armaa/src/bin/bin:$PATH"
896   export PATH="/home/armaa/.local/bin:$PATH"
897   export PATH="/usr/lib/ccache/bin:$PATH"
898 #+end_src
899 **** Locale
900 #+begin_src shell :tangle ~/.config/ash/ashrc
901   export LC_ALL="en_US.UTF-8"
902   export LC_CTYPE="en_US.UTF-8"
903   export LANGUAGE="en_US.UTF-8"
904   export TZ="America/New_York"
905 #+end_src
906 **** KISS
907 #+begin_src shell :tangle ~/.config/ash/ashrc
908   export KISS_PATH=""
909   export KISS_PATH="$KISS_PATH:$HOME/repos/personal"
910   export KISS_PATH="$KISS_PATH:$HOME/repos/bin/bin"
911   export KISS_PATH="$KISS_PATH:$HOME/repos/main/core"
912   export KISS_PATH="$KISS_PATH:$HOME/repos/main/extra"
913   export KISS_PATH="$KISS_PATH:$HOME/repos/main/xorg"
914   export KISS_PATH="$KISS_PATH:$HOME/repos/community/community"
915   export KISS_PATH="$KISS_PATH:$HOME/repos/mid/ports"
916
917   export KISS_COMPRESS=xz
918 #+end_src
919 **** Compilation flags
920 #+begin_src shell :tangle ~/.config/ash/ashrc
921   export CFLAGS="-O3 -pipe -march=native"
922   export CXXFLAGS="$CFLAGS"
923   export MAKEFLAGS="-j$(nproc)"
924   export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig"
925 #+end_src
926 **** XDG desktop dirs
927 #+begin_src shell :tangle ~/.config/ash/ashrc
928   export XDG_DESKTOP_DIR="/dev/null"
929   export XDG_DOCUMENTS_DIR="$HOME/documents"
930   export XDG_DOWNLOAD_DIR="$HOME/downloads"
931   export XDG_MUSIC_DIR="$HOME/music"
932   export XDG_PICTURES_DIR="$HOME/pictures"
933   export XDG_VIDEOS_DIR="$HOME/videos"
934 #+end_src
935 *** Aliases
936 **** SSH
937 #+begin_src shell :tangle ~/.config/ash/ashrc
938   alias poki='ssh armaanb.net'
939   alias irc='ssh root@armaanb.net -t abduco -A irc catgirl freenode'
940   alias union='ssh 192.168.1.18'
941   alias mine='ssh -p 23 root@pickupserver.cc'
942   alias tcf='ssh root@204.48.23.68'
943   alias ngmun='ssh root@157.245.89.25'
944   alias prox='ssh root@192.168.1.224'
945   alias ncq='ssh root@143.198.123.17'
946   alias envs='ssh acheam@envs.net'
947 #+end_src
948 **** File management
949 #+begin_src shell :tangle ~/.config/ash/ashrc
950   alias ls='LC_COLLATE=C ls -lh --group-directories-first'
951   alias la='ls -A'
952   alias df='df -h / /boot'
953   alias du='du -h'
954   alias free='free -m'
955   alias cp='cp -riv'
956   alias rm='rm -iv'
957   alias mv='mv -iv'
958   alias ln='ln -v'
959   alias grep='grep -in'
960   alias mkdir='mkdir -pv'
961   alias lanex='java -jar ~/.local/share/lxc/lanxchange.jar && rm lxc*'
962   emacs() { $EDITOR "$@" & }
963   alias vim="emacs"
964 #+end_src
965 **** System management
966 #+begin_src shell :tangle ~/.config/ash/ashrc
967   alias crontab='crontab-argh'
968   alias sudo='doas'
969   alias pasu='git -C ~/.password-store push'
970   alias yadu='yadm add -u && yadm commit -m "Updated `date -Iseconds`" && \
971     yadm push'
972 #+end_src
973 **** Networking
974 #+begin_src shell :tangle ~/.config/ash/ashrc
975   alias ping='ping -c 10'
976   alias gps='gpg --keyserver keyserver.ubuntu.com --search-keys'
977   alias gpp='gpg --keyserver keyserver.ubuntu.com --recv-key'
978   alias plan='T=$(mktemp) && \
979           rsync armaanb.net:/home/armaa/plan.txt "$T" && \
980           TT=$(mktemp) && \
981           head -n -2 $T > $TT && \
982           /bin/nvim $TT && \
983           echo >> "$TT" && \
984           echo "Last updated: $(date -R)" >> "$TT" && \
985           fold -sw 72 "$TT" > "$T"| \
986           rsync "$T" armaanb.net:/home/armaa/plan.txt && \
987           rm -f "$T"'
988 #+end_src
989 **** Virtual machines, chroots
990 #+begin_src shell :tangle ~/.config/ash/ashrc
991   alias cwindows='qemu-system-x86_64 \
992     -smp 3 \
993     -cpu host \
994     -enable-kvm \
995     -m 3G \
996     -device VGA,vgamem_mb=64 \
997     -device intel-hda \
998     -device hda-duplex \
999     -net nic \
1000     -net user,smb=/home/armaa/public \
1001     -drive format=qcow2,file=/home/armaa/virtual/windows.qcow2'
1002 #+end_src
1003 **** Latin
1004 #+begin_src shell :tangle ~/.config/ash/ashrc
1005   alias words='gen-shell -c "words"'
1006   alias words-e='gen-shell -c "words ~E"'
1007 #+end_src
1008 **** Other
1009 #+begin_src shell :tangle ~/.config/ash/ashrc
1010   alias bigrandomfile='dd if=/dev/urandom of=1GB-urandom bs=1M count=1024 \
1011     iflag=fullblock'
1012   alias bigboringfile='dd if=/dev/zero of=1GB-zero bs=1M count=1024 \
1013     iflag=fullblock'
1014   alias ytmusic="youtube-dl -x --add-metadata  --audio-format aac \
1015     --restrict-filenames -o '%(title)s.%(ext)s'"
1016   alias bc='bc -l'
1017 #+end_src
1018 ** MPV
1019 Make MPV play a little bit smoother.
1020 #+begin_src conf :tangle ~/.config/mpv/mpv.conf
1021   ytdl-format="bestvideo[height<=?1080]+bestaudio/best"
1022   hwdec=auto-copy
1023 #+end_src
1024 ** Inputrc
1025 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!.
1026 #+begin_src conf :tangle ~/.inputrc
1027   set editing-mode emacs
1028 #+end_src
1029 ** Git
1030 *** User
1031 #+begin_src conf :tangle ~/.gitconfig
1032   [user]
1033   name = Armaan Bhojwani
1034   email = me@armaanb.net
1035   signingkey = 0FEB9471E19C49C60CFBEB133C9ED82FFE788E4A
1036 #+end_src
1037 *** Init
1038 #+begin_src conf :tangle ~/.gitconfig
1039   [init]
1040   defaultBranch = main
1041 #+end_src
1042 *** GPG
1043 #+begin_src conf :tangle ~/.gitconfig
1044   [gpg]
1045   program = gpg
1046 #+end_src
1047 *** Sendemail
1048 #+begin_src conf :tangle ~/.gitconfig
1049   [sendemail]
1050   smtpserver = smtp.mailbox.org
1051   smtpuser = me@armaanb.net
1052   smtpencryption = ssl
1053   smtpserverport = 465
1054   confirm = auto
1055 #+end_src
1056 *** Submodule
1057 #+begin_src conf :tangle ~/.gitconfig
1058   [submodule]
1059   recurse = true
1060 #+end_src
1061 *** Aliases
1062 #+begin_src conf :tangle ~/.gitconfig
1063   [alias]
1064   stat = diff --stat
1065   sclone = clone --depth 1
1066   sclean = clean -dfX
1067   a = add
1068   aa = add .
1069   c = commit
1070   quickfix = commit . --amend --no-edit
1071   p = push
1072   subup = submodule update --remote
1073   loc = diff --stat 4b825dc642cb6eb9a060e54bf8d69288fbee4904 # Empty hash
1074   pushnc = push -o skip-ci
1075 #+end_src
1076 *** Commit
1077 #+begin_src conf :tangle ~/.gitconfig
1078   [commit]
1079   gpgsign = true
1080   verbose = true
1081 #+end_src
1082 *** Tag
1083 #+begin_src conf :tangle ~/.gitconfig
1084   [tag]
1085   gpgsign = true
1086 #+end_src
1087 ** Zathura
1088 The best document reader!
1089 *** Options
1090 #+begin_src conf :tangle ~/.config/zathura/zathurarc
1091   map <C-i> recolor
1092   map <A-b> toggle_statusbar
1093   set selection-clipboard clipboard
1094   set scroll-step 200
1095
1096   set window-title-basename "true"
1097   set selection-clipboard "clipboard"
1098 #+end_src
1099 *** Colors
1100 #+begin_src conf :tangle ~/.config/zathura/zathurarc
1101   set default-bg         "#000000"
1102   set default-fg         "#ffffff"
1103   set render-loading     true
1104   set render-loading-bg  "#000000"
1105   set render-loading-fg  "#ffffff"
1106
1107   set recolor-lightcolor "#000000" # bg
1108   set recolor-darkcolor  "#ffffff" # fg
1109   set recolor            "true"
1110 #+end_src
1111 ** Tmux
1112 I use tmux in order to keep my st build light. Still learning how it works.
1113 #+begin_src conf :tangle ~/.tmux.conf
1114   set -g status off
1115   set -g mouse on
1116
1117   set-option -g history-limit 50000
1118
1119   set -g set-titles on
1120   set -g set-titles-string "#W"
1121
1122   set-window-option -g mode-keys vi
1123   bind-key -T copy-mode-vi 'v' send -X begin-selection
1124   bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard'
1125 #+end_src
1126 ** GPG
1127 *** Config
1128 #+begin_src conf :tangle ~/.gnupg/gpg.conf
1129   default-key 3C9ED82FFE788E4A
1130   use-agent
1131 #+end_src
1132 *** Agent
1133 #+begin_src conf :tangle ~/.gnupg/gpg-agent.conf
1134   pinentry-program /sbin/pinentry
1135   max-cache-ttl 6000
1136   default-cache-ttl 6000
1137   allow-emacs-pinentry
1138 #+end_src
1139 ** Xmodmap
1140 #+begin_src conf :tangle (progn (if (string= (system-name) "frost.armaanb.net") "~/.config/xmodmap" "no"))
1141   ! Unmap left super
1142   clear mod4
1143
1144   ! Turn right alt into super
1145   remove mod1 = Alt_R
1146   add mod4 = Alt_R
1147
1148   ! Swap caps and control
1149   remove Lock = Caps_Lock
1150   remove Control = Control_L
1151   remove Lock = Control_L
1152   remove Control = Caps_Lock
1153   keysym Control_L = Caps_Lock
1154   keysym Caps_Lock = Control_L
1155   add Lock = Caps_Lock
1156   add Control = Control_L
1157 #+end_src
1158 ** sx
1159 #+begin_src shell :tangle ~/.config/sx/sxrc :tangle-mode (identity #o755)
1160   autostart &
1161   dwmblocks &
1162   exec dwm
1163 #+end_src