;;; org-mode.el --- org-mode customizations -*- lexical-binding: t -*- ;; Author: Andrew Scott ;; Keywords: org, convenience, tools ;; URL: https://codeberg.org/andyscott/dotfiles ;; This file is not part of GNU Emacs ;; Copyright (c) 2024 Andrew Scott ;; MIT No Attribution ;; Permission is hereby granted, free of charge, to any person obtaining a copy of this ;; software and associated documentation files (the "Software"), to deal in the Software ;; without restriction, including without limitation the rights to use, copy, modify, ;; merge, publish, distribute, sublicense, and/or sell copies of the Software, and to ;; permit persons to whom the Software is furnished to do so. ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, ;; INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A ;; PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ;;; Commentary: ;; My org-mode customizations. ;;; Code: (use-feature org :bind (:map as/org-prefix-map ("a" . org-agenda) ("c" . org-capture) ("d" . org-priority-down) ("h" . consult-org-heading) ("l" . org-store-link) ("s" . org-insert-subheading) ("u" . org-priority-up) ("y" . org-todo-yesterday) ("C-h" . consult-org-agenda) ("C-l" . embark-org-copy-link-target) ; `embark' ("M-l" . org-toggle-link-display) ; `ol' ("t" . org-tags-view)) ; `org-agenda' (:map org-mode-map ;; supposed to be set by `org-use-extra-keys' ;; and still overwritten with `org-insert-drawer' when `org' is loaded ("C-c C-x d" . org-metadown)) :config ;; General options TODO: Comment various options more descriptively (setopt org-adapt-indentation nil org-agenda-files (directory-files-recursively org-directory "org$") org-archive-location (expand-file-name "archive/%s_archive.org::" org-directory) org-blank-before-new-entry '((heading . t) (plain-list-item . t)) org-deadline-warning-days 5 org-default-notes-file (expand-file-name "inbox.org" org-directory) org-enforce-todo-checkbox-dependencies t org-fontify-done-headline t org-fontify-todo-headline nil org-goto-interface 'outline-path-completion ; `org-goto' org-hide-emphasis-markers t org-insert-heading-respect-content t org-log-done 'time org-log-into-drawer t org-log-redeadline 'time org-M-RET-may-split-line nil org-pretty-entities t org-pretty-entities-include-sub-superscripts nil org-reverse-note-order t ; Add/refile notes at the beginning of an entry org-special-ctrl-a/e t org-special-ctrl-k t org-startup-folded 'content org-tags-column 0 org-todo-keywords '((sequence "TODO(t)" "NEXT(x)" "PROG(p)" "WAIT(w@/!)" "|" "DONE(d!)" "WONT(n@/!)") (sequence "IDEA(i)" "|")) org-todo-repeat-to-state "TODO") :defer 3 :hook (org-mode . org-indent-mode) (org-mode . variable-pitch-mode) :init (bind-keys :prefix-map as/org-prefix-map :prefix "C-c o") (setopt org-directory "~/Nextcloud/Documents/org" org-use-extra-keys t)) ;;; Built-in Packages: (use-feature oc :after (org) :config (setopt org-cite-export-processors '((latex biblatex) (t csl)) org-cite-global-bibliography '("~/Nextcloud/Library/bib/library.bib")) (when (elpaca-installed-p 'citar) (setopt org-cite-activate-processor 'citar org-cite-follow-processor 'citar org-cite-insert-processor 'citar))) (use-feature oc-csl :after (citeproc oc) :config (let ((zotero_styles (expand-file-name "Zotero/styles/" (or (getenv "XDG_DATA_HOME") "~/.local/share/")))) (if (file-directory-p zotero_styles) (setopt org-cite-csl-styles-dir zotero_styles)))) (use-feature org-agenda :after (org) :bind (:map org-agenda-mode-map ("C-c C-r" . as/org-agenda-reconcile-inbox-item)) :config (setopt org-agenda-block-separator ?- org-agenda-skip-deadline-if-done nil org-agenda-skip-scheduled-if-deadline-is-shown nil org-agenda-skip-scheduled-if-done nil org-agenda-start-on-weekday nil org-agenda-start-with-log-mode '(clock closed state) org-agenda-tags-column 0) (defun as/org-agenda-reconcile-inbox-item () "Process and refile an org-agenda item" (interactive) (org-with-wide-buffer (org-agenda-set-tags) (org-agenda-priority) (if (y-or-n-p "Schedule item?") (org-agenda-schedule nil nil)) (org-agenda-refile nil nil t)))) (use-feature org-capture :after (org) :config (setq org-capture-templates ; `org-capture' `( ("i" "Inbox" entry (file+headline "inbox.org" "Ideas") "** IDEA %?" :empty-lines 1 ) ("j" "Log Entry" entry (file+datetree "log.org") "** %?" :empty-lines 1) ("n" "Note" entry (file+headline "inbox.org" "Notes") "** %? :PROPERTIES: :CREATED: %U :END:" :empty-lines 1) ("t" "Todo" entry (file+headline "inbox.org" "Tasks") "** TODO [#B] %? :PROPERTIES: :CREATED: %U :END: %i\n%a Notes: " :empty-lines 1) ) ) ) (use-feature org-clock :after (org) :config (setopt org-clock-in-resume t org-clock-in-switch-to-state "PROG" org-clock-persist t org-clock-rounding-minutes 5 org-clock-string-limit 20)) (use-feature org-faces :after (org) :config (setopt org-fontify-quote-and-verse-blocks t org-todo-keyword-faces '(("TODO" . (:inherit dired-mark :inverse-video t)) ("PROG" . (:inherit match :inverse-video t)) ("NEXT" . (:inherit dired-special :inverse-video t)) ("WAIT" . (:inherit shadow :inverse-video t)) ("WONT" . (:inherit org-done)) ("DONE" . (:inherit org-done)) ("IDEA" . (:inherit bold :inverse-video t))) org-priority-faces '((?A . (:inherit error :weight semibold :inverse-video t)) (?B . (:inherit warning :weight semibold :inverse-video t)) (?C . (:inherit mode-line-inactive :weight semibold :inverse-video t)))) :custom-face ;; Headlines (org-level-1 ((t (:inherit outline-1 :height 1.5)))) (org-level-2 ((t (:inherit outline-2 :height 1.4)))) (org-level-3 ((t (:inherit outline-3 :height 1.4)))) (org-level-4 ((t (:inherit outline-4 :height 1.2)))) (org-level-5 ((t (:inherit outline-5 :height 1.1)))) ;; Ensure monospace Keywords/Tags/Blocks (org-block ((t (:inherit fixed-pitch)))) ; inherited by `org-code' (org-block-begin-line ((t (:inherit fixed-pitch)))) (org-block-end-line ((t (:inherit (org-block-begin-line fixed-pitch))))) (org-checkbox ((t (:inherit (org-todo fixed-pitch))))) (org-checkbox-statistics-todo ((t (:inherit (org-todo fixed-pitch))))) (org-date ((t (:inherit fixed-pitch)))) (org-document-info-keyword ((t (:inherit (shadow fixed-pitch))))) (org-drawer ((t (:inherit fixed-pitch)))) (org-indent ((t (:inherit (org-hide fixed-pitch))))) (org-link ((t (:foreground "dark cyan" :underline t)))) (org-list-dt ((t (:inherit fixed-pitch)))) (org-meta-line ((t (:inherit (fixed-pitch))))) (org-property-value ((t (:inherit fixed-pitch)))) (org-special-keyword ((t (:inherit fixed-pitch)))) (org-table ((t (:inherit fixed-pitch)))) (org-tag ((t (:inherit (fixed-pitch) :height 0.8)))) (org-verbatim ((t (:inherit fixed-pitch))))) (use-feature org-fold :after (org) :config (setopt org-fold-catch-invisible-edits 'show-and-error)) (use-feature org-habit :after (org)) (use-feature org-id :after (org) :config (setopt org-id-link-to-org-use-id t org-id-locations-file (locate-user-emacs-file "org-id-locations") org-id-method 'ts org-id-ts-format "%Y%m%dT%H%M%S.%2N%z")) (use-feature org-keys :after (org) :config (setopt org-return-follows-link t)) (use-feature org-list :after (org) :config (setopt org-list-demote-modify-bullet '(("+" . "-") ("-" . "+") ("*" . "+")))) (use-feature org-refile :after (org) :config (setopt org-log-refile 'note org-outline-path-complete-in-steps nil org-refile-allow-creating-parent-nodes 'confirm org-refile-targets '((nil :maxlevel . 3) (org-agenda-files :maxlevel . 2)) org-refile-use-outline-path 'file)) (use-feature org-src :after (org) :config (setopt org-edit-src-content-indentation 0 org-src-preserve-indentation t org-src-tab-acts-natively t)) ;;; 3rd-party Packages: (use-package citar :after (oc) :config (setopt citar-bibliography org-cite-global-bibliography citar-library-paths '("~/Nextcloud/Library/")) ;; (when (elpaca-installed-p 'citar-embark) ;; (setopt citar-at-point-function 'embark-act)) :hook (org-mode . citar-capf-setup)) (use-package citar-embark :after (citar embark) :config (citar-embark-mode)) (use-package citar-org-roam :after (citar org-roam) :config (setopt citar-org-roam-capture-template-key "r" citar-org-roam-note-title-template "${title} - ${author}" citar-org-roam-subdir "references") (citar-org-roam-mode)) (use-package citeproc :defer t) (use-package org-appear :bind (:prefix-map as/org-appear :prefix "C-c C-q") :config (setopt org-appear-autoentities t org-appear-autolinks nil org-appear-autosubmarkers t org-appear-trigger 'on-change) :hook (org-mode . org-appear-mode)) (use-package org-edna :bind (:map as/org-prefix-map ("e" . org-edna-edit)) :config (setopt org-edna-finder-use-cache t) :hook (org-mode . org-edna-mode)) (use-package org-noter :disabled t :after (org) :config (setopt org-noter-notes-search-path (list (concat org-directory "/roam"))) (org-noter-enable-org-roam-integration)) (use-package org-pomodoro :after (org-clock) :bind (:map as/org-prefix-map ("m" . org-pomodoro)) :commands (org-pomodoro) :config (setopt alert-user-configuration ; Send messages to libnotify '((((:category . "org-pomodoro")) libnotify nil)) org-pomodoro-audio-player (concat (executable-find "pw-cat") " -p") org-pomodoro-keep-killed-pomodoro-time t org-pomodoro-length 50 org-pomodoro-long-break-frequency 2 org-pomodoro-manual-break t org-pomodoro-short-break-length 10)) (use-package org-roam ;; :after (org) :bind (:map as/org-roam-prefix-map ("b" . org-roam-buffer-display-dedicated) ("c" . org-roam-capture) ("f" . org-roam-node-find) ("i" . org-roam-node-insert)) :config (setopt org-roam-database-connector 'sqlite-builtin org-roam-directory (file-name-as-directory (expand-file-name "roam" org-directory))) (setq org-roam-db-gc-threshold most-positive-fixnum) ; doesn't like the new `setopt' (add-to-list 'display-buffer-alist '("\\*org-roam\\*" (display-buffer-in-direction) (direction . right) (window-width . 0.33) (window-height . fit-window-to-buffer))) (add-to-list 'org-roam-capture-templates '("r" "reference" plain "%?" :target (file+head "references/${citar-citekey}.org" "#+title: ${note-title}\n") :empty-lines 1 :unnarrowed t )) (add-to-list 'org-roam-capture-templates `("p" "project" plain (file ,(concat org-roam-directory "/templates/projects.org")) :target (file+head "projects/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: :projects:") :empty-lines 1 :unnarrowed t)) (org-roam-db-autosync-mode) :ensure (org-roam :files (:defaults "extensions/*")) :init (bind-keys :prefix-map as/org-roam-prefix-map :prefix "C-c r")) (use-package org-super-agenda :hook (org-agenda-mode . org-super-agenda-mode) :init (setq org-agenda-custom-commands '(("u" "Super agenda" ((agenda "" ((org-agenda-prefix-format " %-12t% s%?-6e") ;;(org-agenda-prefix-format " %?-12t %s") (org-agenda-remove-tags t) (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo '("WONT"))) (org-agenda-span 'day))) (alltodo "" ((org-agenda-overriding-header "\nI'M DOING IT...") (org-agenda-prefix-format " %-20T") ;; (org-agenda-prefix-format " %?-12t %s") (org-agenda-remove-tags t) (org-super-agenda-groups '( (:name "Done Today" ; FIXME :todo "DONE" :log t :order 95) (:name "Overdue" :deadline past :scheduled past :order 1) (:name "Waiting" :todo "WAIT" :order 80) (:name "Upcoming" :deadline future :scheduled future :order 99) (:name "High Priority" :priority "A" :order 5) (:name "Now" :todo ("PROG" "NEXT") :order 10) (:name "Personal" :and (:deadline today :tag "personal") :and (:scheduled today :tag "personal") :order 30) (:name "Household" :and (:deadline today :tag "household") :and (:scheduled today :tag "household") :order 35) (:name "Today" :deadline today :scheduled today :order 15) (:name "Project Backlog" :and (:todo "TODO" :tag "projects") :order 20) (:name "Research" :tag "research" :order 40) (:name "Personal Backlog" :and (:todo "TODO" :tag "personal") :and (:todo "TODO" :tag "job_search") :order 45) (:name "Household Backlog" :and (:todo "TODO" :priority<= "B" :tag "household") :order 50) (:name "Inbox" :tag "inbox" :order 90) ))))) )))) (use-package org-superstar :config (if org-odd-levels-only (setopt org-superstar-headline-bullets-list '(?◉ ?- ?🞛 ?- ?○ ?- ?▷ ?- ?✸ ?- ?✿ ?-)) (setopt org-superstar-headline-bullets-list '(?◉ ?🞛 ?○ ?▷ ?✸ ?✿))) (setopt org-indent-mode-turns-on-hiding-stars nil ; needed for `org-superstar-leading-bullet' org-superstar-leading-bullet ?\s org-superstar-hide-leading-stars t org-superstar-special-todo-items t org-superstar-todo-bullet-alist '(("TODO" . ?☐) ("NEXT" . ?☐) ("PROG" . ?☐) ("WAIT" . ?☐) ("DONE" . ?☑) ("WONT" . ?☑))) :hook (org-mode . org-superstar-mode)) (use-package org-timeblock :bind (:map as/org-prefix-map ("b" . org-timeblock)) :config (setopt org-timeblock-new-task-time 'pick org-timeblock-show-future-repeats 'next org-timeblock-scale-options (cons 7 20) org-timeblock-span 3)) (provide 'init-org) ;;; org-mode.el ends here