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