dotfiles/.emacs.d/org.org
2024-01-31 11:48:06 -08:00

9.3 KiB

Org is a package that allows you to create files like this one that look nice while also being able to run code. In this file, the code being run is stored in code blocks and all other text is disregarded.

Org Setup

This installs the org package and creates a setup function to enable/disable certain functionalities.

;; Setup org mode
(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))) ; Open link in current window not other window.

(use-package org
  :hook (org-mode . jm/org-mode-setup)
  :config
  (setq org-ellipsis " ▾"
        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 agenda timestamp formatting
        org-display-custom-times t
        org-time-stamp-custom-formats '("%m-%d-%y %a" . "%m-%d-%y %a %I:%M %p"))

  (jm/leader-keys
    "oa" '(org-agenda :which-key "Org agenda")))

Cosmetics

Org-Bullets

Org-bullets is a package that adds bullets to each heading instead of asterisks. It just makes org files nicer to look at.

;; Org-bullets for better headings
(use-package org-bullets
  :after org
  :hook (org-mode . org-bullets-mode)
  :custom
  (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●")))

Add List Dots

By default lists are started with a hyphen, though this doesn't really match the aesthetic of the rest of the org file. Due to that, I added this line which replaces the hyphen with a dot.

  • Bullet point 1
  • Bullet point 2
  • Bullet point 3
;; Replace - lists with a dot
(font-lock-add-keywords 'org-mode
                        '(("^ *\\([-]\\) "
                           (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))

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.

(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 "Fira Code Light" :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))

Visual Fill Column

Visual fill column is a package that allows you to center text and add borders to the sides of an org file. By default org files are displayed completely to the left side of the page like normal text files.

;; Set left-right margins with visual-fill-column
(defun jm/org-mode-visual-fill ()
  (setq visual-fill-column-width 100
        visual-fill-column-center-text t)
  (visual-fill-column-mode 1))

(use-package visual-fill-column
  :after org
  :hook (org-mode . jm/org-mode-visual-fill))

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.

(use-package evil-org
  :after org
  :hook (org-mode . (lambda () evil-org-mode))
  :config
  (require 'evil-org-agenda)
  (evil-org-agenda-set-keys))

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.

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

Refresh Org Agenda Files

Creates a function to refresh the org-agenda-files variable to be set to include all org roam notes files.

(defun jm/org-roam-refresh-agenda-list ()
  (interactive)
  (setq org-agenda-files (org-roam-list-files)))

To use this function, I'll add it to some hooks to make sure to run it before the agenda list is needed.

(advice-add 'org-agenda :before #'jm/org-roam-refresh-agenda-list)
(advice-add 'org-todo-list :before #'jm/org-roam-refresh-agenda-list)
(advice-add 'dashboard-get-agenda :before #'jm/org-roam-refresh-agenda-list)

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.

(setq org-todo-keyword-faces '(("IN PROGRESS" . (:foreground "orange" :weight bold))
                               ("WAITING" . (:foreground "yellow" :weight bold))))
                               

(setq org-todo-keywords '((sequence "TODO(t)" "IN PROGRESS(i)" "WAITING(w)" "|" "DONE(d)" "CANCELLED(c)")))

Refresh Checkboxes

Adds a hook to repeated tasks in org agenda that, when repeated, checkboxes will be reset to an unchecked state.

(add-hook 'org-todo-repeat-hook #'org-reset-checkbox-state-subtree)

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.

(use-package org-roam
  :custom
  (org-roam-directory (file-truename "~/Dropbox/org"))
  :bind (("C-c n l" . org-roam-buffer-toggle)
         ("C-c n f" . org-roam-node-find)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n c" . org-roam-capture)
         ("C-c n o" . org-id-get-create)

         ;; Dailies
         ("C-c n j" . org-roam-dailies-capture-today)
         ("C-c n k" . org-roam-dailies-capture-tomorrow))
  :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)))
  (setq org-roam-dailies-capture-templates
        `(("d" "Default" entry "* %?" :target
           (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n"))
          ("t" "Daily 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))

  (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
  (require 'org-roam-dailies)
  (org-roam-db-autosync-mode))

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.

  (require 'org-tempo)

Ispell

Configure Ispell to not spell check certain org mode specific keywords. By default, Ispell doesn't have a default dictionary selected. This can be changed by running ispell-change-dictionary. If no dictionaries are found, you can install them from the hunspell-en_us pacman package.

(add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:")) ;
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
(add-to-list 'ispell-skip-region-alist '("~" . "~"))
(add-to-list 'ispell-skip-region-alist '("\\[\\[" . "\\]"))