Files
dot-emacs/.emacs.d/org.org
2026-01-10 08:38:40 -05:00

258 lines
9.6 KiB
Org Mode

* Org
Enable/disable certain ~org~ mode functionalities:
#+begin_src elisp
(defconst jm/cloud-root "~/Nextcloud")
(defconst jm/notes-directory (expand-file-name "org" jm/cloud-root))
(defun jm/org-mode-setup ()
(org-indent-mode)
(flyspell-mode)
(variable-pitch-mode 1)
(visual-line-mode 1)
(add-to-list 'org-link-frame-setup '(file . find-file)))
#+end_src
Setup ~org~ mode:
#+begin_src elisp
(use-package org
:hook ((org-mode . jm/org-mode-setup)
(org-agenda-mode . jm/org-roam-refresh-agenda-list))
:config
(setq jm/inbox-file (expand-file-name "inbox.org" jm/notes-directory)
org-ellipsis ""
org-pretty-entities t
org-hide-emphasis-markers t
org-src-preserve-indentation t
;; Default export configuration
org-export-with-toc nil
org-export-with-section-numbers nil
org-export-with-sub-superscripts nil
org-latex-src-block-backend 'listings
org-format-latex-options (plist-put org-format-latex-options :scale 1.3)
;; Org agenda timestamp formatting
org-display-custom-times t
org-time-stamp-custom-formats '("%m-%d-%y %a" . "%m-%d-%y %a %I:%M %p")
;; Capture templates
org-capture-templates '(("i" "Inbox" entry (file jm/inbox-file)
"* TODO %^{Task}\nSCHEDULED: %^t DEADLINE: %^t")))
(jm/leader-keys
"oa" '(org-agenda :which-key "Org agenda")
"oc" '(org-capture :which-key "Org capture")
"oi" '((lambda () (interactive) (find-file jm/inbox-file)) :which-key "Open inbox file")))
#+end_src
* Cosmetics
** Org-Modern
Org-Modern is a package that adds several features to emacs to make it look more /modern/.
#+begin_src elisp
(use-package org-modern
:after org
:hook ((org-mode . org-modern-mode)
(org-agenda-finalize . org-modern-agenda))
:config
(setq org-modern-star 'replace
org-modern-replace-stars '("" "" "" "" "" "" "")
org-modern-priority-faces
'((?A :foreground "black" :background "red")
(?B :foreground "black" :background "orange")
(?C :foreground "black" :background "yellow")
(?D :foreground "black" :background "green"))))
#+end_src
** Font Changes
Org-faces changes the font size of the headings to make them bigger in the org file. Though this code also changes the font to a variable-pitch font. To make it so that only fixed-pitch fonts are used in things like code blocks, *set-face-attribute* is used below.
#+begin_src elisp
(with-eval-after-load 'org-faces
;; Set faces for heading size levels
(dolist (face '((org-level-1 . 1.2)
(org-level-2 . 1.1)
(org-level-3 . 1.05)
(org-level-4 . 1.0)
(org-level-5 . 1.0)
(org-level-6 . 1.0)
(org-level-7 . 1.0)
(org-level-8 . 1.0)))
(set-face-attribute (car face) nil :font "Maple Mono" :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))
#+end_src
* Todo Items
** Custom States
Adds custom states to tasks such as ~IN PROGRESS~, ~CANCELLED~, etc. I've also added some changes to the color of the todo items based on the status. For example, turning the task face orange if it is /in progress/.
#+begin_src emacs-lisp
(setq org-todo-keyword-faces
'(("IN PROGRESS" . (:foreground "orange" :weight bold))
("WAITING" . (:foreground "yellow" :weight bold))))
(setq org-modern-todo-faces
'(("IN PROGRESS" . (:background "orange" :foreground "black" :weight bold))
("WAITING" . (:background "yellow" :foreground "black" :weight bold))))
(setq org-todo-keywords
'((sequence
"TODO(t)"
"IN PROGRESS(i)"
"WAITING(w)"
"|"
"DONE(d)"
"CANCELLED(c)"
"FAILED(f)")))
(setq org-clock-in-switch-to-state "IN PROGRESS")
#+end_src
** Refresh Checkboxes
Adds a hook to repeated tasks in org agenda that, when repeated, checkboxes will be reset to an unchecked state.
#+begin_src emacs-lisp
(add-hook 'org-todo-repeat-hook #'org-reset-checkbox-state-subtree)
#+end_src
** Automatic UUIDs
#+begin_src emacs-lisp
(add-hook 'org-after-todo-state-change-hook
(lambda () (when (org-get-todo-state)
(org-id-get-create))))
#+end_src
** Org Agenda
Org mode by default contains an /agenda/ system which is like a basic calendar that allows you to schedule todo items from org documents. All of the todo items from each org document are stored in a central area to allow for a formation of an /agenda/.
#+begin_src emacs-lisp
(setq org-agenda-start-with-log-mode t)
(setq org-log-done 'time)
(setq org-log-into-drawer t)
(setq org-priority-default ?D)
(setq org-priority-lowest ?D)
#+end_src
* Org Roam
Org-roam is a plain-text knowledge management system. It brings some of Roam's more powerful features into the Org-mode ecosystem such as org-file linking, etc. Below is the main config for org-roam.
#+begin_src emacs-lisp
(use-package org-roam
:init (require 'org-roam-dailies)
:custom
(org-roam-directory jm/notes-directory)
(org-roam-node-display-template "${title:60} ${file-title}")
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . jm/org-roam-find)
("C-c n d" . jm/org-roam-dailies-find)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
("C-c n o" . org-id-get-create)
("C-c n y" . org-roam-dailies-capture-yesterday)
("C-c n t" . org-roam-dailies-capture-today)
("C-c n k" . org-roam-dailies-capture-tomorrow)
("C-c n r" . jm/org-roam-refresh-agenda-list))
:config
;; Config for org-roam capture templates.
(setq jm/org-roam-templates-directory (expand-file-name "templates" org-roam-directory)
org-roam-capture-templates
`(("d" "Default" plain "%?"
:target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
:unnarrowed t)
("p" "Project" plain
(file ,(expand-file-name "project.org" jm/org-roam-templates-directory))
:target (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n")
:unnarrowed t)
("y" "12 Week Year" plain
(file ,(expand-file-name "12-week-year.org" jm/org-roam-templates-directory))
:target (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n")
:unnarrowed t)))
(setq org-roam-dailies-capture-templates
`(("d" "Default" entry "* %?"
:target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n"))
("r" "Reflection" entry
(file ,(expand-file-name "reflection.org" jm/org-roam-templates-directory))
:target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")
:unnarrowed t)
("S" "Weekly Scorecard" entry
(file ,(expand-file-name "weekly-scorecard.org" jm/org-roam-templates-directory))
:target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")
:unnarrowed t)
("s" "Daily Scorecard" entry
(file ,(expand-file-name "daily-scorecard.org" jm/org-roam-templates-directory))
:target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")
:unnarrowed t)
("t" "Todos" entry
(file ,(expand-file-name "daily.org" jm/org-roam-templates-directory))
:target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")
:unnarrowed t)))
;; Create org roam directory and templates directory if not found.
(unless (file-directory-p org-roam-directory)
(make-directory org-roam-directory))
(unless (file-directory-p jm/org-roam-templates-directory)
(make-directory jm/org-roam-templates-directory))
(org-roam-db-autosync-mode))
#+end_src
** Consult Integration
Consult Org Roam is a package that integrates searching from consult with ~org-roam~ which adds functionality such as full text searches over notes.
#+begin_src emacs-lisp
(use-package consult-org-roam
:after org-roam
:bind (("C-c n s" . consult-org-roam-search))
:init (consult-org-roam-mode 1))
#+end_src
* Other Packages
** Evil Org
By default, many of the org specific keybindings do not feel intuitive when using evil mode. ~evil-org~ is a package that attempts to fix this by rebinding many of the default org keybindings to work better with Evil mode.
#+begin_src emacs-lisp
(use-package evil-org
:after org
:hook (org-mode . (lambda () evil-org-mode))
:config
(require 'evil-org-agenda)
(evil-org-agenda-set-keys))
#+end_src
** Fix Snippets
This is required as of org 9.2 as snippets such as ~<s~ don't work. Without this fix, you are required to manually type out structures like code blocks.
#+begin_src emacs-lisp
(require 'org-tempo)
#+end_src