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