;;; syd-org.el -*- lexical-binding: t; -*- (require 'syd-prose) (defun syd-org--init-hacks-h () ;; Open file links in current window, rather than new ones (setf (alist-get 'file org-link-frame-setup) #'find-file) ;; Open directory links in dired (add-to-list 'org-file-apps '(directory . emacs)) (add-to-list 'org-file-apps '(remote . emacs)) (defun syd-org--restart-mode-h () "Restart `org-mode', but only once." (syd-quietly (org-mode-restart)) (setq org-agenda-new-buffers (delq (current-buffer) org-agenda-new-buffers)) (run-hooks 'find-file-hook)) (syd-add-hook 'org-agenda-finalize-hook (defun syd-org-exclude-agenda-buffers-from-workspace-h () "Don't associate temporary agenda buffers with current workspace." (when (and org-agenda-new-buffers (bound-and-true-p persp-mode) (not org-agenda-sticky)) (let (persp-autokill-buffer-on-remove) (persp-remove-buffer org-agenda-new-buffers (get-current-persp) nil))))) (syd-defadvice syd-org--restart-mode-before-indirect-buffer-a (&optional buffer _) "Restart `org-mode' in buffers in which the mode has been deferred (see `syd-org-defer-mode-in-agenda-buffers-h') before they become the base buffer for an indirect org-cpature buffer. This ensures that the buffer is fully functional not only when the *user* visits it, but also when org-capture interacts with it via an indirect buffer." :before #'org-capture-get-indirect-buffer (with-current-buffer (or buffer (current-buffer)) (when (memq #'syd-org--restart-mode-h on-switch-buffer-hook) (syd-org--restart-mode-h)))) (defvar recentf-exclude) (syd-defadvice syd-org--optimize-backgrounded-agenda-buffers-a (fn file) "Disable `org-mode's startup processes for temporary agenda buffers. Prevents recentf pollution as well. However, if the user tries to visit one of these buffers they'll see a gimped, half-broken org buffer, so to avoid that, install a hook to restart `org-mode' when they're switched to so they can grow up to be fully-fledged org-mode buffers." :around #'org-get-agenda-file-buffer (if-let* ((buf (org-find-base-buffer-visiting file))) buf (let ((recentf-exclude '(always)) ;; (doom-inhibit-large-file-detection t) ;; (doom-inhibit-local-var-hooks t) (org-inhibit-startup t) vc-handled-backends enable-local-variables find-file-hook) (when-let ((buf (delay-mode-hooks (funcall fn file)))) (with-current-buffer buf (add-hook 'on-switch-buffer-hook #'syd-org--restart-mode-h nil 'local)) buf)))) (syd-defadvice syd-org--fix-inconsistent-uuidgen-case-a (uuid) "Ensure uuidgen is always lowercase (consistent) regardless of system. See https://lists.gnu.org/archive/html/emacs-orgmode/2019-07/msg00081.html." :filter-return #'org-id-new (if (eq org-id-method 'uuid) (downcase uuid) uuid))) (defun syd-org-init-faces () (let ((headline `(:weight bold))) (custom-theme-set-faces 'user ;; It is important that the `org-indent' face uses a fixed-pitch font, lest ;; e.g. multi-line bullets appear misaligned. '(org-indent ((t (:inherit (org-hide fixed-pitch))))) ;; Must be fixed-pitch; `[ ]` and `[X]' should be the same width. '(org-checkbox ((t (:inherit fixed-pitch)))) '(org-drawer ((t (:inherit (font-lock-comment-face fixed-pitch))))) '(org-property-value ((t (:inherit fixed-pitch))))))) (defun syd-org-init-keybinds () (general-def :keymaps 'org-mode-map :states '(insert emacs) [tab] #'org-cycle [C-M-return] #'org-insert-subheading) (general-def :prefix-map 'syd-org-mode-links-map "l" #'org-insert-link) (general-define-key :keymaps 'org-mode-map :states '(normal visual motion emacs insert) :major-modes t :prefix syd-localleader-key :non-normal-prefix syd-alt-localleader-key "." #'consult-org-heading "/" #'consult-org-agenda "@" #'org-cite-insert "e" #'org-export-dispatch "f" #'org-footnote-action "h" #'org-toggle-heading "i" #'org-toggle-item "I" #'org-id-get-create "k" #'org-babel-remove-result "l" `("Links" . ,syd-org-mode-links-map))) (use-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 :custom ((org-startup-folded 'content) (org-directory "~/org") ;; Stay out of my config dir! (org-id-locations-file (file-name-concat syd-cache-dir "org-id-locations")) ;; New headings should be inserted /after/ the heading's contents. (org-insert-heading-respect-content t)) :preface ;; Speed up initialisation by disabling modules we don't need. (defvar org-modules '(;; ol-w3m ;; ol-bbdb ol-bibtex ;; ol-docview ;; ol-gnus ;; ol-info ;; ol-irc ;; ol-mhe ;; ol-rmail ;; ol-eww )) :config (syd-add-hook 'org-mode-hook #'org-indent-mode #'syd-prose-mode) (syd-org-init-faces) (syd-org-init-keybinds)) ;; Unlike those appearing in `syd-org--init-roam-keybinds', these should be ;; available even outside of Org-mode. (general-def :prefix-map 'syd-leader-notes-roam-map "f" #'org-roam-node-find) (defun syd-org--init-roam-keybinds () (general-def :prefix-map 'syd-org-roam-mode-map) (general-def :prefix-map 'syd-leader-notes-map "r" `("Org-roam" . ,syd-leader-notes-roam-map)) (general-define-key :keymaps 'org-mode-map :states '(normal visual motion emacs insert) :major-modes t :prefix syd-localleader-key :non-normal-prefix syd-alt-localleader-key "m" `("Org-roam" . ,syd-org-roam-mode-map))) (use-package org-roam :hook (org-load . syd-org-init-roam-h) :commands (org-roam-buffer-toggle-display org-roam-dailies-find-date org-roam-dailies-find-today org-roam-dailies-find-tomorrow org-roam-dailies-find-yesterday) :init (progn (syd-org--init-roam-keybinds) (syd-load-packages-incrementally '(ansi-color dash f rx seq magit-section emacsql))) :custom ((org-roam-directory org-directory) (org-roam-db-location (file-name-concat syd-data-dir "org-roam.db")) ;; Make org-roam buffer sticky; i.e. don't replace it when opening a ;; file with an *-other-window command. (org-roam-buffer-window-parameters '((no-delete-other-windows . t))) (org-roam-completion-everywhere t)) :config (defun syd-org-init-roam-h () "Setup `org-roam' but don't immediately initialize its database. Instead, initialize it when it will be actually needed." (cl-letf (((symbol-function #'org-roam-db-sync) #'ignore)) (org-roam-db-autosync-enable))) (syd-org--init-roam-keybinds) (syd-defadvice syd-org-roam-try-init-db-a (&rest _) "Try to initialize org-roam database at the last possible safe moment. In case of failure, fail gracefully." :before #'org-roam-db-query (message "Initializing org-roam database...") (advice-remove 'org-roam-db-query #'syd-org-roam-try-init-db-a) (org-roam-db-sync))) (use-package evil-org :hook ((org-mode . evil-org-mode) (org-capture-mode . evil-insert-state) (doom-docs-org-mode . evil-org-mode)) :init (defvar evil-org-retain-visual-state-on-shift t) (defvar evil-org-special-o/O '(table-row)) (defvar evil-org-use-additional-insert t)) ;; (use-package evil-org-agenda ;; :hook (org-agenda-mode . evil-org-agenda-mode) ;; :config ;; (evil-org-agenda-set-keys) ;; ;; Stay away from my leader key! ;; (evil-define-key* 'motion evil-org-agenda-mode-map ;; (kbd syd-leader-key) nil)) (use-package hide-mode-line :hook (org-mode-hook . hide-mode-line-mode)) (provide 'syd-org) ;;; syd-org.el ends here