Refactor lang/org

This commit is contained in:
Henrik Lissner 2019-03-07 00:15:15 -05:00
parent c0c4b897ea
commit fa26dc1269
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
7 changed files with 253 additions and 271 deletions

View file

@ -1,7 +1,5 @@
;;; lang/org/+attach.el -*- lexical-binding: t; -*- ;;; lang/org/+attach.el -*- lexical-binding: t; -*-
(add-hook 'org-load-hook #'+org|init-attach)
;; I believe Org's native attachment system is over-complicated and litters ;; I believe Org's native attachment system is over-complicated and litters
;; files with metadata I don't want. So I wrote my own, which: ;; files with metadata I don't want. So I wrote my own, which:
;; ;;
@ -25,7 +23,37 @@
;; ;;
;; Packages ;;; Bootstrap
(setq org-attach-directory (expand-file-name +org-attach-dir org-directory)
org-download-image-dir org-attach-directory
org-download-heading-lvl nil
org-download-timestamp "_%Y%m%d_%H%M%S")
;; A shorter link to attachments
(add-to-list 'org-link-abbrev-alist (cons "attach" (abbreviate-file-name org-attach-directory)))
(org-link-set-parameters
"attach"
:follow (lambda (link) (find-file (expand-file-name link org-attach-directory)))
:complete (lambda (&optional _arg)
(+org--relpath (+org-link-read-file "attach" org-attach-directory)
org-attach-directory))
:face (lambda (link)
(if (file-exists-p (expand-file-name link org-attach-directory))
'org-link
'error)))
(after! projectile
(add-to-list 'projectile-globally-ignored-directories
(car (last (split-string +org-attach-dir "/" t)))))
(after! recentf
(add-to-list 'recentf-exclude (format "%s.+$" (regexp-quote org-attach-directory))))
;;
;;; Packages
(def-package! org-download (def-package! org-download
:commands (org-download-dnd org-download-dnd-base64) :commands (org-download-dnd org-download-dnd-base64)
@ -62,35 +90,3 @@
(advice-add #'org-download--dir-2 :override #'ignore) (advice-add #'org-download--dir-2 :override #'ignore)
(advice-add #'org-download--fullname (advice-add #'org-download--fullname
:filter-return #'+org-attach*download-fullname)) :filter-return #'+org-attach*download-fullname))
;;
;; Bootstrap
(defun +org|init-attach ()
(setq org-attach-directory (expand-file-name +org-attach-dir org-directory))
(setq-default org-download-image-dir org-attach-directory
org-download-heading-lvl nil
org-download-timestamp "_%Y%m%d_%H%M%S")
;; A shorter link to attachments
(add-to-list 'org-link-abbrev-alist (cons "attach" (abbreviate-file-name org-attach-directory)))
(org-link-set-parameters
"attach"
:follow (lambda (link) (find-file (expand-file-name link org-attach-directory)))
:complete (lambda (&optional _arg)
(+org--relpath (+org-link-read-file "attach" org-attach-directory)
org-attach-directory))
:face (lambda (link)
(if (file-exists-p (expand-file-name link org-attach-directory))
'org-link
'error)))
(after! projectile
(add-to-list 'projectile-globally-ignored-directories
(car (last (split-string +org-attach-dir "/" t)))))
(after! recentf
(add-to-list 'recentf-exclude (format "%s.+$" (regexp-quote org-attach-directory)))))

View file

@ -1,7 +1,5 @@
;;; lang/org/+babel.el -*- lexical-binding: t; -*- ;;; lang/org/+babel.el -*- lexical-binding: t; -*-
(add-hook 'org-load-hook #'+org|init-babel)
(defvar +org-babel-mode-alist (defvar +org-babel-mode-alist
'((cpp . C) '((cpp . C)
(C++ . C) (C++ . C)
@ -16,48 +14,51 @@ For example, with (fish . shell) will cause #+BEGIN_SRC fish to load ob-shell.el
when executed.") when executed.")
(defvar +org-babel-load-functions () (defvar +org-babel-load-functions ()
"A list of functions for loading the current executing src block. They take "A list of functions executed to load the current executing src block. They
one argument (the language specified in the src block, as a string). Stops at take one argument (the language specified in the src block, as a string). Stops
the first function to return non-nil.") at the first function to return non-nil.")
(defun +org|init-babel ()
(setq org-src-fontify-natively t ; make code pretty
org-src-preserve-indentation t ; use native major-mode indentation
org-src-tab-acts-natively t
org-src-window-setup 'current-window
org-confirm-babel-evaluate nil) ; you don't need my permission
(defun +org*babel-lazy-load-library (info)
"Load babel libraries as needed when babel blocks are executed."
(let* ((lang (nth 0 info))
(lang (if (symbolp lang) lang (intern lang)))
(lang (or (cdr (assq lang +org-babel-mode-alist))
lang)))
(when (and (not (cdr (assq lang org-babel-load-languages)))
(or (run-hook-with-args-until-success '+org-babel-load-functions lang)
(require (intern (format "ob-%s" lang)) nil t)))
(when (assq :async (nth 2 info))
;; ob-async has its own agenda for lazy loading packages (in the
;; child process), so we only need to make sure it's loaded.
(require 'ob-async nil t))
(add-to-list 'org-babel-load-languages (cons lang t)))
t))
(advice-add #'org-babel-confirm-evaluate :after-while #'+org*babel-lazy-load-library)
;; I prefer C-c C-c over C-c ' (more consistent)
(define-key org-src-mode-map (kbd "C-c C-c") #'org-edit-src-exit)
;; `org-babel-get-header' was removed from org in 9.0. Quite a few babel
;; plugins use it, so until those plugins update, this polyfill will do:
(defun org-babel-get-header (params key &optional others)
(cl-loop with fn = (if others #'not #'identity)
for p in params
if (funcall fn (eq (car p) key))
collect p)))
;; ;;
;; Packages ;;; Bootstrap
(setq org-src-fontify-natively t ; make code pretty
org-src-preserve-indentation t ; use native major-mode indentation
org-src-tab-acts-natively t
org-src-window-setup 'current-window
org-confirm-babel-evaluate nil) ; you don't need my permission
(defun +org*babel-lazy-load-library (info)
"Load babel libraries lazily when babel blocks are executed."
(let* ((lang (nth 0 info))
(lang (if (symbolp lang) lang (intern lang)))
(lang (or (cdr (assq lang +org-babel-mode-alist))
lang)))
(when (and (not (cdr (assq lang org-babel-load-languages)))
(or (run-hook-with-args-until-success '+org-babel-load-functions lang)
(require (intern (format "ob-%s" lang)) nil t)))
(when (assq :async (nth 2 info))
;; ob-async has its own agenda for lazy loading packages (in the
;; child process), so we only need to make sure it's loaded.
(require 'ob-async nil t))
(add-to-list 'org-babel-load-languages (cons lang t)))
t))
(advice-add #'org-babel-confirm-evaluate :after-while #'+org*babel-lazy-load-library)
;; I prefer C-c C-c over C-c ' (more consistent)
(define-key org-src-mode-map (kbd "C-c C-c") #'org-edit-src-exit)
;; `org-babel-get-header' was removed from org in 9.0. Quite a few babel
;; plugins use it, so until those plugins update, this polyfill will do:
(defun org-babel-get-header (params key &optional others)
(cl-loop with fn = (if others #'not #'identity)
for p in params
if (funcall fn (eq (car p) key))
collect p))
;;
;;; Packages
(def-package! ob-ipython (def-package! ob-ipython
:when (featurep! +ipython) :when (featurep! +ipython)
@ -83,7 +84,6 @@ the first function to return non-nil.")
("\\*Python:.*" ("\\*Python:.*"
:slot 0 :side right :size 100 :slot 0 :side right :size 100
:select nil :quit nil :transient nil))) :select nil :quit nil :transient nil)))
;; TODO Add more popup styles
;; advices for remote kernel and org-src-edit ;; advices for remote kernel and org-src-edit
(advice-add 'org-babel-edit-prep:ipython :override #'+org*org-babel-edit-prep:ipython) (advice-add 'org-babel-edit-prep:ipython :override #'+org*org-babel-edit-prep:ipython)

View file

@ -1,7 +1,5 @@
;;; lang/org/+capture.el -*- lexical-binding: t; -*- ;;; lang/org/+capture.el -*- lexical-binding: t; -*-
(add-hook 'org-load-hook #'+org|init-capture)
;; Sets up some reasonable defaults, as well as two `org-capture' workflows that ;; Sets up some reasonable defaults, as well as two `org-capture' workflows that
;; I like: ;; I like:
;; ;;
@ -28,68 +26,62 @@ Is relative to `org-directory', unless it is absolute. Is used in Doom's default
It is used in Doom's default `org-capture-templates'.") It is used in Doom's default `org-capture-templates'.")
(defvar org-capture-templates
'(("t" "Personal todo" entry
(file+headline +org-capture-todo-file "Inbox")
"* [ ] %?\n%i\n%a" :prepend t :kill-buffer t)
("n" "Personal notes" entry
(file+headline +org-capture-notes-file "Inbox")
"* %u %?\n%i\n%a" :prepend t :kill-buffer t)
;; Will use {project-root}/{todo,notes,changelog}.org, unless a
;; {todo,notes,changelog}.org file is found in a parent directory.
("p" "Templates for projects")
("pt" "Project todo" entry ; {project-root}/todo.org
(file+headline +org-capture-project-todo-file "Inbox")
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)
("pn" "Project notes" entry ; {project-root}/notes.org
(file+headline +org-capture-project-notes-file "Inbox")
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)
("pc" "Project changelog" entry ; {project-root}/changelog.org
(file+headline +org-capture-project-notes-file "Unreleased")
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)))
(defvar org-default-notes-file nil) ; defined in org.el
;; ;;
(defun +org|init-capture () ;;; Bootstrap
(dolist (var '(+org-capture-todo-file
+org-capture-notes-file))
(set var (expand-file-name (symbol-value var) org-directory)))
(unless org-default-notes-file
(setq org-default-notes-file +org-capture-notes-file))
(add-hook 'org-capture-after-finalize-hook #'+org-capture|cleanup-frame) (setq org-capture-templates
'(("t" "Personal todo" entry
(file+headline +org-capture-todo-file "Inbox")
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)
("n" "Personal notes" entry
(file+headline +org-capture-notes-file "Inbox")
"* %u %?\n%i\n%a" :prepend t :kill-buffer t)
(defun +org*expand-variable-paths (file) ;; Will use {project-root}/{todo,notes,changelog}.org, unless a
"If a variable is used for a file path in `org-capture-template', it is used ;; {todo,notes,changelog}.org file is found in a parent directory.
("p" "Templates for projects")
("pt" "Project todo" entry ; {project-root}/todo.org
(file+headline +org-capture-project-todo-file "Inbox")
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)
("pn" "Project notes" entry ; {project-root}/notes.org
(file+headline +org-capture-project-notes-file "Inbox")
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)
("pc" "Project changelog" entry ; {project-root}/changelog.org
(file+headline +org-capture-project-notes-file "Unreleased")
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)))
(defvaralias '+org-capture-notes-file 'org-default-notes-file)
(add-hook 'org-capture-after-finalize-hook #'+org-capture|cleanup-frame)
(defun +org*capture-expand-variable-file (file)
"If a variable is used for a file path in `org-capture-template', it is used
as is, and expanded relative to `default-directory'. This changes it to be as is, and expanded relative to `default-directory'. This changes it to be
relative to `org-directory', unless it is an absolute path." relative to `org-directory', unless it is an absolute path."
(if (and (symbolp file) (boundp file)) (if (and (symbolp file) (boundp file))
(expand-file-name (symbol-value file) org-directory) (expand-file-name (symbol-value file) org-directory)
file)) file))
(advice-add #'org-capture-expand-file :filter-args #'+org*expand-variable-paths) (advice-add #'org-capture-expand-file :filter-args #'+org*capture-expand-variable-file)
(defun +org*prevent-save-prompts-when-refiling (&rest _) (defun +org*prevent-save-prompts-when-refiling (&rest _)
"Fix #462: when refiling from org-capture, Emacs prompts to kill the "Fix #462: when refiling from org-capture, Emacs prompts to kill the
underlying, modified buffer. This fixes that." underlying, modified buffer. This fixes that."
(when (bound-and-true-p org-capture-is-refiling) (when (bound-and-true-p org-capture-is-refiling)
(org-save-all-org-buffers))) (org-save-all-org-buffers)))
(advice-add 'org-refile :after #'+org*prevent-save-prompts-when-refiling) (advice-add 'org-refile :after #'+org*prevent-save-prompts-when-refiling)
(defun +org|show-target-in-capture-header () (defun +org|show-target-in-capture-header ()
(setq header-line-format (setq header-line-format
(format "%s%s%s" (format "%s%s%s"
(propertize (abbreviate-file-name (buffer-file-name (buffer-base-buffer))) (propertize (abbreviate-file-name (buffer-file-name (buffer-base-buffer)))
'face 'font-lock-string-face) 'face 'font-lock-string-face)
org-eldoc-breadcrumb-separator org-eldoc-breadcrumb-separator
header-line-format))) header-line-format)))
(add-hook 'org-capture-mode-hook #'+org|show-target-in-capture-header) (add-hook 'org-capture-mode-hook #'+org|show-target-in-capture-header)
(when (featurep! :feature evil) (when (featurep! :feature evil)
(add-hook 'org-capture-mode-hook #'evil-insert-state)) (add-hook 'org-capture-mode-hook #'evil-insert-state))
(when (featurep! :ui doom-dashboard) (when (featurep! :ui doom-dashboard)
(add-hook '+doom-dashboard-inhibit-functions #'+org-capture-frame-p))) (add-hook '+doom-dashboard-inhibit-functions #'+org-capture-frame-p))

View file

@ -1,7 +1,5 @@
;;; lang/org/+export.el -*- lexical-binding: t; -*- ;;; lang/org/+export.el -*- lexical-binding: t; -*-
(add-hook 'org-load-hook #'+org|init-export)
;; I don't have any beef with org's built-in export system, but I do wish it ;; I don't have any beef with org's built-in export system, but I do wish it
;; would export to a central directory (by default), rather than ;; would export to a central directory (by default), rather than
;; `default-directory'. This is because all my org files are usually in one ;; `default-directory'. This is because all my org files are usually in one
@ -14,30 +12,29 @@ path too.")
;; ;;
(defun +org|init-export () (setq org-export-backends '(ascii html latex md)
(setq org-export-backends '(ascii html latex md) org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/"))
org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/"))
(when (and (executable-find "pandoc") (when (and (executable-find "pandoc")
(require 'ox-pandoc nil t)) (require 'ox-pandoc nil t))
(add-to-list 'org-export-backends 'pandoc nil #'eq) (add-to-list 'org-export-backends 'pandoc nil #'eq)
(setq org-pandoc-options (setq org-pandoc-options
'((standalone . t) '((standalone . t)
(mathjax . t) (mathjax . t)
(variable . "revealjs-url=https://cdn.jsdelivr.net/npm/reveal.js@3/")))) (variable . "revealjs-url=https://cdn.jsdelivr.net/npm/reveal.js@3/"))))
;; Export to a central location by default or if target isn't in ;; Export to a central location by default or if target isn't in
;; `org-directory'. ;; `org-directory'.
(defun +org*export-output-file-name (args) (defun +org*export-output-file-name (args)
"Return a centralized export location unless one is provided or the current "Return a centralized export location unless one is provided or the current
file isn't in `org-directory'." file isn't in `org-directory'."
(when (and (not (nth 2 args)) (when (and (not (nth 2 args))
buffer-file-name buffer-file-name
(file-in-directory-p buffer-file-name org-directory)) (file-in-directory-p buffer-file-name org-directory))
(cl-destructuring-bind (extension &optional subtreep _pubdir) args (cl-destructuring-bind (extension &optional subtreep _pubdir) args
(let ((dir (expand-file-name +org-export-dir org-directory))) (let ((dir (expand-file-name +org-export-dir org-directory)))
(unless (file-directory-p dir) (unless (file-directory-p dir)
(make-directory dir t)) (make-directory dir t))
(setq args (list extension subtreep dir))))) (setq args (list extension subtreep dir)))))
args) args)
(advice-add #'org-export-output-file-name :filter-args #'+org*export-output-file-name)) (advice-add #'org-export-output-file-name :filter-args #'+org*export-output-file-name)

View file

@ -1,7 +1,5 @@
;;; lang/org/+present.el -*- lexical-binding: t; -*- ;;; lang/org/+present.el -*- lexical-binding: t; -*-
(add-hook 'org-load-hook #'+org|init-present)
(defvar +org-present-text-scale 7 (defvar +org-present-text-scale 7
"The `text-scale-amount' for `org-tree-slide-mode'.") "The `text-scale-amount' for `org-tree-slide-mode'.")
@ -10,7 +8,7 @@
;; Packages ;; Packages
(def-package! ox-reveal (def-package! ox-reveal
:defer t :after ox
:init :init
;; Fix #1127, where ox-reveal adds an errant entry to ;; Fix #1127, where ox-reveal adds an errant entry to
;; `org-structure-template-alist' ;; `org-structure-template-alist'
@ -34,18 +32,10 @@
:n [left] #'org-tree-slide-move-previous-tree) :n [left] #'org-tree-slide-move-previous-tree)
(add-hook! 'org-tree-slide-mode-after-narrow-hook (add-hook! 'org-tree-slide-mode-after-narrow-hook
#'(+org-present|detect-slide +org-present|add-overlays org-display-inline-images)) #'(+org-present|detect-slide
+org-present|add-overlays
org-display-inline-images))
(add-hook 'org-tree-slide-mode-hook #'+org-present|init-org-tree-window) (add-hook 'org-tree-slide-mode-hook #'+org-present|init-org-tree-window)
(advice-add #'org-tree-slide--display-tree-with-narrow (advice-add #'org-tree-slide--display-tree-with-narrow
:around #'+org-present*narrow-to-subtree)) :around #'+org-present*narrow-to-subtree))
(def-package! centered-window :commands centered-window-mode)
;;
;; Bootstrap
(defun +org|init-present ()
(require 'ox-reveal))

View file

@ -13,3 +13,20 @@
(format "%s:%s" (format "%s:%s"
key key
(file-relative-name file dir)))) (file-relative-name file dir))))
;;;###autoload
(defun +org-inline-data-image (_protocol link _description)
"Interpret LINK as base64-encoded image data."
(base64-decode-string link))
;;;###autoload
(defun +org-image-link (protocol link _description)
"Interpret LINK as base64-encoded image data."
(when (image-type-from-file-name link)
(if-let* ((buf (url-retrieve-synchronously (concat protocol ":" link))))
(with-current-buffer buf
(goto-char (point-min))
(re-search-forward "\r?\n\r?\n" nil t)
(buffer-substring-no-properties (point) (point-max)))
(message "Download of image \"%s\" failed" link)
nil)))

View file

@ -1,8 +1,5 @@
;;; lang/org/config.el -*- lexical-binding: t; -*- ;;; lang/org/config.el -*- lexical-binding: t; -*-
;; FIXME deprecated
(define-obsolete-variable-alias '+org-dir 'org-directory "2.1.0")
;; Changed org defaults (should be set before org loads) ;; Changed org defaults (should be set before org loads)
(defvar org-directory "~/org/") (defvar org-directory "~/org/")
(defvar org-modules (defvar org-modules
@ -17,25 +14,58 @@
;; org-rmail ;; org-rmail
)) ))
;; Sub-modules
(if (featurep! +attach) (load! "+attach"))
(if (featurep! +babel) (load! "+babel"))
(if (featurep! +capture) (load! "+capture"))
(if (featurep! +export) (load! "+export"))
(if (featurep! +present) (load! "+present"))
;; TODO (if (featurep! +publish) (load! "+publish"))
(doom-load-packages-incrementally ;;
'(calendar find-func format-spec org-macs org-compat ;;; Bootstrap
org-faces org-entities org-list org-pcomplete org-src
org-footnote org-macro ob org org-agenda org-capture)) (def-package! org
:defer-incrementally
(calendar find-func format-spec org-macs org-compat org-faces org-entities
org-list org-pcomplete org-src org-footnote org-macro ob org org-agenda
org-capture)
:init
(add-hook! 'org-load-hook
#'(+org|setup-ui
+org|setup-popup-rules
+org|setup-agenda
+org|setup-keybinds
+org|setup-hacks
+org|setup-pretty-code
+org|setup-custom-links))
(add-hook! 'org-mode-hook
#'(org-bullets-mode ; "prettier" bullets
org-indent-mode ; margin-based indentation
toc-org-enable ; auto-table of contents
auto-fill-mode ; line wrapping
;; `show-paren-mode' causes flickering with indentation margins made by
;; `org-indent-mode', so we simply turn off show-paren-mode altogether."
doom|disable-show-paren-mode
+org|enable-auto-reformat-tables
+org|enable-auto-update-cookies
+org|smartparens-compatibility-config
+org|unfold-to-2nd-level-or-point))
:config
;; Sub-modules
(if (featurep! +attach) (load! "+attach"))
(if (featurep! +babel) (load! "+babel"))
(if (featurep! +capture) (load! "+capture"))
(if (featurep! +export) (load! "+export"))
(if (featurep! +present) (load! "+present")))
;; ;;
;; Packages ;;; Packages
;; `toc-org' ;; `toc-org'
(setq toc-org-hrefify-default "org") (setq toc-org-hrefify-default "gh")
(defun +org*unfold-toc (&rest _)
(save-excursion
(when (re-search-forward toc-org-toc-org-regexp (point-max) t)
(+org/open-fold))))
(advice-add #'toc-org-insert-toc :before #'+org*unfold-toc)
(def-package! evil-org (def-package! evil-org
:when (featurep! :feature evil +everywhere) :when (featurep! :feature evil +everywhere)
@ -43,7 +73,7 @@
:init :init
(defvar evil-org-key-theme '(navigation insert textobjects)) (defvar evil-org-key-theme '(navigation insert textobjects))
(defvar evil-org-special-o/O '(table-row)) (defvar evil-org-special-o/O '(table-row))
(add-hook 'org-load-hook #'+org|setup-evil) (add-hook 'org-load-hook #'+org|setup-evil-keybinds)
(add-hook 'evil-org-mode-hook #'evil-normalize-keymaps) (add-hook 'evil-org-mode-hook #'evil-normalize-keymaps)
:config :config
;; change `evil-org-key-theme' instead ;; change `evil-org-key-theme' instead
@ -56,65 +86,34 @@
:when (featurep! :tools pdf) :when (featurep! :tools pdf)
:commands (org-pdfview-open) :commands (org-pdfview-open)
:init :init
(after! org (delete '("\\.pdf\\'" . default) org-file-apps)
(delete '("\\.pdf\\'" . default) org-file-apps) ;; org links to pdf files are opened in pdf-view-mode
;; org links to pdf files are opened in pdf-view-mode (add-to-list 'org-file-apps '("\\.pdf\\'" . (lambda (_file link) (org-pdfview-open link))))
(add-to-list 'org-file-apps '("\\.pdf\\'" . (lambda (_file link) (org-pdfview-open link)))) ;; support for links to specific pages
;; support for links to specific pages (add-to-list 'org-file-apps '("\\.pdf::\\([[:digit:]]+\\)\\'" . (lambda (_file link) (org-pdfview-open link)))))
(add-to-list 'org-file-apps '("\\.pdf::\\([[:digit:]]+\\)\\'" . (lambda (_file link) (org-pdfview-open link))))))
(def-package! org-yt (def-package! org-crypt ; built-in
:after org :commands org-encrypt-entries
:hook (org-reveal-start . org-decrypt-entry)
:init
(add-hook! 'org-mode-hook
(add-hook 'before-save-hook 'org-encrypt-entries nil t))
:config :config
(defun +org-inline-data-image (_protocol link _description) (setq org-tags-exclude-from-inheritance '("crypt")
"Interpret LINK as base64-encoded image data." org-crypt-key user-mail-address))
(base64-decode-string link))
(defun +org-image-link (protocol link _description) (def-package! org-clock ; built-in
"Interpret LINK as base64-encoded image data." :commands org-clock-save
(when (image-type-from-file-name link) :hook (org-mode . org-clock-load)
(if-let* ((buf (url-retrieve-synchronously (concat protocol ":" link)))) :init
(with-current-buffer buf (setq org-clock-persist 'history
(goto-char (point-min)) org-clock-persist-file (concat doom-etc-dir "org-clock-save.el"))
(re-search-forward "\r?\n\r?\n" nil t) :config
(buffer-substring-no-properties (point) (point-max))) (add-hook 'kill-emacs-hook #'org-clock-save))
(message "Download of image \"%s\" failed" link)
nil)))
(org-link-set-parameters "http" :image-data-fun #'+org-image-link)
(org-link-set-parameters "https" :image-data-fun #'+org-image-link)
(org-link-set-parameters "img" :image-data-fun #'+org-inline-data-image))
;; ;;
;; Bootstrap ;;; `org-mode' hooks
(add-hook! 'org-load-hook
#'(+org|setup-ui
+org|setup-popup-rules
+org|setup-agenda
+org|setup-keybinds
+org|setup-hacks
+org|setup-pretty-code
+org|setup-custom-links))
(add-hook! 'org-mode-hook
#'(org-bullets-mode ; "prettier" bullets
org-indent-mode ; margin-based indentation
toc-org-enable ; auto-table of contents
auto-fill-mode ; line wrapping
;; `show-paren-mode' causes flickering with indentation margins made by
;; `org-indent-mode', so we simply turn off show-paren-mode altogether."
doom|disable-show-paren-mode
+org|enable-auto-reformat-tables
+org|enable-auto-update-cookies
+org|smartparens-compatibility-config
+org|unfold-to-2nd-level-or-point))
;;
;; `org-mode' hooks
(defun +org|unfold-to-2nd-level-or-point () (defun +org|unfold-to-2nd-level-or-point ()
"My version of the 'overview' #+STARTUP option: expand first-level headings. "My version of the 'overview' #+STARTUP option: expand first-level headings.
@ -163,7 +162,7 @@ unfold to point on startup."
;; ;;
;; `org-load' hooks ;;; `org-load' hooks
(defun +org|setup-agenda () (defun +org|setup-agenda ()
(unless org-agenda-files (unless org-agenda-files
@ -179,6 +178,7 @@ unfold to point on startup."
org-agenda-start-on-weekday nil org-agenda-start-on-weekday nil
org-agenda-start-day "-3d")) org-agenda-start-day "-3d"))
(defun +org|setup-popup-rules () (defun +org|setup-popup-rules ()
"Defines popup rules for org-mode (does nothing if :ui popup is disabled)." "Defines popup rules for org-mode (does nothing if :ui popup is disabled)."
(set-popup-rules! (set-popup-rules!
@ -189,6 +189,7 @@ unfold to point on startup."
("^\\*Org Src" :size 0.3 :quit nil :select t :autosave t :ttl nil) ("^\\*Org Src" :size 0.3 :quit nil :select t :autosave t :ttl nil)
("^CAPTURE.*\\.org$" :size 0.2 :quit nil :select t :autosave t)))) ("^CAPTURE.*\\.org$" :size 0.2 :quit nil :select t :autosave t))))
(defun +org|setup-pretty-code () (defun +org|setup-pretty-code ()
"Setup the default pretty symbols for" "Setup the default pretty symbols for"
(set-pretty-symbols! 'org-mode (set-pretty-symbols! 'org-mode
@ -196,6 +197,7 @@ unfold to point on startup."
:src_block "#+BEGIN_SRC" :src_block "#+BEGIN_SRC"
:src_block_end "#+END_SRC")) :src_block_end "#+END_SRC"))
(defun +org|setup-custom-links () (defun +org|setup-custom-links ()
"Set up custom org links." "Set up custom org links."
(setq org-link-abbrev-alist (setq org-link-abbrev-alist
@ -235,7 +237,14 @@ unfold to point on startup."
(+org-def-link "org" org-directory) (+org-def-link "org" org-directory)
(+org-def-link "doom" doom-emacs-dir) (+org-def-link "doom" doom-emacs-dir)
(+org-def-link "doom-docs" doom-docs-dir) (+org-def-link "doom-docs" doom-docs-dir)
(+org-def-link "doom-modules" doom-modules-dir)) (+org-def-link "doom-modules" doom-modules-dir)
(def-package! org-yt
:config
(org-link-set-parameters "http" :image-data-fun #'+org-image-link)
(org-link-set-parameters "https" :image-data-fun #'+org-image-link)
(org-link-set-parameters "img" :image-data-fun #'+org-inline-data-image)))
(defun +org|setup-ui () (defun +org|setup-ui ()
"Configures the UI for `org-mode'." "Configures the UI for `org-mode'."
@ -272,8 +281,8 @@ unfold to point on startup."
org-startup-with-inline-images nil org-startup-with-inline-images nil
org-tags-column 0 org-tags-column 0
org-todo-keywords org-todo-keywords
'((sequence "[ ](t)" "[-](p)" "[?](m)" "|" "[X](d)") '((sequence "TODO(t)" "|" "DONE(d)")
(sequence "TODO(T)" "|" "DONE(D)") (sequence "[ ](T)" "[-](p)" "[?](m)" "|" "[X](D)")
(sequence "NEXT(n)" "WAITING(w)" "LATER(l)" "|" "CANCELLED(c)")) (sequence "NEXT(n)" "WAITING(w)" "LATER(l)" "|" "CANCELLED(c)"))
org-todo-keyword-faces org-todo-keyword-faces
'(("[-]" :inherit (font-lock-constant-face bold)) '(("[-]" :inherit (font-lock-constant-face bold))
@ -303,6 +312,7 @@ unfold to point on startup."
:background nil t)))) :background nil t))))
(add-hook 'doom-load-theme-hook #'+org|update-latex-preview-background-color)) (add-hook 'doom-load-theme-hook #'+org|update-latex-preview-background-color))
(defun +org|setup-keybinds () (defun +org|setup-keybinds ()
"Sets up org-mode and evil keybindings. Tries to fix the idiosyncrasies "Sets up org-mode and evil keybindings. Tries to fix the idiosyncrasies
between the two." between the two."
@ -331,7 +341,8 @@ between the two."
[remap doom/backward-to-bol-or-indent] #'org-beginning-of-line [remap doom/backward-to-bol-or-indent] #'org-beginning-of-line
[remap doom/forward-to-last-non-comment-or-eol] #'org-end-of-line)) [remap doom/forward-to-last-non-comment-or-eol] #'org-end-of-line))
(defun +org|setup-evil (&rest args)
(defun +org|setup-evil-keybinds (&rest args)
;; In case this hook is used in an advice on `evil-org-set-key-theme', this ;; In case this hook is used in an advice on `evil-org-set-key-theme', this
;; prevents recursive requires. ;; prevents recursive requires.
(unless args (require 'evil-org)) (unless args (require 'evil-org))
@ -420,6 +431,7 @@ between the two."
"G" (λ! (org-clock-goto 'select)) "G" (λ! (org-clock-goto 'select))
"x" #'org-clock-cancel))) "x" #'org-clock-cancel)))
(defun +org|setup-hacks () (defun +org|setup-hacks ()
"Getting org to behave." "Getting org to behave."
;; Don't open separate windows ;; Don't open separate windows
@ -469,29 +481,7 @@ conditions where a window's buffer hasn't changed at the time this hook is run."
;; ;;
;; Built-in libraries ;;; In case org has already been loaded (or you're running `doom/reload')
(def-package! org-crypt ; built-in
:commands org-encrypt-entries
:hook (org-reveal-start . org-decrypt-entry)
:init
(add-hook! 'org-mode-hook
(add-hook 'before-save-hook 'org-encrypt-entries nil t))
:config
(setq org-tags-exclude-from-inheritance '("crypt")
org-crypt-key user-mail-address))
(def-package! org-clock
:commands org-clock-save
:hook (org-mode . org-clock-load)
:defer-incrementally t
:init
(setq org-clock-persist 'history
org-clock-persist-file (concat doom-etc-dir "org-clock-save.el"))
:config
(add-hook 'kill-emacs-hook #'org-clock-save))
;; In case org has already been loaded (or you're running `doom/reload')
(when (featurep 'org) (when (featurep 'org)
(run-hooks 'org-load-hook)) (run-hooks 'org-load-hook))