{"id":20068831,"url":"https://github.com/dotangad/dotemacs","last_synced_at":"2026-03-19T13:24:23.948Z","repository":{"id":111418481,"uuid":"388450319","full_name":"dotangad/dotemacs","owner":"dotangad","description":"Emacs config","archived":false,"fork":false,"pushed_at":"2021-09-10T15:56:38.000Z","size":202,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-02T11:25:48.543Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dotangad.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-22T12:13:43.000Z","updated_at":"2023-07-17T19:59:40.000Z","dependencies_parsed_at":"2023-03-13T13:40:44.456Z","dependency_job_id":null,"html_url":"https://github.com/dotangad/dotemacs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dotangad/dotemacs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotangad%2Fdotemacs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotangad%2Fdotemacs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotangad%2Fdotemacs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotangad%2Fdotemacs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dotangad","download_url":"https://codeload.github.com/dotangad/dotemacs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotangad%2Fdotemacs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30173373,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T07:56:45.623Z","status":"ssl_error","status_checked_at":"2026-03-06T07:55:55.621Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T14:09:26.260Z","updated_at":"2026-03-06T11:04:00.945Z","avatar_url":"https://github.com/dotangad.png","language":"Emacs Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+TITLE: Angad Singh's Emacs Config\n\nHeavily inspired by [[https://github.com/daviwil/emacs-from-scratch][Emacs From Scratch]].\n\n* Personal information\n#+begin_src emacs-lisp\n(setq user-full-name \"Angad Singh\"\n      user-mail-address \"mail@angad.dev\")\n#+end_src\n\n* Package management and =use-package=\n#+begin_src emacs-lisp\n(require 'package)\n\n(setq package-archives '((\"melpa\" . \"https://melpa.org/packages/\")\n                         (\"org\" . \"https://orgmode.org/elpa/\")\n                         (\"elpa\" . \"https://elpa.gnu.org/packages/\")))\n\n(package-initialize)\n(unless package-archive-contents\n (package-refresh-contents))\n\n(unless (package-installed-p 'use-package)\n   (package-install 'use-package))\n\n(require 'use-package)\n(setq use-package-always-ensure t)\n#+end_src\n\n* Improvements\n** UI Stuff\n#+begin_src emacs-lisp\n  (tool-bar-mode -1)\n  (scroll-bar-mode -1)\n  (menu-bar-mode -1)\n  (tooltip-mode -1)\n  (set-fringe-mode 1)\n  (blink-cursor-mode -1)\n  (global-hl-line-mode 1)\n  (toggle-frame-maximized)\n#+end_src\n\n** No audible bell\n#+begin_src emacs-lisp\n(setq visible-bell t)\n#+end_src\n\n** Auto pair delimeters\n#+begin_src emacs-lisp\n(electric-pair-mode 1)\n#+end_src\n\n** Make ESC quit prompts\n#+begin_src emacs-lisp\n(global-set-key (kbd \"\u003cescape\u003e\") 'keyboard-escape-quit)\n#+end_src\n\n** No backups\n#+begin_src emacs-lisp\n(setq make-backup-files nil)\n(setq auto-save-default nil)\n#+end_src\n\n** Use different custom file\n#+begin_src emacs-lisp\n(setq custom-file (expand-file-name \"custom.el\" user-emacs-directory))\n(load custom-file)\n#+end_src\n\n** Use y-or-n instead of yes-or-no\n#+begin_src emacs-lisp\n(fset 'yes-or-no-p 'y-or-n-p)\n#+end_src\n\n** Automatically update buffer on change\n#+begin_src emacs-lisp\n(global-auto-revert-mode t)\n#+end_src\n\n** Record changes in window configuration\n#+begin_src emacs-lisp\n(winner-mode 1)\n#+end_src\n\n** Line and column numbers\n#+begin_src emacs-lisp\n  (column-number-mode)\n  ;; (global-display-line-numbers-mode t)\n  (add-hook 'prog-mode-hook 'display-line-numbers-mode)\n#+end_src\n\n*** Switch them off in some modes\n#+begin_src emacs-lisp\n(dolist (mode '(org-mode-hook\n                term-mode-hook\n\t\tvterm-mode-hook\n                shell-mode-hook\n                eshell-mode-hook))\n  (add-hook mode (lambda () (display-line-numbers-mode 0))))\n#+end_src\n\n** Indentation\n#+begin_src emacs-lisp\n  (setq-default indent-tabs-mode nil)\n  (setq tab-width 2)\n#+end_src\n\n** Secrets\n#+begin_src emacs-lisp\n  (add-to-list 'load-path\n               (concat\n                (file-name-as-directory user-emacs-directory)\n                \"secrets.el\"))\n  (require 'secrets)\n#+end_src\n\n* Ivy, Counsel and Swiper\n** Ivy\n#+begin_src emacs-lisp\n  (use-package ivy\n    :diminish\n    :bind ((\"C-s\" . swiper)\n           :map ivy-minibuffer-map\n           (\"TAB\" . ivy-alt-done)\n           (\"C-l\" . ivy-alt-done)\n           (\"C-j\" . ivy-next-line)\n           (\"C-k\" . ivy-previous-line)\n           :map ivy-switch-buffer-map\n           (\"C-k\" . ivy-previous-line)\n           (\"C-l\" . ivy-done)\n           (\"C-d\" . ivy-switch-buffer-kill)\n           :map ivy-reverse-i-search-map\n           (\"C-k\" . ivy-previous-line)\n           (\"C-d\" . ivy-reverse-i-search-kill))\n    :config (ivy-mode 1)\n    :custom (ivy-count-format \"(%d/%d)\")\n            (ivy-display-style 'fancy))\n#+end_src\n\n** Counsel\n#+begin_src emacs-lisp\n(use-package counsel\n  :bind ((\"M-x\" . counsel-M-x)\n         (\"C-x b\" . counsel-ibuffer)\n         (\"C-x C-f\" . counsel-find-file)\n         :map minibuffer-local-map\n         (\"C-r\" . 'counsel-minibuffer-history)))\n#+end_src\n\n** Make ivy completion better\n=ivy-rich= shows some nice help lines next to the command/file in ivy completion\n\n#+begin_src emacs-lisp\n(use-package ivy-rich\n  :init\n  (ivy-rich-mode 1))\n#+end_src\n\n** Show the Ivy minibuffer in the middle of the screen\nThe constant width hack is from [[https://github.com/tumashu/ivy-posframe/issues/105][a github issue]].\n\n#+begin_src emacs-lisp\n  (use-package ivy-posframe\n    :init (ivy-posframe-mode 1)\n    :config\n    ;; constant width\n    (defun da/ivy-posframe-get-size ()\n      \"Set the ivy-posframe size according to the current frame.\"\n      (let ((height (or ivy-posframe-height (or ivy-height 10)))\n            (width (min (or ivy-posframe-width 200) (round (* .60 (frame-width))))))\n        (list :height height :width width :min-height height :min-width width)))\n\n    (setq ivy-posframe-size-function 'da/ivy-posframe-get-size)\n\n    :custom (ivy-posframe-display-functions-alist\n              '((swiper          . ivy-posframe-display-at-frame-center)\n                (complete-symbol . ivy-posframe-display-at-frame-center)\n                (counsel-M-x     . ivy-posframe-display-at-frame-center)\n                (t               . ivy-posframe-display))))\n#+end_src\n\n* Aesthetics\n** Nicer font\n#+begin_src emacs-lisp\n  (set-face-attribute 'default nil :font \"JetBrainsMono Nerd Font Mono\" :height 90)\n  (set-face-attribute 'fixed-pitch nil :font \"JetBrainsMono Nerd Font Mono\" :height 90)\n  (set-face-attribute 'variable-pitch nil :font \"Source Sans Pro\" :height 110 :weight 'regular)\n#+end_src\n\n** Ligatures\nLigatures make Emacs too slow, there's a significant input lag when typing after typing a ligature (not rendering one).\n#+begin_src emacs-lisp\n  ;; (load-file \"~/.emacs.d/site-lisp/ligature/ligature.el\")\n  ;; (use-package ligature\n  ;;   :load-path \"path-to-ligature-repo\"\n  ;;   :config\n  ;;   (ligature-set-ligatures\n  ;;    't\n  ;;    '(\"|||\u003e\" \"\u003c|||\" \"\u003c==\u003e\" \"\u003c!--\" \"~~\u003e\" \"***\" \"||=\" \"||\u003e\"\n  ;;      \":::\" \"::=\" \"=:=\" \"===\" \"==\u003e\" \"=!=\" \"=\u003e\u003e\" \"=\u003c\u003c\" \"=/=\" \"!==\"\n  ;;      \"!!.\" \"\u003e=\u003e\" \"\u003e\u003e=\" \"\u003e\u003e\u003e\" \"\u003e\u003e-\" \"\u003e-\u003e\" \"-\u003e\u003e\" \"--\u003e\" \"---\" \"-\u003c\u003c\"\n  ;;      \"\u003c~~\" \"\u003c~\u003e\" \"\u003c*\u003e\" \"\u003c||\" \"\u003c|\u003e\" \"\u003c$\u003e\" \"\u003c==\" \"\u003c=\u003e\" \"\u003c=\u003c\" \"\u003c-\u003e\"\n  ;;      \"\u003c--\" \"\u003c-\u003c\" \"\u003c\u003c=\" \"\u003c\u003c-\" \"\u003c\u003c\u003c\" \"\u003c+\u003e\" \"\u003c/\u003e\" \"###\" \"#_(\" \"..\u003c\"\n  ;;      \"...\" \"+++\" \"/==\" \"///\" \"_|_\" \"www\" \"\u0026\u0026\" \"^=\" \"~~\" \"~@\" \"~=\"\n  ;;      \"~\u003e\" \"~-\" \"**\" \"*\u003e\" \"*/\" \"||\" \"|}\" \"|]\" \"|=\" \"|\u003e\" \"|-\" \"{|\"\n  ;;      \"[|\" \"]#\" \"::\" \":=\" \":\u003e\" \":\u003c\" \"$\u003e\" \"==\" \"=\u003e\" \"!=\" \"!!\" \"\u003e:\"\n  ;;      \"\u003e=\" \"\u003e\u003e\" \"\u003e-\" \"-~\" \"-|\" \"-\u003e\" \"--\" \"-\u003c\" \"\u003c~\" \"\u003c*\" \"\u003c|\" \"\u003c:\"\n  ;;      \"\u003c$\" \"\u003c=\" \"\u003c\u003e\" \"\u003c-\" \"\u003c\u003c\" \"\u003c+\" \"\u003c/\" \"#{\" \"#[\" \"#:\" \"#=\" \"#!\"\n  ;;      \"##\" \"#(\" \"#?\" \"#_\" \"%%\" \".=\" \".-\" \"..\" \".?\" \"+\u003e\" \"++\" \"?:\"\n  ;;      \"?=\" \"?.\" \"??\" \";;\" \"/*\" \"/=\" \"/\u003e\" \"//\" \"__\" \"~~\" \"(*\" \"*)\"\n  ;;      \"\\\\\\\\\" \"://\" \"www\"))\n  ;;   (global-ligature-mode t))\n#+end_src\n\n** Icons\nNicer icons for Emacs, if these don't show up just run =M-x all-the-icons-install-fonts=.\n\n#+begin_src emacs-lisp\n(use-package all-the-icons)\n#+end_src\n\n** Themes\n#+begin_src emacs-lisp\n(use-package doom-themes\n  :init (load-theme 'doom-nord t))\n#+end_src\n\n** Modeline\n#+begin_src emacs-lisp\n(use-package doom-modeline\n  :init (doom-modeline-mode 1)\n\t(display-time-mode 1)\n\t(set-face-attribute 'mode-line nil :height 80)\n\t(set-face-attribute 'mode-line-inactive nil :height 80)\n  :custom ((doom-modeline-height 35)\n\t   (doom-modeline-bar-width 0)\n\t   (display-time-24hr-format t)\n\t   (display-time-default-load-average nil)))\n#+end_src\n\n** Color matching delimeters\n#+begin_src emacs-lisp\n(use-package rainbow-delimiters\n  :hook (prog-mode . rainbow-delimiters-mode))\n#+end_src\n\n* QOL packages\nPackages that improve general user experience.\n\n** =which-key=\nShow prompt in minibuffer during incomplete keybindings to help re-inforce keymap.\n#+begin_src emacs-lisp\n(use-package which-key\n  :init (which-key-mode)\n  :diminish which-key-mode\n  :config\n  (setq which-key-idle-delay 1))\n#+end_src\n\n** Better help pages\n=helpful= beautifies the help pages and adds some nice functionality to them\n\n#+begin_src emacs-lisp\n(use-package helpful\n  :custom\n  (counsel-describe-function-function #'helpful-callable)\n  (counsel-describe-variable-function #'helpful-variable)\n  :bind\n  ([remap describe-function] . counsel-describe-function)\n  ([remap describe-command] . helpful-command)\n  ([remap describe-variable] . counsel-describe-variable)\n  ([remap describe-key] . helpful-key))\n#+end_src\n\n** Get path from shell\n#+begin_src emacs-lisp\n  (use-package exec-path-from-shell\n    :config\n    (exec-path-from-shell-initialize))\n#+end_src\n\n* Keybindings\n** Evil\nA vim emulation layer for Emacs, very useful for stubborn Vim defectors.\n\n#+begin_src emacs-lisp\n(use-package evil\n  :init\n  (setq evil-want-integration t)\n  (setq evil-want-keybinding nil)\n  (setq evil-want-C-i-jump nil)\n  (setq-default evil-escape-key-sequence \"jk\")\n  :config\n  (evil-mode 1)\n  (evil-global-set-key 'motion \"j\" 'evil-next-visual-line)\n  (evil-global-set-key 'motion \"k\" 'evil-previous-visual-line)\n  (define-key evil-insert-state-map (kbd \"C-g\") 'evil-normal-state)\n  (define-key evil-insert-state-map (kbd \"C-h\") 'evil-delete-backward-char-and-join)\n  (evil-set-initial-state 'messages-buffer-mode 'normal)\n  (evil-set-initial-state 'dashboard-mode 'normal))\n#+end_src\n\n*** Make Evil behave nicely with the rest of Emacs\n=evil-collection= creates Vim-like keybindings in other Emacs modes.\n\n#+begin_src emacs-lisp\n(use-package evil-collection\n  :after evil magit\n  :config\n  (evil-collection-init))\n#+end_src\n\n*** Make =jk= leave normal mode\n#+begin_src emacs-lisp\n(use-package evil-escape\n  :init (setq-default evil-escape-key-sequence \"jk\")\n  :config (evil-escape-mode))\n#+end_src\n\n*** =surround.vim= for Evil\n#+begin_src emacs-lisp\n(use-package evil-surround\n  :ensure t\n  :config\n  (global-evil-surround-mode 1))\n#+end_src\n\n** Better keybindings with general.el\nGeneral makes it easier to create keybindings.\n\n#+begin_src emacs-lisp\n  (use-package general\n    :config\n    (general-evil-setup)\n    (general-create-definer da/leader\n      :keymaps '(normal insert visual emacs)\n      :prefix \"SPC\"\n      :global-prefix \"C-SPC\")\n    (da/leader\n      \"w\"   'save-buffer\n      \"SPC\" 'da/save-all\n      \"q\"   'delete-window\n      \"s\"   'multi-vterm-project\n      \"b\"   'counsel-ibuffer\n      \"g\"   'magit\n      \"a\"   'org-agenda\n      \"c\"   'org-capture\n      \"x\"   'counsel-M-x\n      \"t\"   'counsel-find-file))\n#+end_src\n\n* Syntax highlighting and language-specific modes\n** Markdown\n#+begin_src emacs-lisp\n(use-package markdown-mode)\n#+end_src\n\n** Fish\n#+begin_src emacs-lisp\n(use-package fish-mode)\n#+end_src\n\n** JSON\n#+begin_src emacs-lisp\n  (use-package json-mode)\n#+end_src\n\n* Misc Developer Tools\n** VTerm\n=ansi-term= doesn't play well some of the escape sequences fish uses, but vterm seems to do fine. I also set the encoding to =utf-8= so it can render some of the weirder characters.\n\n#+begin_src emacs-lisp\n  (use-package vterm\n    :ensure t\n    :config\n    (add-hook 'vterm-mode-hook\n        (lambda ()\n          (set-buffer-process-coding-system 'utf-8-unix 'utf-8-unix))))\n#+end_src\n\n*** Manage multiple vterm buffers\nThis lets me manage multiple vterm buffers, much easier than running tmux inside emacs.\n#+begin_src emacs-lisp\n  (use-package multi-vterm\n    :bind (:map vterm-mode-map\n                (\"C-c n\" . multi-vterm)\n                (\"C-c l\" . multi-vterm-next)\n                (\"C-c h\" . multi-vterm-prev)))\n#+end_src\n\n** Magit\nGit integration for Emacs\n\n#+begin_src emacs-lisp\n(use-package magit\n  :custom\n  (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1))\n#+end_src\n\n*** Use Delta for the diffs\n#+begin_src emacs-lisp\n  (use-package magit-delta\n    :hook (magit-mode . magit-delta-mode))\n#+end_src\n\n** Show git diff in gutter\n#+begin_src emacs-lisp\n  (use-package diff-hl\n    :config\n    (add-hook 'prog-mode-hook 'turn-on-diff-hl-mode)\n    (add-hook 'vc-dir-mode-hook 'turn-on-diff-hl-mode))\n#+end_src\n\n** Comment code\n#+begin_src emacs-lisp\n(use-package evil-nerd-commenter\n  :bind (\"M-/\" . evilnc-comment-or-uncomment-lines))\n#+end_src\n\n** Snippets\n#+begin_src emacs-lisp\n  (use-package yasnippet\n    :config\n    (yas-global-mode 1))\n#+end_src\n\n** Projectile\n#+begin_src emacs-lisp\n  (use-package projectile\n    :diminish projectile-mode\n    :config (projectile-mode)\n    :custom ((projectile-completion-system 'ivy))\n    :bind-keymap\n    (\"C-c p\" . projectile-command-map)\n    :init\n    ;; NOTE: Set this to the folder where you keep your Git repos!\n    (when (file-directory-p \"~/src\")\n      (setq projectile-project-search-path '(\"~/src\")))\n    (setq projectile-switch-project-action #'projectile-dired)\n    (evil-define-key 'normal projectile-mode-map (kbd \"SPC p\") 'projectile-find-file))\n\n  (use-package counsel-projectile\n    :after projectile\n    :config (counsel-projectile-mode))\n#+end_src\n\n* LSP and Completion\n** Header breadcrumbs\n#+begin_src emacs-lisp\n(defun da/lsp-mode-setup ()\n  (setq lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols))\n  (lsp-headerline-breadcrumb-mode))\n#+end_src\n\n** Setup\n#+begin_src emacs-lisp\n  (use-package lsp-mode\n    :commands (lsp lsp-deferred)\n    :hook (lsp-mode . da/lsp-mode-setup)\n    :init\n    (setq lsp-keymap-prefix \"C-l\")\n    (setq lsp-ui-doc-position 'at-point)\n    (setq read-process-output-max 1048576)\n    (setq gc-cons-threshold 100000000)\n    (setq lsp-idle-delay 0.500)\n    :config\n    (lsp-enable-which-key-integration t))\n#+end_src\n\n** UI Enhancements\n#+begin_src emacs-lisp\n(use-package lsp-ui\n  :hook (lsp-mode . lsp-ui-mode))\n#+end_src\n\n** Hierarchical view of symbols in file\n#+begin_src emacs-lisp\n(use-package lsp-treemacs\n  :after lsp)\n#+end_src\n\n** Ivy integration\n#+begin_src emacs-lisp\n(use-package lsp-ivy)\n#+end_src\n\n** Completion with company-mode\n*** Setup\n#+begin_src emacs-lisp\n(use-package company\n  :after lsp-mode\n  :hook (prog-mode . company-mode)\n  :bind (:map company-active-map\n         (\"\u003ctab\u003e\" . company-complete-selection))\n        (:map lsp-mode-map\n         (\"\u003ctab\u003e\" . company-indent-or-complete-common))\n  :custom\n  (company-minimum-prefix-length 1)\n  (company-idle-delay 0.0))\n#+end_src\n\n** Keybindings\n#+begin_src emacs-lisp\n  (evil-define-key 'normal lsp-mode-map (kbd \"SPC l\") lsp-command-map)\n  (evil-define-key 'normal lsp-mode-map (kbd \"SPC d\") 'flymake-show-diagnostics-buffer)\n#+end_src\n\n** Format on save\n#+begin_src emacs-lisp\n  (defun da/format-on-save ()\n    (when (member major-mode '(php-mode web-mode))\n      (lsp-format-buffer))\n    (when (member major-mode '(js-mode typescript-mode))\n      (lsp-eslint-apply-all-fixes)))\n\n  (add-hook 'before-save-hook 'da/format-on-save)\n#+end_src\n\n* Languages and Language Servers\n** Typescript\n#+begin_src emacs-lisp\n(use-package typescript-mode\n  :mode \"\\\\.tsx?\\\\'\"\n  :hook (typescript-mode . lsp-deferred)\n  :config\n  (setq typescript-indent-level 2))\n#+end_src\n\n** JavaScript\n*** LSP mode\n#+begin_src emacs-lisp\n  (add-hook 'js-mode-hook #'lsp-deferred)\n  (setq lsp-eslint-auto-fix-on-save t)\n  (setq js-indent-level 2)\n#+end_src\n\n*** Code-formatting with prettier\n#+begin_src emacs-lisp\n  (use-package prettier-js\n    :hook ((js-mode . prettier-js)\n           (ts-mode . prettier-js)))\n#+end_src\n\n** Web Mode\n#+begin_src emacs-lisp\n  (use-package web-mode\n    :hook (web-mode . lsp-deferred)\n    :config\n    (add-to-list 'auto-mode-alist '(\"\\\\.html?\\\\'\" . web-mode))\n    (add-to-list 'auto-mode-alist '(\"\\\\.css?\\\\'\" . web-mode))\n    (setq web-mode-engines-alist '((\"blade\"  . \"\\\\.blade\\\\.\")\n                                   (\"js\" . \"\\\\.tsx\")))\n    (setq web-mode-css-indent-offset 2)\n    (setq css-indent-offset 2)\n    (setq web-mode-markup-indent-offset 2)\n    (setq web-mode-sql-indent-offset 2)\n    (setq web-mode-code-indent-offset 2))\n#+end_src\n\n** PHP\n#+begin_src emacs-lisp\n  (use-package php-mode\n    :mode \"\\\\.php\\\\'\"\n    :hook (php-mode . lsp-deferred)\n    :hook (php-mode . (lambda () (setq-local c-basic-offset 2)))\n    :config\n    (setq c-basic-offset 2))\n#+end_src\n\n** Styled Components with mmm-mode\nFrom [[https://gist.github.com/rangeoshun/67cb17392c523579bc6cbd758b2315c1][this gist]].\n\n#+begin_src emacs-lisp\n  ; Assign typescript-mode to .tsx files\n  (add-to-list 'auto-mode-alist '(\"\\\\.tsx\\\\'\" . typescript-mode))\n\n  (use-package mmm-mode)\n  (setq mmm-global-mode t)\n  (setq mmm-submode-decoration-level 0) ;; Turn off background highlight\n\n  ;; Turn off mmm-mode in org-mode\n  (add-to-list 'mmm-never-modes 'org-mode)\n  (add-to-list 'mmm-never-modes 'org-agenda-mode)\n\n  ;; Add css mode for CSS in JS blocks\n  (mmm-add-classes\n    '((mmm-styled-mode\n      :submode css-mode\n      :front \"\\\\(styled\\\\|css\\\\)[.()\u003c\u003e[:alnum:]]?+`\"\n      :back \"`;?\")))\n\n  (mmm-add-mode-ext-class 'typescript-mode nil 'mmm-styled-mode)\n\n  ;; Add submodule for graphql blocks\n  (mmm-add-classes\n    '((mmm-graphql-mode\n      :submode graphql-mode\n      :front \"gr?a?p?h?ql`\"\n      :back \"`;?\")))\n\n  (mmm-add-mode-ext-class 'typescript-mode nil 'mmm-graphql-mode)\n\n  ;; Add JSX submodule, because typescript-mode is not that great at it\n  (mmm-add-classes\n    '((mmm-jsx-mode\n       :front \"\\\\(return\\s\\\\|n\\s\\\\|(\\n\\s*\\\\)\u003c\"\n       :front-offset -1\n       :back \"\u003e\\n?\\s*)\"\n       :back-offset 1\n       :submode web-mode)))\n\n  (mmm-add-mode-ext-class 'typescript-mode nil 'mmm-jsx-mode)\n\n  (defun mmm-reapply ()\n    (mmm-mode)\n    (mmm-mode))\n\n  (add-hook 'after-save-hook\n            (lambda ()\n              (when (string-match-p \"\\\\.tsx?\" buffer-file-name)\n                (mmm-reapply))))\n#+end_src\n\n* Utility functions\n** Save all files\n#+begin_src emacs-lisp\n  (defun da/save-all () (interactive)\n         (save-some-buffers t))\n#+end_src\n\n* Org-mode\n** Set default org directory\n#+begin_src emacs-lisp\n(setq org-directory \"~/notes/\")\n#+end_src\n\n** Utility functions\n*** org-subdir\n#+begin_src emacs-lisp\n  (defun da/org-subdir (file)\n     \"Get filename of file inside org-directory\"\n     (concat (file-name-as-directory org-directory) file))\n#+end_src\n\n*** Paste images into org-mode\n#+begin_src emacs-lisp\n  (defun da/org-insert-clipboard-image ()\n    (interactive)\n    (let ((file (format-time-string (da/org-subdir \"_img/%Y-%m-%d-%H-%M-%S.png\"))))\n    (shell-command (concat \"xclip -selection clipboard -t image/png -o \u003e \" file))\n    (insert (concat \"[[\" file \"]]\"))\n    (org-display-inline-images)))\n#+end_src\n\n*** Get level 1 headings\n#+begin_src emacs-lisp\n  (defun da/org-get-level-1-headings (filename)\n    (mapcar 'substring-no-properties\n            (org-ql-query\n              :select #'org-get-heading\n              :from filename\n              :where '(level 1))))\n#+end_src\n\n*** Re-index agenda files\n#+begin_src emacs-lisp\n  (defun da/org-refresh-agenda-files ()\n    (interactive)\n    (setq org-agenda-files (directory-files-recursively org-directory \"\\\\.org$\")))\n#+end_src\n\n** Fonts and Aesthetics\n#+begin_src emacs-lisp\n  (defun da/org-mode-aesthetics ()\n    ;; Hide the ugly stuff\n    (setq org-hide-emphasis-markers t)\n\n    ;; Neater ellipsis\n    (setq org-ellipsis \" ▾\")\n\n    (font-lock-add-keywords 'org-mode\n                            '((\"^ *\\\\([-]\\\\) \"\n                               (0 (prog1 ()\n                                    (compose-region\n                                     (match-beginning 1)\n                                     (match-end 1) \"•\"))))))\n\n    ;; Set faces for heading levels\n    (dolist (face '((org-level-1 . 1.2)\n                    (org-level-2 . 1.1)\n                    (org-level-3 . 1.1)\n                    (org-level-4 . 1.1)\n                    (org-level-5 . 1.1)\n                    (org-level-6 . 1.1)\n                    (org-level-7 . 1.1)\n                    (org-level-8 . 1.1)))\n      (set-face-attribute (car face) nil\n                          :inherit 'default\n                          :weight 'regular\n                          :height (cdr face)))\n\n    ;; Ensure that anything that should be fixed-pitch in Org files appears that way\n    (set-face-attribute 'org-block nil    :foreground nil :inherit 'fixed-pitch)\n    (set-face-attribute 'org-table nil    :inherit 'fixed-pitch)\n    (set-face-attribute 'org-formula nil  :inherit 'fixed-pitch)\n    (set-face-attribute 'org-code nil     :inherit '(shadow fixed-pitch))\n    (set-face-attribute 'org-table nil    :inherit '(shadow fixed-pitch))\n    (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))\n    (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))\n    (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))\n    (set-face-attribute 'org-checkbox nil  :inherit 'fixed-pitch)\n    (set-face-attribute 'line-number nil :inherit 'fixed-pitch)\n    (set-face-attribute 'line-number-current-line nil :inherit 'fixed-pitch)\n\n    ;; Properties and drawer\n    (set-face-attribute 'org-special-keyword nil\n                        :inherit 'fixed-pitch\n                        :height 80\n                        :foreground \"#aaaaaa\")\n    (set-face-attribute 'org-property-value nil\n                        :inherit 'fixed-pitch\n                        :height 80\n                        :foreground \"#aaaaaa\")\n    (set-face-attribute 'org-drawer nil\n                        :inherit 'fixed-pitch\n                        :height 80\n                        :foreground \"#aaaaaa\")\n    (set-face-attribute 'org-date nil\n                        :inherit 'fixed-pitch\n                        :height 80\n                        :foreground \"#aaaaaa\")\n    (set-face-attribute 'org-done nil\n                        :inherit 'default\n                        :foreground \"#666666\"\n                        :background nil))\n\n  (defun da/org-mode-hook ()\n    ;; Soft wrap lines\n    (visual-line-mode 1)\n    ;; Variable pitch fonts\n    (variable-pitch-mode 1)\n    ;; Indent sub headings\n    (setq org-indent-indentation-per-level 2)\n    (org-indent-mode 1)\n    (set-face-attribute 'org-indent nil :inherit '(org-hide fixed-pitch))\n    ;; No line numbers\n    (display-line-numbers-mode 0))\n#+end_src\n\n** Visual fill column\nDecrease window text and center window.\n\n#+begin_src emacs-lisp\n  (defun da/org-mode-visual-fill ()\n    (setq visual-fill-column-width 120\n          visual-fill-column-center-text t)\n    (visual-fill-column-mode 1))\n\n  (da/org-mode-visual-fill)\n\n  (use-package visual-fill-column\n    :hook (org-mode . da/org-mode-visual-fill))\n#+end_src\n\n** Bullets\n#+begin_src emacs-lisp\n  (use-package org-bullets\n    :after org\n    :hook (org-mode . org-bullets-mode)\n    :custom\n    (org-bullets-bullet-list '(\"●\" \"●\" \"●\" \"●\" \"●\" \"●\" \"●\")))\n#+end_src\n\n** Keybindings\n*** Evil Keybindings\n#+begin_src emacs-lisp\n(use-package evil-org\n  :ensure t\n  :after org\n  :hook (org-mode . (lambda () evil-org-mode))\n  :config\n  (require 'evil-org-agenda)\n  (evil-org-agenda-set-keys))\n#+end_src\n*** Show and hide images\n#+begin_src emacs-lisp\n  (general-define-key\n    \"C-c i\" 'org-toggle-inline-images)\n#+end_src\n\n** Monthly/Weekly/Daily files\n*** Define file formats\n#+begin_src emacs-lisp\n  (defun da/monthly-file ()\n    (format-time-string (concat (file-name-as-directory org-directory) \"monthly/%Y-M%m %B.org\")))\n\n  (defun da/weekly-file ()\n    (format-time-string (concat (file-name-as-directory org-directory) \"weekly/%Y-W%W.org\")))\n#+end_src\n\n*** Functions to open files\n#+begin_src emacs-lisp\n  (defun da/open-weekly-file ()\n    (interactive)\n    (find-file (da/weekly-file)))\n\n  (defun da/open-monthly-file ()\n    (interactive)\n    (find-file (da/monthly-file)))\n\n  (defun da/open-weekly-file-today ()\n    (interactive)\n    (find-file (da/weekly-file))\n    (org-overview)\n    (goto-char (point-min))\n    (re-search-forward (format-time-string \"* %a\")))\n#+end_src\n\n*** Keybindings\n#+begin_src emacs-lisp\n  (general-nmap \"SPC n w\" 'da/open-weekly-file)\n  (general-nmap \"SPC n t\" 'da/open-weekly-file-today)\n  (general-nmap \"SPC n n\" 'da/open-weekly-file-today)\n  (general-nmap \"SPC n m\" 'da/open-monthly-file)\n#+end_src\n\n** Agenda\n#+begin_src emacs-lisp\n  (setq org-agenda-files (directory-files-recursively org-directory \"\\\\.org$\"))\n  (setq org-agenda-start-with-log-mode t)\n  (setq org-log-done 'time)\n  (setq org-log-into-drawer t)\n#+end_src\n\n** Capture\nThe [[https://orgmode.org/manual/Template-expansion.html#Template-expansion][Template Expansion page]] in the org-mode documentation is particularly helpful when writing org-capture templates. They seem terse and intricate at first, but once I skimmed through the page I was able to write my first template with little difficulty.\n\n#+begin_src emacs-lisp\n  (setq org-default-notes-file (concat (file-name-as-directory org-directory) \"capture.org\"))\n  (setq org-capture-templates\n    '((\"l\"                          ; hotkey\n       \"Link\"                       ; description\n       entry                        ; capture type\n       (file \"~/notes/links.org\")   ; target\n       \"* [[%^{Link}][%^{Description}]]\\n%U\\n:PROPERTIES:\\n:Tags: %^g\\n:END:\\n\" ; template\n       )\n\n      (\"b\" \"Books\")\n\n      (\"bu\"\n       \"Book (from URL)\"\n       entry\n       (file (lambda () (da/org-subdir \"books/reading-list.org\")))\n       \"%(let* ((url (substring-no-properties (read-string \\\"URL: \\\")))\n                    (details (org-books-get-details url)))\n               (when details (apply #'org-books-format 1 details)))\"\n       :immediate-finish t)\n\n      (\"bk\"\n       \"Book (from clipboard)\"\n       entry\n       (file (lambda () (da/org-subdir \"books/reading-list.org\")))\n       \"%(let* ((url (substring-no-properties (current-kill 0)))\n                    (details (org-books-get-details url)))\n               (when details (apply #'org-books-format 1 details)))\"\n       :immediate-finish t)\n\n      (\"bl\" \"Book log\"\n       entry\n       (function org-books-visit-book-log)\n       \"* %U - %?\")\n\n      (\"c\"\n       \"College Inbox\"\n       entry\n       (file+headline (lambda () (da/org-subdir \"college-apps/college-apps.org\")) \"Inbox\")\n       \"* %?\\n%T\")\n\n      (\"i\" \"Inbox (Weekly File)\")\n      (\"it\"\n       \"Todo\"\n       entry\n       (file+headline (lambda () (da/weekly-file)) \"Inbox\")\n       \"\\n\\n* TODO %?\\n%U\\n\\n\")\n\n      (\"in\"\n       \"Reminder\"\n       entry\n       (file+headline (lambda () (da/weekly-file)) \"Inbox\")\n       \"\\n\\n* %?\\n%T\\n\\n\")\n\n      (\"ie\"\n       \"Event\"\n       entry\n       (file+headline (lambda () (da/weekly-file)) \"Inbox\")\n       \"\\n\\n* EVENT %?\\n%T\\n\\n\")\n\n      (\"n\"\n       \"Note (today's heading in weekly file)\"\n       entry\n       (function da/open-weekly-file-today)\n       \"\\n\\n* %?\\n%T\\n\\n\")\n\n      (\"f\"\n       \"For Later\"\n       entry\n       (file (lambda () (da/org-subdir \"for-later.org\")))\n       \"* %?\\n%U\\n:PROPERTIES:\\n:Tags: %^g\\n:END:\\n\")\n\n      (\"s\"\n       \"Study Log\"\n       entry\n       (file+datetree\n        (lambda () (da/org-subdir \"Academics/Study Log.org\")))\n       \"* %?\\n%U\\n\\n\")))\n#+end_src\n\n** Load org-babel languages\n#+begin_src emacs-lisp\n(org-babel-do-load-languages\n   'org-babel-load-languages\n   '((shell . t)\n     (ruby . t)\n     (emacs-lisp . t)\n     ))\n#+end_src\n\n** Install latest org-mode\n#+begin_src emacs-lisp\n  (use-package org\n    :hook (org-mode . da/org-mode-hook)\n    :config\n    (da/org-mode-aesthetics)\n    (setq org-todo-keywords\n          '((sequence \"READING\" \"EVENT\" \"TODO\" \"DOING\" \"|\" \"DONE\" \"CANCELLED\")))\n    (setq org-agenda-span 'day)\n    (add-to-list 'org-modules 'org-habit)\n    ;; Templates\n    (require 'org-tempo))\n#+end_src\n\n** Better search\n#+begin_src emacs-lisp\n  (use-package deft\n    :config\n    (setq deft-extensions '(\"txt\" \"tex\" \"org\"))\n    (setq deft-directory \"~/notes\")\n    (setq deft-recursive t)\n    (general-nmap \"SPC n s\" 'deft)\n    ;; Start in insert mode for deft buffers\n    (add-to-list 'evil-insert-state-modes 'deft-mode))\n#+end_src\n\n** LaTeX preview\n=C-c C-x C-l= over a LaTeX block to toggle preview.\n#+begin_src emacs-lisp\n(setq org-format-latex-options (plist-put org-format-latex-options :scale 1.3))\n#+end_src\n\n** Pomodoro\n#+begin_src emacs-lisp\n  (use-package org-pomodoro\n    :bind (:map org-mode-map\n                (\"C-c C-x C-p\" . org-pomodoro))\n    :config\n    (setq org-pomodoro-manual-break t)\n    (setq org-pomodoro-keep-killed-pomodoro-time t)\n    (setq org-pomodoro-length 35)\n    (setq org-pomodoro-play-sounds t)\n    (setq org-pomodoro-short-break-sound\n          (concat\n           (file-name-as-directory user-emacs-directory)\n           \"org-pomodoro.wav\"))\n    (setq org-pomodoro-long-break-sound\n          (concat\n           (file-name-as-directory user-emacs-directory)\n           \"org-pomodoro.wav\"))\n    (setq org-pomodoro-overtime-break-sound\n          (concat\n           (file-name-as-directory user-emacs-directory)\n           \"org-pomodoro.wav\"))\n    (setq org-pomodoro-finished-sound nil))\n#+end_src\n\n** org-ql\n#+begin_src emacs-lisp\n  (use-package org-ql)\n#+end_src\n\n** org-books: Track reading\n#+begin_src emacs-lisp\n  (use-package org-books\n    :config\n    (setq org-books-file (da/org-subdir \"books/reading-list.org\")))\n#+end_src\n\n** org-gcal\n#+begin_src emacs-lisp\n  ;; (setq package-check-signature nil)\n\n  ;; (use-package org-gcal\n  ;;   :ensure t\n  ;;   :config\n  ;;   (setq org-gcal-file-alist '((\"angadsingh567890@gmail.com\" . \"~/notes/gcal.org\"))))\n\n  ;; (add-hook 'org-agenda-mode-hook (lambda () (org-gcal-sync)))\n  ;; (add-hook 'org-capture-after-finalize-hook (lambda () (org-gcal-sync)))\n#+end_src\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotangad%2Fdotemacs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdotangad%2Fdotemacs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotangad%2Fdotemacs/lists"}