Adithya Chari

Email: contact@adchari.dev

Sourcehut: adchari

LinkedIn: adithyachari

Résumé: Click Here

~/adchari/.emacs/

;; Let's start with some things that directly change how Emacs works...
;; Increase GC limit to 10MB and enable garbage collection on loss of focus
(setq gc-cons-threshold 100000000)
(add-function :after after-focus-change-function 'garbage-collect)

;; Natively compile .emacs.el when the file is saved
(defun autocompile nil
  "Compile itself if ~/.emacs.el."
  (interactive)
  (require 'comp)
  (let ((dotemacs (file-truename user-init-file)))
    (if (string= (buffer-file-name) (file-chase-links dotemacs))
		(native-compile dotemacs))))
(add-hook 'after-save-hook 'autocompile)

;; Store all backup and autosave files in the tmp dir
(setq backup-directory-alist `((".*" . ,temporary-file-directory))
	  auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))

;; Make sure Emacs auto-reverts files
(global-auto-revert-mode)

;; Move custom.el bindings to an .emacs.d/ file
(setq custom-file "~/.emacs.d/custom.el")
(load custom-file :noerror)

;; Enable some disabled features
(put 'narrow-to-region 'disabled nil)


;; Now, time to configure package management...
;; Add MELPA support and require use-package
(require 'package)
(require 'use-package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

;; Enable no-littering to clean up .emacs.d
(use-package no-littering)


;; Aaand, let's make things look pretty...
;; First, maximize Emacs on open
(setq initial-frame-alist '((fullscreen . maximized))
	  default-frame-alist '((fullscreen . maximized)))

;; Now, let's get rid of the cruft
(tool-bar-mode -1)
(scroll-bar-mode -1)
(menu-bar-mode -1)

(setq inhibit-startup-screen t
	  initial-major-mode 'fundamental-mode
	  use-short-answers t)
(setq-default cursor-type 'bar
			  indent-tabs-mode nil
			  tab-width 4)

;; Emacs 29 comes with fancy smooth-scrolling, enable it
(setq pixel-scroll-precision-large-scroll-height 40.0
	  pixel-scroll-precision-interpolation-factor 30)
(pixel-scroll-precision-mode)

;; Emacs 28+ has modus-vivendi, set up dark mode theme
(setq modus-themes-italic-constructs t
      modus-themes-toggle '(modus-vivendi modus-operandi))
(load-theme 'modus-vivendi)

;; The bell sound is horrible, give a visual cue instead
(setq visible-bell nil
	  ring-bell-function 'flash-mode-line)
(defun flash-mode-line ()
  "Temporarily invert mode line."
  (invert-face 'mode-line)
  (run-with-timer 0.1 nil #'invert-face 'mode-line))


;; How about some quality-of-life keybindings...
(global-set-key (kbd "C-c r") #'rgrep) 	; Get easy access to rgrep
(global-set-key (kbd "C-c q") #'modus-themes-toggle) ; Flip the theme to light-mode and back
(global-set-key (kbd "C-c y") #'calc) ; Quick call to the calculator
(global-set-key (kbd "C-c #") #'display-line-numbers-mode) ; Create a toggle for line numbers
(global-set-key (kbd "C-x C-b") #'ibuffer) ; Use ibuffer over the regular buffer menu


;; Package time, let's start with necessities...
;; Ace-Window makes it very easy to jump between buffers
(use-package
  ace-window
  :bind ("C-<tab>" . ace-window)
  :init (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)))

;; Aggressive-indent is self-explanatory, always indent everything
(use-package
  aggressive-indent
  :config
  (global-aggressive-indent-mode 1))

;; Avy allows a bunch of different jump commands
(use-package
  avy
  :bind (("C-c j j" . avy-goto-char-2)
		 ("C-c j l" . avy-goto-line)))

;; bm enables visual bookmarks that you can jump to
(use-package
  bm
  :bind (("C-c b b" . bm-toggle)
		 ("C-c b n" . bm-next)
		 ("C-c b p" . bm-previous)
		 ("C-c b l" . bm-show-all)
		 ("C-c b s" . bm-buffer-save))
  :init
  (setq-default bm-buffer-persistence t)
  (setq bm-highlight-style 'bm-highlight-only-fringe
		bm-restore-repository-on-load t
		bm-repository-file "~/.emacs.d/bm-repository"
		bm-cycle-all-buffers t))

;; Cape to extend emacs' completion-at-point capabilities
(use-package
  cape
  :init
  (add-to-list 'completion-at-point-functions #'cape-file)
  (add-to-list 'completion-at-point-functions #'cape-dabbrev)
  (add-to-list 'completion-at-point-functions #'cape-keyword)
  (add-to-list 'completion-at-point-functions #'cape-history)
  (add-to-list 'completion-at-point-functions #'cape-dict))

;; Corfu as a light auto-complete platform
(use-package
  corfu
  :init
  (setq corfu-auto t
		corfu-quit-no-match 'separator
		tab-always-indent 'complete
		completion-cycle-threshold 5)
  (global-corfu-mode)
  (corfu-popupinfo-mode))

;; Deadgrep (requires ripgrep) is a fast file search tool
(use-package
  deadgrep
  :commands deadgrep
  :bind ("C-c s" . deadgrep))

;; eglot is a LSP program for Emacs-lisp-mode
(use-package eglot)

;; God Mode makes it easy to enter long command strings
(use-package
  god-mode
  :bind (([escape] . god-mode-all)
		 :map god-local-mode-map
		 ("." . repeat))
  :init (setq god-mode-enable-function-key-translation nil)
  :config
  (add-hook 'god-mode-enabled-hook (lambda () (setq cursor-type 'hbar)))
  (add-hook 'god-mode-disabled-hook (lambda () (setq cursor-type 'bar))))

;; Magit for git integration because it's amazing
(use-package
  magit
  :bind ("C-c g" . magit-status)
  :init (setq smerge-command-prefix "\C-cv"))

;; Multiple-cursors is self explanatory
(use-package
  multiple-cursors
  :bind (("C-c m" . mc/edit-lines)
		 ("C->" . mc/mark-next-like-this)
		 ("C-<" . mc/mark-previous-like-this)
		 ("C-c C->" . mc/mark-all-like-this)))

;; Neotree is a sidebar file window
(use-package
  neotree
  :bind ("C-c n" . neotree-toggle)
  :config
  (setq neo-window-fixed-size t
		neo-theme 'arrow))

;; Smartparens pairs all parentheses for you and highlights them
(use-package
  smartparens
  :config (smartparens-global-mode t))

;; Vterm is a better Emacs terminal
(use-package
  vterm
  :bind (("C-c t" . vterm-other-window)
         :map vterm-mode-map
         ("C-q" . vterm-send-next-key)))

;; Vundo exposes a visual tree of all the available undo paths
(use-package
  vundo
  :commands vundo
  :bind ("C-c u" . vundo)
  :init (setq vundo-compact-display t))

;; Which-key pops up a buffer with command completions
(use-package
  which-key
  :config
  (which-key-mode)
  (which-key-setup-side-window-bottom))

;; Yasnippet lets you make little text snippets and insert them everywhere
(use-package
  yasnippet
  :init (setq yas-snippet-dirs '("~/.emacs.d/snippets/"))
  :config (yas-global-mode 1))

;; Zoom-mode automatically resizes windows to focus on the point
(use-package
  zoom
  :init
  (setq zoom-size '(0.618 . 0.618)
		zoom-ignored-major-modes '(dired-mode vundo-mode)
		zoom-ignored-buffer-name-regexps '("^*calc"))
  :config (zoom-mode 1))


;; Now, let's get some language support for writing code...
;; First, let's set up Rust support
(use-package
  rust-mode
  :mode ("\\.rs\\'")
  :hook (rust-mode . eglot-ensure)
  :config
  (setq rust-format-on-save t)
  (add-hook 'flycheck-mode-hook #'flycheck-rust-setup)
  (cargo-minor-mode))

;; Setting up Python support
(use-package
  python
  :mode ("\\.py\\'" . python-mode)
  :hook (python-mode . eglot-ensure))

;; Set up ein for iPython notebooks
(use-package
  ein
  :commands (ein:run ein:login)
  :init (setq ein:output-area-inlined-images t))


;; Set up Julia support
(use-package
  julia-mode
  :mode ("\\.jl\\'")
  :hook (julia-mode . eglot-ensure))

(use-package
  julia-repl
  :hook (julia-repl-mode . julia-mode))

(use-package
  eglot-jl
  :config (eglot-jl-init))


;; Set up LaTeX mode
(use-package
  tex
  :mode ("\\.tex\\'" . latex-mode)
  :hook (latex-mode . eglot-ensure)
  :config
  (setq TeX-auto-save t
		TeX-parse-self t
		TeX-save-query nil)
  (TeX-global-PDF-mode t)
  (flymake-mode))


;; Markup Language Modes
(use-package
  csv-mode
  :mode ("\\.csv\\'"))

(use-package
  json-mode
  :mode ("\\.json\\'")
  :init (setq js-indent-level 2))

(use-package
  yaml-mode
  :mode ("\\.yaml\\'"))


;; PDF/EPUB support
(use-package
  nov
  :mode ("\\.epub\\'" . nov-mode))

(use-package
  pdf-tools
  :mode ("\\.pdf\\'" . pdf-view-mode)
  :config (pdf-tools-install))


;; Finally, set up all the other applications I use Emacs for...
;; Org mode is a all-in-one life management system
(use-package
  org
  :mode ("\\.org\\'" . org-mode)
  :bind (("C-c l" . org-store-link)
		 ("C-c a" . org-agenda)
		 ("C-c c" . org-capture))
  :init
  (setq org-agenda-files '("~/org")
		org-default-notes-file "~/org/inbox.org"
		org-refile-targets '((org-agenda-files :maxlevel . 2))
		org-support-shift-select t
		org-startup-indented t
		org-agenda-skip-deadline-prewarning-if-scheduled t
		org-agenda-skip-deadline-if-done t)
  
  (setq org-agenda-time-grid
		'((daily today require-timed remove-match)
		  (800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000)
		  "......" "----------------"))

  (setq org-babel-load-languages
        '((python . t)
          (emacs-lisp . t)))
  
  (setq org-capture-templates
		'(("t" "todo" entry (file+headline "~/org/inbox.org" "Inbox")
		   "*** TODO %?\nSCHEDULED: %t")
		  ("l" "Linked todo" entry (file+headline "~/org/inbox.org" "Inbox")
		   "*** TODO %?\nSCHEDULED: %t\n%a")
		  ("s" "Scheduled todo" entry (file+headline "~/org/inbox.org" "Inbox")
		   "*** TODO %?\nSCHEDULED: %^t")
		  ("a" "Assignment" entry (file+headline "~/org/inbox.org" "Inbox")
		   "*** TODO %?\nDEADLINE: %^t SCHEDULED: %^t")
		  ("c" "Calendar Event" entry (file+headline "~/org/inbox.org" "Inbox")
		   "*** %?\n%^T")
		  ("g" "Weekly Goal" entry (file+headline "~/org/goals.org" "Weekly")
		   "*** Goal %(org-insert-time-stamp (org-read-date nil t \"+1w\"))\n - [ ] %?")
		  ("n" "Note" entry (file+olp+datetree "~/org/notes.org")
		   "* %? %^G\n%U")))
  
  (setq org-agenda-custom-commands
		'(("T" "Tasks" agenda ""
		   ((org-agenda-overriding-header "Tasks")
			(org-agenda-span 'week)
			(org-agenda-time-grid nil)
			(org-agenda-show-all-dates nil)
			(org-agenda-entry-types
			 '(:deadline :scheduled))))
		  ("W" "Upcoming Week" agenda ""
		   ((org-agenda-overriding-header "Upcoming Week")
			(org-agenda-span 'week)
			(org-agenda-start-on-weekday nil)
			))
		  ("M" "Upcoming Month" agenda ""
		   ((org-agenda-overriding-header "Upcoming Month")
			(org-agenda-span 'month)
			(org-agenda-show-all-dates nil)
			))
		  ("L" "Look Around" agenda ""
		   ((org-agenda-overriding-header "Look Around")
			(org-agenda-span 5)
			(org-agenda-start-on-weekday nil)
			(org-agenda-start-day "-2d")
			)))))


;; Ledger mode allows financial tracking in Emacs
(use-package
  ledger-mode
  :mode ("\\.dat\\'"
         "\\.ledger\\'")
  :config
  (flycheck-mode)
  (setq ledger-clear-whole-transactions t
		ledger-complete-in-steps t)
  
  (setq ledger-reports
		'(("SOTU" "%(binary) -f %(ledger-file) -V --price-db prices.db --sort \"-abs(T)\" --cleared bal Assets Liabilities")
          ("SOTF" "%(binary) -f %(ledger-file) -V --price-db prices.db --sort \"-abs(T)\" bal Assets Liabilities")
          ("SOTB" "%(binary) -f %(ledger-file) -V --price-db prices.db --sort \"-abs(T)\" bal Assets:Schwab:Checking Liabilities")
		  ("ThisMonth" "%(binary) -f %(ledger-file) -p \"this month\" --monthly --budget bal expenses")
          ("LastMonth" "%(binary) -f %(ledger-file) -p \"last month\" --monthly --budget bal expenses")
          ("NetBudget" "%(binary) -f %(ledger-file) -p \"this year\" --budget bal expenses")
          ("Expenses" "%(binary) -f %(ledger-file) -p \"this month\" bal Expenses")
          ("LastExpenses" "%(binary) -f %(ledger-file) -p \"last month\" bal Expenses")
          ("NetExpenses" "%(binary) -f %(ledger-file) -p \"this year\" bal Expenses")
		  ("Balance" "%(binary) -f %(ledger-file) -V --price-db prices.db --cleared bal")
		  ("equity" "%(binary) -f %(ledger-file) equity"))))


;; Notmuch is an email client for Emacs
(use-package notmuch
  :commands notmuch
  :bind ("C-c e" . notmuch)
  :init
  (setq user-full-name "Adithya Chari"
		user-mail-address "adithya.chari@gmail.com"
		mail-user-agent 'message-user-agent
		smtpmail-smtp-server "smtp.gmail.com"
        smtpmail-stream-type 'ssl
        smtpmail-smtp-service 465
		smtpmail-debug-info t
		message-directory "~/mail/"
		message-auto-save-directory "~/mail/drafts"
		message-default-mail-headers "Cc: \nBcc: \n"
		message-send-mail-function 'message-smtpmail-send-it
		message-kill-buffer-on-exit t
		notmuch-show-logo nil)
  
  :config
  (define-key notmuch-show-mode-map "d"
			  (lambda () (interactive)
				(if (member "trash" (notmuch-show-get-tags))
					(notmuch-show-tag (list "-trash"))
				  (notmuch-show-tag (list "+trash")))))
  
  (define-key notmuch-search-mode-map "d"
			  (lambda (&optional beg end)
				"toggle deleted tag for message"
				(interactive (notmuch-interactive-region))
				(if (member "trash" (notmuch-search-get-tags))
					(notmuch-search-tag (list "-trash") beg end)
				  (notmuch-search-tag (list "+trash") beg end))))

  (setq notmuch-saved-searches
		'((:name "inbox" :query "tag:inbox" :key "i")
		  (:name "unread" :query "tag:unread" :key "u")
		  (:name "action" :query "tag:action" :key "a")
		  (:name "receipt" :query "tag:receipt" :key "r")
		  (:name "cal" :query "tag:cal" :key "c")
		  (:name "notifications" :query "tag:notifications" :key "n")
		  (:name "drafts" :query "tag:drafts" :key "d")
		  (:name "all mail" :query "*" :key "m"))))


;; Elfeed is a newsfeed/RSS reader
(use-package
  elfeed
  :commands elfeed
  :bind ("C-c w" . elfeed)
  :config
  (setq-default elfeed-search-filter "@1-day-ago +unread -list #50 ")
  (define-key elfeed-search-mode-map "l" #'(lambda () (interactive) (elfeed-search-set-filter "+unread +list ")))
  (define-key elfeed-search-mode-map "k" #'(lambda () (interactive) (elfeed-search-set-filter nil)))
  (define-key elfeed-search-mode-map "m" #'(lambda () (interactive) (elfeed-search-tag-all 'list)))
  (define-key elfeed-search-mode-map "," #'(lambda () (interactive) (elfeed-search-untag-all 'list)))
  (define-key elfeed-search-mode-map (kbd "SPC") #'elfeed-search-untag-all-unread)
  (setq elfeed-feeds
        '(("https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml" news NYT)
          ("https://rss.nytimes.com/services/xml/rss/nyt/US.xml" news NYT)
          ("https://rss.nytimes.com/services/xml/rss/nyt/World.xml" news NYT)
          ("https://rss.nytimes.com/services/xml/rss/nyt/Politics.xml" news NYT)
          ("https://rss.nytimes.com/services/xml/rss/nyt/Economy.xml" economy NYT)
          ("https://rss.nytimes.com/services/xml/rss/nyt/Technology.xml" tech NYT)
          ("https://rss.nytimes.com/services/xml/rss/nyt/EnergyEnvironment.xml" NYT)
          ("https://rss.nytimes.com/services/xml/rss/nyt/YourMoney.xml" NYT)
          ("https://www.nytimes.com/svc/collections/v1/publish/www.nytimes.com/column/thomas-l-friedman/rss.xml" NYT ThomasFriedman)
          ("https://www.nytimes.com/svc/collections/v1/publish/www.nytimes.com/column/ezra-klein/rss.xml" NYT EzraKlein)
          ("https://www.nytimes.com/svc/collections/v1/publish/www.nytimes.com/column/paul-krugman/rss.xml" NYT PaulKrugman)
          ("https://feeds.a.dj.com/rss/RSSWorldNews.xml" news WSJ)
          ("https://feeds.a.dj.com/rss/RSSMarketsMain.xml" economy WSJ)
          ("https://feeds.a.dj.com/rss/WSJcomUSBusiness.xml" economy WSJ)
          ("https://feeds.a.dj.com/rss/RSSWSJD.xml" tech WSJ)
          ("https://feeds.a.dj.com/rss/RSSOpinion.xml" opinion WSJ)
          ("https://www.reddit.com/.rss" Reddit)
          ("https://www.reddit.com/r/emacs/.rss" emacs Reddit)
          ("https://www.reddit.com/r/news/.rss" news Reddit)
          ("https://www.reddit.com/r/finance/.rss" economy Reddit)
          ("https://www.reddit.com/r/technology/.rss" tech Reddit)
          ("https://news.ycombinator.com/rss" HN)
          ("https://astralcodexten.substack.com/feed" AstralCodexTen)
          ("https://www.notboring.co/feed" NotBoring)
          ("https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" economy MattLevine)
          ("https://sachachua.com/blog/category/emacs-news/feed/" emacs SachaChua)
          ("https://braddelong.substack.com/feed" economy BradDelong)
          ("https://cms.zerohedge.com/fullrss2.xml" ZeroHedge)
          ("https://effectiveaccelerationism.substack.com/feed" tech BeffJezos)
          ("https://chamath.substack.com/feed" tech Chamath)
          ("https://robertreich.substack.com/feed" politics RobReich)
          ("https://www.messageboxnews.com/feed" politics DanPfeiffer)
          ("https://adamtooze.substack.com/feed" economics ChartBook)
          ("https://danjones.substack.com/feed" history DanJones))))