Adithya Chari

Email: contact@adchari.dev

Sourcehut: adchari

LinkedIn: adithyachari

Résumé: Click Here

~/adchari/.emacs/

;;; -*- lexical-binding: t; -*-
;; 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)

;; 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")
(when (file-exists-p custom-file) (load custom-file))

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

;; Enable mouse mode in terminals
(unless (display-graphic-p)
  (xterm-mouse-mode 1))


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

;; Set up use-package
(require 'use-package)
(setq use-package-always-ensure t)

;; 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 a") #'calc) ; Quick call to the calculator
(global-set-key (kbd "C-c q") #'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-c w" . 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)
  (add-to-list 'aggressive-indent-excluded-modes 'c-mode)
  (add-to-list 'aggressive-indent-excluded-modes 'c++-mode))

;; 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))

(use-package
  corfu-terminal
  :init
  (unless (display-graphic-p)
    (corfu-terminal-mode 1)))

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

;; eglot is a LSP program
(use-package
  eglot
  :bind (:map eglot-mode-map
              ("C-c l a" . eglot-code-actions)
              ("C-c l r" . eglot-rename)
              ("C-c l h" . eldoc)
              ("C-c l f" . eglot-format)
              ("C-c l R" . eglot-reconnect))
  :config
  (add-to-list 'eglot-server-programs
               '(c++-mode . ("clangd" "--query-driver=/**/*"))))

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

;; Multiple-cursors is self explanatory
(use-package
  multiple-cursors
  :bind (("C-c e" . 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 f" . 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)
         :map vterm-mode-map
         ("C-q" . vterm-send-next-key))
  :init (setq vterm-shell "/bin/zsh"))

;; 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))

;; Windmove allows basic window switching
(use-package
  windmove
  :bind (("M-<up>" . windmove-up)
         ("M-<down>" . windmove-down)
         ("M-<left>" . windmove-left)
         ("M-<right>" . windmove-right)))

;; 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
  :bind (("C-c y n" . yas-new-snippet)
         ("C-c y i" . yas-insert-snippet)
         ("C-c y f" . yas-visit-snippet-file))
  :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...
(use-package
  rust-mode
  :mode ("\\.rs\\'")
  :hook (rust-mode . eglot-ensure)
  :init
  (setq rust-format-on-save t))

(use-package
  cargo
  :hook (rust-mode . cargo-minor-mode))

(use-package
  cc-mode
  :mode (("\\.h\\'" . c++-mode)
         ("\\.hpp\\'" . c++-mode)
         ("\\.cpp\\'" . c++-mode)
         ("\\.cxx\\'" . c++-mode)
         ("\\.java\\'" . java-mode))
  :hook (c++-mode . eglot-ensure)
  :hook (java-mode . eglot-java-mode)
  :init (setq c-basic-offset 4))

(use-package clang-format
  :hook (c++-mode . clang-format-on-save-mode)
  :init (setq clang-format-style "file"
              clang-format-fallback-style "google"))

(use-package
  eglot-java
  :bind (:map eglot-java-mode-map
              ("C-c l n" . eglot-java-file-new)
              ("C-c l x" . eglot-java-run-main)
              ("C-c l t" . eglot-java-run-test)
              ("C-c l b" . eglot-java-project-build-task)))

(use-package
  python
  :mode ("\\.py\\'" . python-mode)
  :hook (python-mode . eglot-ensure))

(use-package
  tex
  :ensure auctex
  :mode ("\\.tex\\'" . latex-mode)
  :config
  (setq TeX-auto-save t
        TeX-parse-self t
        TeX-save-query nil)
  (TeX-global-PDF-mode t))

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

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

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

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

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

(use-package
  protobuf-mode
  :mode ("\\.proto\\'"))


;; Finally, set up all the other applications I use Emacs for...
;; Ledger mode allows financial tracking in Emacs
(use-package
  ledger-mode
  :mode ("\\.dat\\'")
  :config
  (setq ledger-clear-whole-transactions t
        ledger-complete-in-steps t)
  (setq ledger-reports
        '(("Balance"   "%(binary) -f %(ledger-file) -S \"-U(T)\" -CV bal --price-db ~/finances/prices.db")
          ("NetWorth"  "%(binary) -f %(ledger-file) -S \"-U(T)\" -CV bal Assets Liabilities --price-db ~/finances/prices.db")
          ("Current"   "%(binary) -f %(ledger-file) -S \"-U(T)\" -C bal Checking Amex Chase")
          ("Drawdown"  "%(binary) -f %(ledger-file) -S \"-U(T)\" bal Checking Amex Chase")
          ("Portfolio" "%(binary) -f %(ledger-file) -T a -C --flat bal Assets")
          ("Budget"    "%(binary) -f %(ledger-file) --budget -p %(month) bal Expenses")  ; M-n/M-p to switch months
          ("YBudget"   "%(binary) -f %(ledger-file) --budget -p \"this year\" bal Expenses")
          ("Expenses"  "%(binary) -f %(ledger-file) -p %(month) bal Expenses")
          ("YExpenses" "%(binary) -f %(ledger-file) -p \"this year\" bal Expenses")
          ("Equity"    "%(binary) -f %(ledger-file) equity"))))


;; Notmuch is an email client for Emacs
(use-package notmuch
  :commands notmuch
  :bind ("C-c m" . 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 n" . 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))))