https://github.com/dotangad/dotemacs
Emacs config
https://github.com/dotangad/dotemacs
Last synced: 4 months ago
JSON representation
Emacs config
- Host: GitHub
- URL: https://github.com/dotangad/dotemacs
- Owner: dotangad
- Created: 2021-07-22T12:13:43.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2021-09-10T15:56:38.000Z (almost 5 years ago)
- Last Synced: 2025-03-02T11:25:48.543Z (over 1 year ago)
- Language: Emacs Lisp
- Size: 197 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.org
Awesome Lists containing this project
README
#+TITLE: Angad Singh's Emacs Config
Heavily inspired by [[https://github.com/daviwil/emacs-from-scratch][Emacs From Scratch]].
* Personal information
#+begin_src emacs-lisp
(setq user-full-name "Angad Singh"
user-mail-address "mail@angad.dev")
#+end_src
* Package management and =use-package=
#+begin_src emacs-lisp
(require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
("elpa" . "https://elpa.gnu.org/packages/")))
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package)
(setq use-package-always-ensure t)
#+end_src
* Improvements
** UI Stuff
#+begin_src emacs-lisp
(tool-bar-mode -1)
(scroll-bar-mode -1)
(menu-bar-mode -1)
(tooltip-mode -1)
(set-fringe-mode 1)
(blink-cursor-mode -1)
(global-hl-line-mode 1)
(toggle-frame-maximized)
#+end_src
** No audible bell
#+begin_src emacs-lisp
(setq visible-bell t)
#+end_src
** Auto pair delimeters
#+begin_src emacs-lisp
(electric-pair-mode 1)
#+end_src
** Make ESC quit prompts
#+begin_src emacs-lisp
(global-set-key (kbd "") 'keyboard-escape-quit)
#+end_src
** No backups
#+begin_src emacs-lisp
(setq make-backup-files nil)
(setq auto-save-default nil)
#+end_src
** Use different custom file
#+begin_src emacs-lisp
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(load custom-file)
#+end_src
** Use y-or-n instead of yes-or-no
#+begin_src emacs-lisp
(fset 'yes-or-no-p 'y-or-n-p)
#+end_src
** Automatically update buffer on change
#+begin_src emacs-lisp
(global-auto-revert-mode t)
#+end_src
** Record changes in window configuration
#+begin_src emacs-lisp
(winner-mode 1)
#+end_src
** Line and column numbers
#+begin_src emacs-lisp
(column-number-mode)
;; (global-display-line-numbers-mode t)
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
#+end_src
*** Switch them off in some modes
#+begin_src emacs-lisp
(dolist (mode '(org-mode-hook
term-mode-hook
vterm-mode-hook
shell-mode-hook
eshell-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
#+end_src
** Indentation
#+begin_src emacs-lisp
(setq-default indent-tabs-mode nil)
(setq tab-width 2)
#+end_src
** Secrets
#+begin_src emacs-lisp
(add-to-list 'load-path
(concat
(file-name-as-directory user-emacs-directory)
"secrets.el"))
(require 'secrets)
#+end_src
* Ivy, Counsel and Swiper
** Ivy
#+begin_src emacs-lisp
(use-package ivy
:diminish
:bind (("C-s" . swiper)
:map ivy-minibuffer-map
("TAB" . ivy-alt-done)
("C-l" . ivy-alt-done)
("C-j" . ivy-next-line)
("C-k" . ivy-previous-line)
:map ivy-switch-buffer-map
("C-k" . ivy-previous-line)
("C-l" . ivy-done)
("C-d" . ivy-switch-buffer-kill)
:map ivy-reverse-i-search-map
("C-k" . ivy-previous-line)
("C-d" . ivy-reverse-i-search-kill))
:config (ivy-mode 1)
:custom (ivy-count-format "(%d/%d)")
(ivy-display-style 'fancy))
#+end_src
** Counsel
#+begin_src emacs-lisp
(use-package counsel
:bind (("M-x" . counsel-M-x)
("C-x b" . counsel-ibuffer)
("C-x C-f" . counsel-find-file)
:map minibuffer-local-map
("C-r" . 'counsel-minibuffer-history)))
#+end_src
** Make ivy completion better
=ivy-rich= shows some nice help lines next to the command/file in ivy completion
#+begin_src emacs-lisp
(use-package ivy-rich
:init
(ivy-rich-mode 1))
#+end_src
** Show the Ivy minibuffer in the middle of the screen
The constant width hack is from [[https://github.com/tumashu/ivy-posframe/issues/105][a github issue]].
#+begin_src emacs-lisp
(use-package ivy-posframe
:init (ivy-posframe-mode 1)
:config
;; constant width
(defun da/ivy-posframe-get-size ()
"Set the ivy-posframe size according to the current frame."
(let ((height (or ivy-posframe-height (or ivy-height 10)))
(width (min (or ivy-posframe-width 200) (round (* .60 (frame-width))))))
(list :height height :width width :min-height height :min-width width)))
(setq ivy-posframe-size-function 'da/ivy-posframe-get-size)
:custom (ivy-posframe-display-functions-alist
'((swiper . ivy-posframe-display-at-frame-center)
(complete-symbol . ivy-posframe-display-at-frame-center)
(counsel-M-x . ivy-posframe-display-at-frame-center)
(t . ivy-posframe-display))))
#+end_src
* Aesthetics
** Nicer font
#+begin_src emacs-lisp
(set-face-attribute 'default nil :font "JetBrainsMono Nerd Font Mono" :height 90)
(set-face-attribute 'fixed-pitch nil :font "JetBrainsMono Nerd Font Mono" :height 90)
(set-face-attribute 'variable-pitch nil :font "Source Sans Pro" :height 110 :weight 'regular)
#+end_src
** Ligatures
Ligatures make Emacs too slow, there's a significant input lag when typing after typing a ligature (not rendering one).
#+begin_src emacs-lisp
;; (load-file "~/.emacs.d/site-lisp/ligature/ligature.el")
;; (use-package ligature
;; :load-path "path-to-ligature-repo"
;; :config
;; (ligature-set-ligatures
;; 't
;; '("|||>" "<|||" "<==>" "" "---" "-<<"
;; "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->"
;; "<--" "<-<" "<<=" "<<-" "<<<" "<+>" ">" "###" "#_(" "..<"
;; "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~="
;; "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|"
;; "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:"
;; ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:"
;; "<$" "<=" "<>" "<-" "<<" "<+" "" "#{" "#[" "#:" "#=" "#!"
;; "##" "#(" "#?" "#_" "%%" ".=" ".-" ".." ".?" "+>" "++" "?:"
;; "?=" "?." "??" ";;" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)"
;; "\\\\" "://" "www"))
;; (global-ligature-mode t))
#+end_src
** Icons
Nicer icons for Emacs, if these don't show up just run =M-x all-the-icons-install-fonts=.
#+begin_src emacs-lisp
(use-package all-the-icons)
#+end_src
** Themes
#+begin_src emacs-lisp
(use-package doom-themes
:init (load-theme 'doom-nord t))
#+end_src
** Modeline
#+begin_src emacs-lisp
(use-package doom-modeline
:init (doom-modeline-mode 1)
(display-time-mode 1)
(set-face-attribute 'mode-line nil :height 80)
(set-face-attribute 'mode-line-inactive nil :height 80)
:custom ((doom-modeline-height 35)
(doom-modeline-bar-width 0)
(display-time-24hr-format t)
(display-time-default-load-average nil)))
#+end_src
** Color matching delimeters
#+begin_src emacs-lisp
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
#+end_src
* QOL packages
Packages that improve general user experience.
** =which-key=
Show prompt in minibuffer during incomplete keybindings to help re-inforce keymap.
#+begin_src emacs-lisp
(use-package which-key
:init (which-key-mode)
:diminish which-key-mode
:config
(setq which-key-idle-delay 1))
#+end_src
** Better help pages
=helpful= beautifies the help pages and adds some nice functionality to them
#+begin_src emacs-lisp
(use-package helpful
:custom
(counsel-describe-function-function #'helpful-callable)
(counsel-describe-variable-function #'helpful-variable)
:bind
([remap describe-function] . counsel-describe-function)
([remap describe-command] . helpful-command)
([remap describe-variable] . counsel-describe-variable)
([remap describe-key] . helpful-key))
#+end_src
** Get path from shell
#+begin_src emacs-lisp
(use-package exec-path-from-shell
:config
(exec-path-from-shell-initialize))
#+end_src
* Keybindings
** Evil
A vim emulation layer for Emacs, very useful for stubborn Vim defectors.
#+begin_src emacs-lisp
(use-package evil
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
(setq evil-want-C-i-jump nil)
(setq-default evil-escape-key-sequence "jk")
:config
(evil-mode 1)
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
(define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
(define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join)
(evil-set-initial-state 'messages-buffer-mode 'normal)
(evil-set-initial-state 'dashboard-mode 'normal))
#+end_src
*** Make Evil behave nicely with the rest of Emacs
=evil-collection= creates Vim-like keybindings in other Emacs modes.
#+begin_src emacs-lisp
(use-package evil-collection
:after evil magit
:config
(evil-collection-init))
#+end_src
*** Make =jk= leave normal mode
#+begin_src emacs-lisp
(use-package evil-escape
:init (setq-default evil-escape-key-sequence "jk")
:config (evil-escape-mode))
#+end_src
*** =surround.vim= for Evil
#+begin_src emacs-lisp
(use-package evil-surround
:ensure t
:config
(global-evil-surround-mode 1))
#+end_src
** Better keybindings with general.el
General makes it easier to create keybindings.
#+begin_src emacs-lisp
(use-package general
:config
(general-evil-setup)
(general-create-definer da/leader
:keymaps '(normal insert visual emacs)
:prefix "SPC"
:global-prefix "C-SPC")
(da/leader
"w" 'save-buffer
"SPC" 'da/save-all
"q" 'delete-window
"s" 'multi-vterm-project
"b" 'counsel-ibuffer
"g" 'magit
"a" 'org-agenda
"c" 'org-capture
"x" 'counsel-M-x
"t" 'counsel-find-file))
#+end_src
* Syntax highlighting and language-specific modes
** Markdown
#+begin_src emacs-lisp
(use-package markdown-mode)
#+end_src
** Fish
#+begin_src emacs-lisp
(use-package fish-mode)
#+end_src
** JSON
#+begin_src emacs-lisp
(use-package json-mode)
#+end_src
* Misc Developer Tools
** VTerm
=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.
#+begin_src emacs-lisp
(use-package vterm
:ensure t
:config
(add-hook 'vterm-mode-hook
(lambda ()
(set-buffer-process-coding-system 'utf-8-unix 'utf-8-unix))))
#+end_src
*** Manage multiple vterm buffers
This lets me manage multiple vterm buffers, much easier than running tmux inside emacs.
#+begin_src emacs-lisp
(use-package multi-vterm
:bind (:map vterm-mode-map
("C-c n" . multi-vterm)
("C-c l" . multi-vterm-next)
("C-c h" . multi-vterm-prev)))
#+end_src
** Magit
Git integration for Emacs
#+begin_src emacs-lisp
(use-package magit
:custom
(magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1))
#+end_src
*** Use Delta for the diffs
#+begin_src emacs-lisp
(use-package magit-delta
:hook (magit-mode . magit-delta-mode))
#+end_src
** Show git diff in gutter
#+begin_src emacs-lisp
(use-package diff-hl
:config
(add-hook 'prog-mode-hook 'turn-on-diff-hl-mode)
(add-hook 'vc-dir-mode-hook 'turn-on-diff-hl-mode))
#+end_src
** Comment code
#+begin_src emacs-lisp
(use-package evil-nerd-commenter
:bind ("M-/" . evilnc-comment-or-uncomment-lines))
#+end_src
** Snippets
#+begin_src emacs-lisp
(use-package yasnippet
:config
(yas-global-mode 1))
#+end_src
** Projectile
#+begin_src emacs-lisp
(use-package projectile
:diminish projectile-mode
:config (projectile-mode)
:custom ((projectile-completion-system 'ivy))
:bind-keymap
("C-c p" . projectile-command-map)
:init
;; NOTE: Set this to the folder where you keep your Git repos!
(when (file-directory-p "~/src")
(setq projectile-project-search-path '("~/src")))
(setq projectile-switch-project-action #'projectile-dired)
(evil-define-key 'normal projectile-mode-map (kbd "SPC p") 'projectile-find-file))
(use-package counsel-projectile
:after projectile
:config (counsel-projectile-mode))
#+end_src
* LSP and Completion
** Header breadcrumbs
#+begin_src emacs-lisp
(defun da/lsp-mode-setup ()
(setq lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols))
(lsp-headerline-breadcrumb-mode))
#+end_src
** Setup
#+begin_src emacs-lisp
(use-package lsp-mode
:commands (lsp lsp-deferred)
:hook (lsp-mode . da/lsp-mode-setup)
:init
(setq lsp-keymap-prefix "C-l")
(setq lsp-ui-doc-position 'at-point)
(setq read-process-output-max 1048576)
(setq gc-cons-threshold 100000000)
(setq lsp-idle-delay 0.500)
:config
(lsp-enable-which-key-integration t))
#+end_src
** UI Enhancements
#+begin_src emacs-lisp
(use-package lsp-ui
:hook (lsp-mode . lsp-ui-mode))
#+end_src
** Hierarchical view of symbols in file
#+begin_src emacs-lisp
(use-package lsp-treemacs
:after lsp)
#+end_src
** Ivy integration
#+begin_src emacs-lisp
(use-package lsp-ivy)
#+end_src
** Completion with company-mode
*** Setup
#+begin_src emacs-lisp
(use-package company
:after lsp-mode
:hook (prog-mode . company-mode)
:bind (:map company-active-map
("" . company-complete-selection))
(:map lsp-mode-map
("" . company-indent-or-complete-common))
:custom
(company-minimum-prefix-length 1)
(company-idle-delay 0.0))
#+end_src
** Keybindings
#+begin_src emacs-lisp
(evil-define-key 'normal lsp-mode-map (kbd "SPC l") lsp-command-map)
(evil-define-key 'normal lsp-mode-map (kbd "SPC d") 'flymake-show-diagnostics-buffer)
#+end_src
** Format on save
#+begin_src emacs-lisp
(defun da/format-on-save ()
(when (member major-mode '(php-mode web-mode))
(lsp-format-buffer))
(when (member major-mode '(js-mode typescript-mode))
(lsp-eslint-apply-all-fixes)))
(add-hook 'before-save-hook 'da/format-on-save)
#+end_src
* Languages and Language Servers
** Typescript
#+begin_src emacs-lisp
(use-package typescript-mode
:mode "\\.tsx?\\'"
:hook (typescript-mode . lsp-deferred)
:config
(setq typescript-indent-level 2))
#+end_src
** JavaScript
*** LSP mode
#+begin_src emacs-lisp
(add-hook 'js-mode-hook #'lsp-deferred)
(setq lsp-eslint-auto-fix-on-save t)
(setq js-indent-level 2)
#+end_src
*** Code-formatting with prettier
#+begin_src emacs-lisp
(use-package prettier-js
:hook ((js-mode . prettier-js)
(ts-mode . prettier-js)))
#+end_src
** Web Mode
#+begin_src emacs-lisp
(use-package web-mode
:hook (web-mode . lsp-deferred)
:config
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.css?\\'" . web-mode))
(setq web-mode-engines-alist '(("blade" . "\\.blade\\.")
("js" . "\\.tsx")))
(setq web-mode-css-indent-offset 2)
(setq css-indent-offset 2)
(setq web-mode-markup-indent-offset 2)
(setq web-mode-sql-indent-offset 2)
(setq web-mode-code-indent-offset 2))
#+end_src
** PHP
#+begin_src emacs-lisp
(use-package php-mode
:mode "\\.php\\'"
:hook (php-mode . lsp-deferred)
:hook (php-mode . (lambda () (setq-local c-basic-offset 2)))
:config
(setq c-basic-offset 2))
#+end_src
** Styled Components with mmm-mode
From [[https://gist.github.com/rangeoshun/67cb17392c523579bc6cbd758b2315c1][this gist]].
#+begin_src emacs-lisp
; Assign typescript-mode to .tsx files
(add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode))
(use-package mmm-mode)
(setq mmm-global-mode t)
(setq mmm-submode-decoration-level 0) ;; Turn off background highlight
;; Turn off mmm-mode in org-mode
(add-to-list 'mmm-never-modes 'org-mode)
(add-to-list 'mmm-never-modes 'org-agenda-mode)
;; Add css mode for CSS in JS blocks
(mmm-add-classes
'((mmm-styled-mode
:submode css-mode
:front "\\(styled\\|css\\)[.()<>[:alnum:]]?+`"
:back "`;?")))
(mmm-add-mode-ext-class 'typescript-mode nil 'mmm-styled-mode)
;; Add submodule for graphql blocks
(mmm-add-classes
'((mmm-graphql-mode
:submode graphql-mode
:front "gr?a?p?h?ql`"
:back "`;?")))
(mmm-add-mode-ext-class 'typescript-mode nil 'mmm-graphql-mode)
;; Add JSX submodule, because typescript-mode is not that great at it
(mmm-add-classes
'((mmm-jsx-mode
:front "\\(return\s\\|n\s\\|(\n\s*\\)<"
:front-offset -1
:back ">\n?\s*)"
:back-offset 1
:submode web-mode)))
(mmm-add-mode-ext-class 'typescript-mode nil 'mmm-jsx-mode)
(defun mmm-reapply ()
(mmm-mode)
(mmm-mode))
(add-hook 'after-save-hook
(lambda ()
(when (string-match-p "\\.tsx?" buffer-file-name)
(mmm-reapply))))
#+end_src
* Utility functions
** Save all files
#+begin_src emacs-lisp
(defun da/save-all () (interactive)
(save-some-buffers t))
#+end_src
* Org-mode
** Set default org directory
#+begin_src emacs-lisp
(setq org-directory "~/notes/")
#+end_src
** Utility functions
*** org-subdir
#+begin_src emacs-lisp
(defun da/org-subdir (file)
"Get filename of file inside org-directory"
(concat (file-name-as-directory org-directory) file))
#+end_src
*** Paste images into org-mode
#+begin_src emacs-lisp
(defun da/org-insert-clipboard-image ()
(interactive)
(let ((file (format-time-string (da/org-subdir "_img/%Y-%m-%d-%H-%M-%S.png"))))
(shell-command (concat "xclip -selection clipboard -t image/png -o > " file))
(insert (concat "[[" file "]]"))
(org-display-inline-images)))
#+end_src
*** Get level 1 headings
#+begin_src emacs-lisp
(defun da/org-get-level-1-headings (filename)
(mapcar 'substring-no-properties
(org-ql-query
:select #'org-get-heading
:from filename
:where '(level 1))))
#+end_src
*** Re-index agenda files
#+begin_src emacs-lisp
(defun da/org-refresh-agenda-files ()
(interactive)
(setq org-agenda-files (directory-files-recursively org-directory "\\.org$")))
#+end_src
** Fonts and Aesthetics
#+begin_src emacs-lisp
(defun da/org-mode-aesthetics ()
;; Hide the ugly stuff
(setq org-hide-emphasis-markers t)
;; Neater ellipsis
(setq org-ellipsis " ▾")
(font-lock-add-keywords 'org-mode
'(("^ *\\([-]\\) "
(0 (prog1 ()
(compose-region
(match-beginning 1)
(match-end 1) "•"))))))
;; Set faces for heading levels
(dolist (face '((org-level-1 . 1.2)
(org-level-2 . 1.1)
(org-level-3 . 1.1)
(org-level-4 . 1.1)
(org-level-5 . 1.1)
(org-level-6 . 1.1)
(org-level-7 . 1.1)
(org-level-8 . 1.1)))
(set-face-attribute (car face) nil
:inherit 'default
:weight 'regular
:height (cdr face)))
;; Ensure that anything that should be fixed-pitch in Org files appears that way
(set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
(set-face-attribute 'org-table nil :inherit 'fixed-pitch)
(set-face-attribute 'org-formula nil :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)
(set-face-attribute 'line-number nil :inherit 'fixed-pitch)
(set-face-attribute 'line-number-current-line nil :inherit 'fixed-pitch)
;; Properties and drawer
(set-face-attribute 'org-special-keyword nil
:inherit 'fixed-pitch
:height 80
:foreground "#aaaaaa")
(set-face-attribute 'org-property-value nil
:inherit 'fixed-pitch
:height 80
:foreground "#aaaaaa")
(set-face-attribute 'org-drawer nil
:inherit 'fixed-pitch
:height 80
:foreground "#aaaaaa")
(set-face-attribute 'org-date nil
:inherit 'fixed-pitch
:height 80
:foreground "#aaaaaa")
(set-face-attribute 'org-done nil
:inherit 'default
:foreground "#666666"
:background nil))
(defun da/org-mode-hook ()
;; Soft wrap lines
(visual-line-mode 1)
;; Variable pitch fonts
(variable-pitch-mode 1)
;; Indent sub headings
(setq org-indent-indentation-per-level 2)
(org-indent-mode 1)
(set-face-attribute 'org-indent nil :inherit '(org-hide fixed-pitch))
;; No line numbers
(display-line-numbers-mode 0))
#+end_src
** Visual fill column
Decrease window text and center window.
#+begin_src emacs-lisp
(defun da/org-mode-visual-fill ()
(setq visual-fill-column-width 120
visual-fill-column-center-text t)
(visual-fill-column-mode 1))
(da/org-mode-visual-fill)
(use-package visual-fill-column
:hook (org-mode . da/org-mode-visual-fill))
#+end_src
** Bullets
#+begin_src emacs-lisp
(use-package org-bullets
:after org
:hook (org-mode . org-bullets-mode)
:custom
(org-bullets-bullet-list '("●" "●" "●" "●" "●" "●" "●")))
#+end_src
** Keybindings
*** Evil Keybindings
#+begin_src emacs-lisp
(use-package evil-org
:ensure t
:after org
:hook (org-mode . (lambda () evil-org-mode))
:config
(require 'evil-org-agenda)
(evil-org-agenda-set-keys))
#+end_src
*** Show and hide images
#+begin_src emacs-lisp
(general-define-key
"C-c i" 'org-toggle-inline-images)
#+end_src
** Monthly/Weekly/Daily files
*** Define file formats
#+begin_src emacs-lisp
(defun da/monthly-file ()
(format-time-string (concat (file-name-as-directory org-directory) "monthly/%Y-M%m %B.org")))
(defun da/weekly-file ()
(format-time-string (concat (file-name-as-directory org-directory) "weekly/%Y-W%W.org")))
#+end_src
*** Functions to open files
#+begin_src emacs-lisp
(defun da/open-weekly-file ()
(interactive)
(find-file (da/weekly-file)))
(defun da/open-monthly-file ()
(interactive)
(find-file (da/monthly-file)))
(defun da/open-weekly-file-today ()
(interactive)
(find-file (da/weekly-file))
(org-overview)
(goto-char (point-min))
(re-search-forward (format-time-string "* %a")))
#+end_src
*** Keybindings
#+begin_src emacs-lisp
(general-nmap "SPC n w" 'da/open-weekly-file)
(general-nmap "SPC n t" 'da/open-weekly-file-today)
(general-nmap "SPC n n" 'da/open-weekly-file-today)
(general-nmap "SPC n m" 'da/open-monthly-file)
#+end_src
** Agenda
#+begin_src emacs-lisp
(setq org-agenda-files (directory-files-recursively org-directory "\\.org$"))
(setq org-agenda-start-with-log-mode t)
(setq org-log-done 'time)
(setq org-log-into-drawer t)
#+end_src
** Capture
The [[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.
#+begin_src emacs-lisp
(setq org-default-notes-file (concat (file-name-as-directory org-directory) "capture.org"))
(setq org-capture-templates
'(("l" ; hotkey
"Link" ; description
entry ; capture type
(file "~/notes/links.org") ; target
"* [[%^{Link}][%^{Description}]]\n%U\n:PROPERTIES:\n:Tags: %^g\n:END:\n" ; template
)
("b" "Books")
("bu"
"Book (from URL)"
entry
(file (lambda () (da/org-subdir "books/reading-list.org")))
"%(let* ((url (substring-no-properties (read-string \"URL: \")))
(details (org-books-get-details url)))
(when details (apply #'org-books-format 1 details)))"
:immediate-finish t)
("bk"
"Book (from clipboard)"
entry
(file (lambda () (da/org-subdir "books/reading-list.org")))
"%(let* ((url (substring-no-properties (current-kill 0)))
(details (org-books-get-details url)))
(when details (apply #'org-books-format 1 details)))"
:immediate-finish t)
("bl" "Book log"
entry
(function org-books-visit-book-log)
"* %U - %?")
("c"
"College Inbox"
entry
(file+headline (lambda () (da/org-subdir "college-apps/college-apps.org")) "Inbox")
"* %?\n%T")
("i" "Inbox (Weekly File)")
("it"
"Todo"
entry
(file+headline (lambda () (da/weekly-file)) "Inbox")
"\n\n* TODO %?\n%U\n\n")
("in"
"Reminder"
entry
(file+headline (lambda () (da/weekly-file)) "Inbox")
"\n\n* %?\n%T\n\n")
("ie"
"Event"
entry
(file+headline (lambda () (da/weekly-file)) "Inbox")
"\n\n* EVENT %?\n%T\n\n")
("n"
"Note (today's heading in weekly file)"
entry
(function da/open-weekly-file-today)
"\n\n* %?\n%T\n\n")
("f"
"For Later"
entry
(file (lambda () (da/org-subdir "for-later.org")))
"* %?\n%U\n:PROPERTIES:\n:Tags: %^g\n:END:\n")
("s"
"Study Log"
entry
(file+datetree
(lambda () (da/org-subdir "Academics/Study Log.org")))
"* %?\n%U\n\n")))
#+end_src
** Load org-babel languages
#+begin_src emacs-lisp
(org-babel-do-load-languages
'org-babel-load-languages
'((shell . t)
(ruby . t)
(emacs-lisp . t)
))
#+end_src
** Install latest org-mode
#+begin_src emacs-lisp
(use-package org
:hook (org-mode . da/org-mode-hook)
:config
(da/org-mode-aesthetics)
(setq org-todo-keywords
'((sequence "READING" "EVENT" "TODO" "DOING" "|" "DONE" "CANCELLED")))
(setq org-agenda-span 'day)
(add-to-list 'org-modules 'org-habit)
;; Templates
(require 'org-tempo))
#+end_src
** Better search
#+begin_src emacs-lisp
(use-package deft
:config
(setq deft-extensions '("txt" "tex" "org"))
(setq deft-directory "~/notes")
(setq deft-recursive t)
(general-nmap "SPC n s" 'deft)
;; Start in insert mode for deft buffers
(add-to-list 'evil-insert-state-modes 'deft-mode))
#+end_src
** LaTeX preview
=C-c C-x C-l= over a LaTeX block to toggle preview.
#+begin_src emacs-lisp
(setq org-format-latex-options (plist-put org-format-latex-options :scale 1.3))
#+end_src
** Pomodoro
#+begin_src emacs-lisp
(use-package org-pomodoro
:bind (:map org-mode-map
("C-c C-x C-p" . org-pomodoro))
:config
(setq org-pomodoro-manual-break t)
(setq org-pomodoro-keep-killed-pomodoro-time t)
(setq org-pomodoro-length 35)
(setq org-pomodoro-play-sounds t)
(setq org-pomodoro-short-break-sound
(concat
(file-name-as-directory user-emacs-directory)
"org-pomodoro.wav"))
(setq org-pomodoro-long-break-sound
(concat
(file-name-as-directory user-emacs-directory)
"org-pomodoro.wav"))
(setq org-pomodoro-overtime-break-sound
(concat
(file-name-as-directory user-emacs-directory)
"org-pomodoro.wav"))
(setq org-pomodoro-finished-sound nil))
#+end_src
** org-ql
#+begin_src emacs-lisp
(use-package org-ql)
#+end_src
** org-books: Track reading
#+begin_src emacs-lisp
(use-package org-books
:config
(setq org-books-file (da/org-subdir "books/reading-list.org")))
#+end_src
** org-gcal
#+begin_src emacs-lisp
;; (setq package-check-signature nil)
;; (use-package org-gcal
;; :ensure t
;; :config
;; (setq org-gcal-file-alist '(("angadsingh567890@gmail.com" . "~/notes/gcal.org"))))
;; (add-hook 'org-agenda-mode-hook (lambda () (org-gcal-sync)))
;; (add-hook 'org-capture-after-finalize-hook (lambda () (org-gcal-sync)))
#+end_src