From fa26dc1269b4872ed8b9a053b588c0a6d2deea88 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 7 Mar 2019 00:15:15 -0500 Subject: [PATCH] Refactor lang/org --- modules/lang/org/+attach.el | 66 +++++---- modules/lang/org/+babel.el | 84 ++++++------ modules/lang/org/+capture.el | 104 +++++++------- modules/lang/org/+export.el | 49 ++++--- modules/lang/org/+present.el | 18 +-- modules/lang/org/autoload/org-link.el | 17 +++ modules/lang/org/config.el | 186 ++++++++++++-------------- 7 files changed, 253 insertions(+), 271 deletions(-) diff --git a/modules/lang/org/+attach.el b/modules/lang/org/+attach.el index eee6c0223..bade75ea5 100644 --- a/modules/lang/org/+attach.el +++ b/modules/lang/org/+attach.el @@ -1,7 +1,5 @@ ;;; 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 ;; 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 :commands (org-download-dnd org-download-dnd-base64) @@ -62,35 +90,3 @@ (advice-add #'org-download--dir-2 :override #'ignore) (advice-add #'org-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))))) - diff --git a/modules/lang/org/+babel.el b/modules/lang/org/+babel.el index f78d10a6b..1495a063f 100644 --- a/modules/lang/org/+babel.el +++ b/modules/lang/org/+babel.el @@ -1,7 +1,5 @@ ;;; lang/org/+babel.el -*- lexical-binding: t; -*- -(add-hook 'org-load-hook #'+org|init-babel) - (defvar +org-babel-mode-alist '((cpp . C) (C++ . C) @@ -16,48 +14,51 @@ For example, with (fish . shell) will cause #+BEGIN_SRC fish to load ob-shell.el when executed.") (defvar +org-babel-load-functions () - "A list of functions for loading the current executing src block. They take -one argument (the language specified in the src block, as a string). Stops 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))) + "A list of functions executed to load the current executing src block. They +take one argument (the language specified in the src block, as a string). Stops +at the first function to return non-nil.") ;; -;; 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 :when (featurep! +ipython) @@ -83,7 +84,6 @@ the first function to return non-nil.") ("\\*Python:.*" :slot 0 :side right :size 100 :select nil :quit nil :transient nil))) - ;; TODO Add more popup styles ;; advices for remote kernel and org-src-edit (advice-add 'org-babel-edit-prep:ipython :override #'+org*org-babel-edit-prep:ipython) diff --git a/modules/lang/org/+capture.el b/modules/lang/org/+capture.el index 3b8edc8c7..25372098d 100644 --- a/modules/lang/org/+capture.el +++ b/modules/lang/org/+capture.el @@ -1,7 +1,5 @@ ;;; 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 ;; 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'.") -(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 () - (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)) +;;; Bootstrap - (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) - "If a variable is used for a file path in `org-capture-template', it is used + ;; 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))) + +(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 relative to `org-directory', unless it is an absolute path." - (if (and (symbolp file) (boundp file)) - (expand-file-name (symbol-value file) org-directory) - file)) - (advice-add #'org-capture-expand-file :filter-args #'+org*expand-variable-paths) + (if (and (symbolp file) (boundp file)) + (expand-file-name (symbol-value file) org-directory) + file)) +(advice-add #'org-capture-expand-file :filter-args #'+org*capture-expand-variable-file) - (defun +org*prevent-save-prompts-when-refiling (&rest _) - "Fix #462: when refiling from org-capture, Emacs prompts to kill the +(defun +org*prevent-save-prompts-when-refiling (&rest _) + "Fix #462: when refiling from org-capture, Emacs prompts to kill the underlying, modified buffer. This fixes that." - (when (bound-and-true-p org-capture-is-refiling) - (org-save-all-org-buffers))) - (advice-add 'org-refile :after #'+org*prevent-save-prompts-when-refiling) + (when (bound-and-true-p org-capture-is-refiling) + (org-save-all-org-buffers))) +(advice-add 'org-refile :after #'+org*prevent-save-prompts-when-refiling) - (defun +org|show-target-in-capture-header () - (setq header-line-format - (format "%s%s%s" - (propertize (abbreviate-file-name (buffer-file-name (buffer-base-buffer))) - 'face 'font-lock-string-face) - org-eldoc-breadcrumb-separator - header-line-format))) - (add-hook 'org-capture-mode-hook #'+org|show-target-in-capture-header) +(defun +org|show-target-in-capture-header () + (setq header-line-format + (format "%s%s%s" + (propertize (abbreviate-file-name (buffer-file-name (buffer-base-buffer))) + 'face 'font-lock-string-face) + org-eldoc-breadcrumb-separator + header-line-format))) +(add-hook 'org-capture-mode-hook #'+org|show-target-in-capture-header) - (when (featurep! :feature evil) - (add-hook 'org-capture-mode-hook #'evil-insert-state)) +(when (featurep! :feature evil) + (add-hook 'org-capture-mode-hook #'evil-insert-state)) - (when (featurep! :ui doom-dashboard) - (add-hook '+doom-dashboard-inhibit-functions #'+org-capture-frame-p))) +(when (featurep! :ui doom-dashboard) + (add-hook '+doom-dashboard-inhibit-functions #'+org-capture-frame-p)) diff --git a/modules/lang/org/+export.el b/modules/lang/org/+export.el index ac418cc66..1e93bfe48 100644 --- a/modules/lang/org/+export.el +++ b/modules/lang/org/+export.el @@ -1,7 +1,5 @@ ;;; 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 ;; would export to a central directory (by default), rather than ;; `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) - org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/")) +(setq org-export-backends '(ascii html latex md) + org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/")) - (when (and (executable-find "pandoc") - (require 'ox-pandoc nil t)) - (add-to-list 'org-export-backends 'pandoc nil #'eq) - (setq org-pandoc-options - '((standalone . t) - (mathjax . t) - (variable . "revealjs-url=https://cdn.jsdelivr.net/npm/reveal.js@3/")))) +(when (and (executable-find "pandoc") + (require 'ox-pandoc nil t)) + (add-to-list 'org-export-backends 'pandoc nil #'eq) + (setq org-pandoc-options + '((standalone . t) + (mathjax . t) + (variable . "revealjs-url=https://cdn.jsdelivr.net/npm/reveal.js@3/")))) - ;; Export to a central location by default or if target isn't in - ;; `org-directory'. - (defun +org*export-output-file-name (args) - "Return a centralized export location unless one is provided or the current +;; Export to a central location by default or if target isn't in +;; `org-directory'. +(defun +org*export-output-file-name (args) + "Return a centralized export location unless one is provided or the current file isn't in `org-directory'." - (when (and (not (nth 2 args)) - buffer-file-name - (file-in-directory-p buffer-file-name org-directory)) - (cl-destructuring-bind (extension &optional subtreep _pubdir) args - (let ((dir (expand-file-name +org-export-dir org-directory))) - (unless (file-directory-p dir) - (make-directory dir t)) - (setq args (list extension subtreep dir))))) - args) - (advice-add #'org-export-output-file-name :filter-args #'+org*export-output-file-name)) + (when (and (not (nth 2 args)) + buffer-file-name + (file-in-directory-p buffer-file-name org-directory)) + (cl-destructuring-bind (extension &optional subtreep _pubdir) args + (let ((dir (expand-file-name +org-export-dir org-directory))) + (unless (file-directory-p dir) + (make-directory dir t)) + (setq args (list extension subtreep dir))))) + args) +(advice-add #'org-export-output-file-name :filter-args #'+org*export-output-file-name) diff --git a/modules/lang/org/+present.el b/modules/lang/org/+present.el index ae054aa1d..bc6938a4f 100644 --- a/modules/lang/org/+present.el +++ b/modules/lang/org/+present.el @@ -1,7 +1,5 @@ ;;; lang/org/+present.el -*- lexical-binding: t; -*- -(add-hook 'org-load-hook #'+org|init-present) - (defvar +org-present-text-scale 7 "The `text-scale-amount' for `org-tree-slide-mode'.") @@ -10,7 +8,7 @@ ;; Packages (def-package! ox-reveal - :defer t + :after ox :init ;; Fix #1127, where ox-reveal adds an errant entry to ;; `org-structure-template-alist' @@ -34,18 +32,10 @@ :n [left] #'org-tree-slide-move-previous-tree) (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) (advice-add #'org-tree-slide--display-tree-with-narrow :around #'+org-present*narrow-to-subtree)) - - -(def-package! centered-window :commands centered-window-mode) - - -;; -;; Bootstrap - -(defun +org|init-present () - (require 'ox-reveal)) diff --git a/modules/lang/org/autoload/org-link.el b/modules/lang/org/autoload/org-link.el index 8d55ef8d0..62e37f7c0 100644 --- a/modules/lang/org/autoload/org-link.el +++ b/modules/lang/org/autoload/org-link.el @@ -13,3 +13,20 @@ (format "%s:%s" key (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))) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index 0e962491b..025107d04 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -1,8 +1,5 @@ ;;; 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) (defvar org-directory "~/org/") (defvar org-modules @@ -17,25 +14,58 @@ ;; 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 - org-faces org-entities org-list org-pcomplete org-src - org-footnote org-macro ob org org-agenda org-capture)) +;; +;;; Bootstrap + +(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' -(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 :when (featurep! :feature evil +everywhere) @@ -43,7 +73,7 @@ :init (defvar evil-org-key-theme '(navigation insert textobjects)) (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) :config ;; change `evil-org-key-theme' instead @@ -56,65 +86,34 @@ :when (featurep! :tools pdf) :commands (org-pdfview-open) :init - (after! org - (delete '("\\.pdf\\'" . default) org-file-apps) - ;; 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)))) - ;; support for links to specific pages - (add-to-list 'org-file-apps '("\\.pdf::\\([[:digit:]]+\\)\\'" . (lambda (_file link) (org-pdfview-open link)))))) + (delete '("\\.pdf\\'" . default) org-file-apps) + ;; 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)))) + ;; support for links to specific pages + (add-to-list 'org-file-apps '("\\.pdf::\\([[:digit:]]+\\)\\'" . (lambda (_file link) (org-pdfview-open link))))) -(def-package! org-yt - :after org +(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 - (defun +org-inline-data-image (_protocol link _description) - "Interpret LINK as base64-encoded image data." - (base64-decode-string link)) + (setq org-tags-exclude-from-inheritance '("crypt") + org-crypt-key user-mail-address)) - (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))) - - (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)) +(def-package! org-clock ; built-in + :commands org-clock-save + :hook (org-mode . org-clock-load) + :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)) ;; -;; Bootstrap - -(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 +;;; `org-mode' hooks (defun +org|unfold-to-2nd-level-or-point () "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 () (unless org-agenda-files @@ -179,6 +178,7 @@ unfold to point on startup." org-agenda-start-on-weekday nil org-agenda-start-day "-3d")) + (defun +org|setup-popup-rules () "Defines popup rules for org-mode (does nothing if :ui popup is disabled)." (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) ("^CAPTURE.*\\.org$" :size 0.2 :quit nil :select t :autosave t)))) + (defun +org|setup-pretty-code () "Setup the default pretty symbols for" (set-pretty-symbols! 'org-mode @@ -196,6 +197,7 @@ unfold to point on startup." :src_block "#+BEGIN_SRC" :src_block_end "#+END_SRC")) + (defun +org|setup-custom-links () "Set up custom org links." (setq org-link-abbrev-alist @@ -235,7 +237,14 @@ unfold to point on startup." (+org-def-link "org" org-directory) (+org-def-link "doom" doom-emacs-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 () "Configures the UI for `org-mode'." @@ -272,8 +281,8 @@ unfold to point on startup." org-startup-with-inline-images nil org-tags-column 0 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)")) org-todo-keyword-faces '(("[-]" :inherit (font-lock-constant-face bold)) @@ -303,6 +312,7 @@ unfold to point on startup." :background nil t)))) (add-hook 'doom-load-theme-hook #'+org|update-latex-preview-background-color)) + (defun +org|setup-keybinds () "Sets up org-mode and evil keybindings. Tries to fix the idiosyncrasies between the two." @@ -331,7 +341,8 @@ between the two." [remap doom/backward-to-bol-or-indent] #'org-beginning-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 ;; prevents recursive requires. (unless args (require 'evil-org)) @@ -420,6 +431,7 @@ between the two." "G" (λ! (org-clock-goto 'select)) "x" #'org-clock-cancel))) + (defun +org|setup-hacks () "Getting org to behave." ;; 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) (run-hooks 'org-load-hook))