From 8e37c4903d65b390244d03bbfe9d4393a0935f9d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 21 Aug 2016 16:53:38 +0200 Subject: [PATCH] Refactor org-mode config (WIP) --- ...ns-org-notebook.el => defuns-org-notes.el} | 67 ++++---- ...le-org-notebook.el => module-org-notes.el} | 76 ++++++---- modules/module-org.el | 143 +++++++++--------- 3 files changed, 145 insertions(+), 141 deletions(-) rename modules/defuns/{defuns-org-notebook.el => defuns-org-notes.el} (67%) rename modules/{module-org-notebook.el => module-org-notes.el} (59%) diff --git a/modules/defuns/defuns-org-notebook.el b/modules/defuns/defuns-org-notes.el similarity index 67% rename from modules/defuns/defuns-org-notebook.el rename to modules/defuns/defuns-org-notes.el index 79671222f..642125b94 100644 --- a/modules/defuns/defuns-org-notebook.el +++ b/modules/defuns/defuns-org-notes.el @@ -1,4 +1,4 @@ -;;; defuns-org-notebook.el +;;; defuns-org-notes.el ;;;###autoload (defun doom/org () @@ -34,7 +34,7 @@ (rassq-delete-all 'doom/org-download-dnd (copy-alist dnd-protocol-alist)))) (dnd-handle-one-url nil action uri)))) -;;;###autoload (autoload 'doom:org-attach "defuns-org-notebook" nil t) +;;;###autoload (autoload 'doom:org-attach "defuns-org-notes" nil t) (evil-define-command doom:org-attach (&optional uri) (interactive "") (unless (eq major-mode 'org-mode) @@ -51,22 +51,21 @@ (if (evil-visual-state-p) (org-insert-link nil (format "./%s" rel-path) (concat (buffer-substring-no-properties (region-beginning) (region-end)) - " " (doom/org-attach-icon rel-path))) + " " (doom--org-attach-icon rel-path))) (insert (if image-p - (format "[[./%s]]" rel-path) - (format "%s [[./%s][%s]]" - (doom/org-attach-icon rel-path) + (format "[[./%s]] " rel-path) + (format "%s [[./%s][%s]] " + (doom--org-attach-icon rel-path) rel-path (f-filename rel-path))))) (when (string-match-p (regexp-opt '("jpg" "jpeg" "gif" "png")) (f-ext rel-path)) - (org-toggle-inline-images))) - (let ((attachments (doom-org-attachments))) - (unless attachments - (user-error "No attachments in this file")) - (helm :sources (helm-build-sync-source "Attachments" :candidates attachments))))) + (org-redisplay-inline-images))) + (let ((default-directory ".attach/")) + (if (file-exists-p default-directory) + (call-interactively 'find-file) + (user-error "No attachments"))))) -;;;###autoload -(defun doom/org-attach-icon (path) +(defun doom--org-attach-icon (path) (char-to-string (pcase (downcase (f-ext path)) ("jpg" ?) ("jpeg" ?) ("png" ?) ("gif" ?) ("pdf" ?) @@ -76,12 +75,20 @@ ("ogg" ?) ("mp3" ?) ("wav" ?) ("mp4" ?) ("mov" ?) ("avi" ?) ("zip" ?) ("gz" ?) ("tar" ?) ("7z" ?) ("rar" ?) - (t ?)))) + (_ ?)))) ;;;###autoload -(defun doom/org-attachments () - "Retrieves a list of all the attachments pertinent to the currect org-mode buffer." - (require 'org-macs) +(defun doom/org-cleanup-attachments () + ;; "Deletes any attachments that are no longer present in the org-mode buffer." + (let* ((attachments-local (doom-org-attachments)) + (attachments (f-entries org-attach-directory)) + (to-delete (-difference attachments-local attachments))) + ;; TODO + to-delete)) + +(defun doom-org-attachments () + (unless (eq major-mode 'org-mode) + (user-error "Not an org buffer")) (org-save-outline-visibility nil (let ((attachments '()) element @@ -100,28 +107,6 @@ (push file attachments)))))) (-distinct attachments)))) -;;;###autoload -(defun doom/org-cleanup-attachments () - "Deletes any attachments that are no longer present in the org-mode buffer." - (let* ((attachments (doom/org-attachments)) - (to-delete (-difference doom-org-attachments-list attachments))) - (mapc (lambda (f) - (message "Deleting attachment: %s" f) - (delete-file f t)) - to-delete) - (setq doom-org-attachments-list attachments))) - -;; -;; Easy searching -;; - -;; Ex-mode interface for `helm-ag'. If `bang', then `search' is interpreted as -;; regexp. -;;;###autoload (autoload 'doom:org-helm-search "defuns-org-notebook" nil t) -(evil-define-operator doom:org-helm-search (beg end &optional search bang) - (interactive "") - (doom:helm-ag-search beg end (if bang (concat "^\\*+.*" search ".*$") search) t org-directory)) - -(provide 'defuns-org-notebook) -;;; defuns-org-notebook.el ends here +(provide 'defuns-org-notes) +;;; defuns-org-notes.el ends here diff --git a/modules/module-org-notebook.el b/modules/module-org-notes.el similarity index 59% rename from modules/module-org-notebook.el rename to modules/module-org-notes.el index d829bf543..c62fc8198 100644 --- a/modules/module-org-notebook.el +++ b/modules/module-org-notes.el @@ -1,4 +1,4 @@ -;;; module-org-notebook.el +;;; module-org-notes.el ;; This transforms Emacs+org-mode into a notebook application with: ;; + Custom links for class notes @@ -13,12 +13,12 @@ (add-hook 'org-load-hook 'doom|org-attach-init t) (add-hook 'org-load-hook 'doom|org-export-init t) -(defvar org-directory-notebook (expand-file-name "/notebook/" org-directory)) -(defvar org-default-notes-file (expand-file-name "inbox.org" org-directory)) +(defconst org-directory-notebook (f-expand "notes/" org-directory)) +(defconst org-default-notes-file (f-expand "inbox.org" org-directory-notebook)) (defvar org-attach-directory ".attach/") -(defvar doom-org-export-directory (concat org-directory ".export")) -(defvar doom-org-quicknote-dir (concat org-directory "Inbox/")) +(defvar org-export-directory (concat org-directory ".export")) +(defvar org-quicknote-directory (concat org-directory "Inbox/")) ;; Keep track of attachments (defvar-local doom-org-attachments-list '() @@ -32,13 +32,40 @@ ;; (defun doom|org-notebook-init () - ;; (define-org-section! course "Classes" - ;; (lambda (path) (substring path 0 (s-index-of " " path))) "%s*.org") - ;; (exmap "ocl[ass]" 'doom:org-search-course) - (doom-fix-unicode "FontAwesome" '(? ? ? ? ? ? ? ?) 13)) + (setq org-capture-templates + '(;; TODO: New Note (note) + ;; TODO: New Task (todo) + ;; TODO: New vocabulary word + ("c" "Changelog" entry + (file+headline (f-expand "CHANGELOG.org" (doom/project-root)) "Unreleased") + "* %?") + + ;; ("p" "Project Notes" entry + ;; (file+headline org-default-notes-file "Inbox") + ;; "* %u %?\n%i" :prepend t) + + ;; ("m" "Major-mode Notes" entry + ;; (file+headline org-default-notes-file "Inbox") + ;; "* %u %?\n%i" :prepend t) + + ;; ("n" "Notes" entry + ;; (file+headline org-default-notes-file "Inbox") + ;; "* %u %?\n%i" :prepend t) + + ;; ("v" "Vocab" entry + ;; (file+headline (concat org-directory "topics/vocab.org") "Unsorted") + ;; "** %i%?\n") + ))) + +;; I don't like Org's attachment system. So I replaced it with my own, which stores +;; attachments in a global org .attach directory. It also implements drag-and-drop +;; file support and attachment icons. It also treats images specially. ;; +;; To clean up unreferenced attachments, call `doom/org-cleanup-attachments' (defun doom|org-attach-init () + ;; Render attachment icons properly + (doom-fix-unicode '("FontAwesome" 13) ? ? ? ? ? ? ? ?) ;; Drag-and-drop support (require 'org-download) (setq-default org-download-image-dir org-attach-directory @@ -56,13 +83,7 @@ ;; Add another drag-and-drop handler that will handle anything but image files (setq dnd-protocol-alist `(("^\\(https?\\|ftp\\|file\\|nfs\\):\\(//\\)?" . doom/org-download-dnd) - ,@dnd-protocol-alist)) - - ;; ...auto-delete attachments once all references to it have been deleted. - (add-hook 'org-mode-hook 'doom|org-attach-track-init) - (defun doom|org-attach-track-init () - (setq doom-org-attachments-list (doom/org-attachments)) - (add-hook 'after-save-hook 'doom/org-cleanup-attachments nil t))) + ,@dnd-protocol-alist))) ;; @@ -76,23 +97,22 @@ (setq org-pandoc-options '((standalone . t) (mathjax . t) (parse-raw . t))) ;; Export to a central directory (why isn't this easier?) - (unless (file-directory-p doom-org-export-directory) - (mkdir doom-org-export-directory)) + (unless (file-directory-p org-export-directory) + (mkdir org-export-directory)) (defun doom*org-export-output-file-name (args) (unless (nth 2 args) - (setq args (append args (list doom-org-export-directory)))) + (setq args (append args (list org-export-directory)))) args) (advice-add 'org-export-output-file-name :filter-args 'doom*org-export-output-file-name)) - -;; +;; TODO ;; (defvar doom-org-tags '()) ;; (defun doom|org-tag-init () ;; (async-start ;; `(lambda () -;; (let ((default-directory (doom/project-root)) -;; (data (s-trim (shell-command-to-string "ag --nocolor --nonumbers '^#\\+TAGS:'"))) -;; (alist '())) +;; (let* ((default-directory (doom/project-root)) +;; (data (s-trim (shell-command-to-string "ag --nocolor --nonumbers '^#\\+TAGS:'"))) +;; (alist '())) ;; (unless (zerop (length data)) ;; (mapc (lambda (l) ;; (let* ((parts (s-split ":" l)) @@ -107,10 +127,8 @@ ;; (s-lines data)) ;; alist))) ;; (lambda (_) -;; (load (concat php-extras-eldoc-functions-file ".el")) -;; (message "PHP eldoc updated!"))) -;; ) +;; ))) ;; -(provide 'module-org-notebook) -;;; module-org-notebook.el ends here +(provide 'module-org-notes) +;;; module-org-notes.el ends here diff --git a/modules/module-org.el b/modules/module-org.el index 94502e8f6..578e6c127 100644 --- a/modules/module-org.el +++ b/modules/module-org.el @@ -1,27 +1,24 @@ ;;; module-org.el --- -*- no-byte-compile: t; -*- -(add-hook 'org-load-hook 'doom|org-init t) -(add-hook 'org-load-hook 'doom|org-keybinds t) -(add-hook 'org-mode-hook 'doom|org-hook) - -(defvar org-directory (expand-file-name "~/Dropbox/notes/")) +(defconst org-directory (expand-file-name "~/Dropbox/org/")) (define-minor-mode evil-org-mode "Evil-mode bindings for org-mode." :init-value nil - :lighter " !" - :keymap (make-sparse-keymap) ; defines evil-org-mode-map - :group 'evil-org) + :lighter " !" + :keymap (make-sparse-keymap) + :group 'evil-org) -(require 'module-org-crm) -(require 'module-org-notebook) +(add-hook 'org-load-hook 'doom|org-init t) +(add-hook 'org-load-hook 'doom|org-keybinds t) +(add-hook 'org-load-hook 'doom|org-hacks t) +(add-hook 'org-mode-hook 'doom|org-hook) ;; (defun doom|org-hook () (evil-org-mode +1) (visual-line-mode +1) - (setq line-spacing 2) - (org-bullets-mode +1) + (setq line-spacing 1) ;; If saveplace places the point in a folded position, unfold it on load (when (outline-invisible-p) @@ -53,7 +50,6 @@ org-indent-mode-turns-on-hiding-stars t org-adapt-indentation nil org-blank-before-new-entry '((heading . nil) (plain-list-item . auto)) - org-bullets-bullet-list '("✸" "•" "◦" "•" "◦" "•" "◦") org-cycle-separator-lines 1 org-cycle-include-plain-lists t org-ellipsis 'hs-face @@ -64,7 +60,7 @@ org-fontify-whole-heading-line t org-footnote-auto-label 'plain org-hide-emphasis-markers t - org-hide-leading-stars nil + org-hide-leading-stars t org-image-actual-width nil org-indent-indentation-per-level 2 org-pretty-entities t @@ -90,7 +86,7 @@ org-special-ctrl-a/e t ;; Sorting/refiling - org-archive-location (concat org-directory "/Archived/%s::") + org-archive-location (concat org-directory "/archived/%s::") org-refile-targets '((nil . (:maxlevel . 2))) ; display full path in refile completion ;; Agenda @@ -100,7 +96,7 @@ org-agenda-window-setup 'other-frame ; to get org-agenda to behave with shackle... org-agenda-inhibit-startup t org-agenda-files (f-entries org-directory (lambda (path) (f-ext? path "org"))) - org-todo-keywords '((sequence "[ ](t)" "[-](p)" "|" "[X](d)") + org-todo-keywords '((sequence "[ ](t)" "[-](p)" "[?](m)" "|" "[X](d)") (sequence "TODO(T)" "|" "DONE(D)") (sequence "IDEA(i)" "NEXT(n)" "ACTIVE(a)" "WAITING(w)" "LATER(l)" "|" "CANCELLED(c)")) @@ -124,40 +120,7 @@ ;; org-latex-packages-alist ;; '(("" "gauss" t) ;; ("" "physics" t) TODO Install this) - - org-capture-templates - '(;; TODO: New Note (note) - ;; TODO: New Task (todo) - ;; TODO: New vocabulary word - - ("c" "Changelog" entry - (file+headline (f-expand "CHANGELOG.org" (doom/project-root)) "Unreleased") - "* %?") - - ;; ("p" "Project Notes" entry - ;; (file+headline org-default-notes-file "Inbox") - ;; "* %u %?\n%i" :prepend t) - - ;; ("m" "Major-mode Notes" entry - ;; (file+headline org-default-notes-file "Inbox") - ;; "* %u %?\n%i" :prepend t) - - ;; ("n" "Notes" entry - ;; (file+headline org-default-notes-file "Inbox") - ;; "* %u %?\n%i" :prepend t) - - ;; ("v" "Vocab" entry - ;; (file+headline (concat org-directory "topics/vocab.org") "Unsorted") - ;; "** %i%?\n") - )) - - ;; Display certain unicode characters properly - ;; (doom-fix-unicode '("DejaVu Sans" 13) - ;; ?♭ ?♯ ?⟳ - ;; ?× ?∙ ?÷ ?⌉ ?⌈ ?⌊ ?⌋ - ;; ?∩ ?∪ ?⊆ ?⊂ ?⊄ ?⊇ ?⊃ ?⊅ - ;; ?⇒ ?⇐ ?⇔ ?↔ ?→ ?≡ ?∴ ?∵ ?⊕ ?∀ ?∃ ?∄ ?∈ ?∉ - ;; ?∨ ?∧ ?¬) + ) (org-babel-do-load-languages 'org-babel-load-languages @@ -176,12 +139,6 @@ ext-regexp "\\)\\(\\]\\]\\|>\\|'\\)?") . 2) (,(concat "<\\(http://.+\\." ext-regexp "\\)>") . 1)))) - ;; Don't open separate windows - (push '(file . find-file) org-link-frame-setup) - - ;; Reveal files in finder - (setq org-file-apps '(("\\.org$" . emacs) (t . "open -R \"%s\""))) - ;; Fontify checkboxes and dividers (defface org-list-bullet '((t ())) "Face for list bullets") (font-lock-add-keywords @@ -199,33 +156,77 @@ org-crypt-key user-mail-address epa-file-encrypt-to user-mail-address) - ;; Don't track attachments - (push (format "/%s.+$" (regexp-quote org-attach-directory)) recentf-exclude) + ;; smartparens config + (sp-with-modes '(org-mode) + (sp-local-pair "\\[" "\\]" :post-handlers '(("| " "SPC"))) + (sp-local-pair "\\(" "\\)" :post-handlers '(("| " "SPC"))) + (sp-local-pair "$$" "$$" :post-handlers '((:add " | ")) :unless '(sp-point-at-bol-p)) + (sp-local-pair "{" nil)) + + ;; bullets + (use-package org-bullets :commands org-bullets-mode)) + +(defun doom|org-hacks () + ;; Don't open separate windows + (push '(file . find-file) org-link-frame-setup) + + ;; Reveal files in finder + (setq org-file-apps '(("\\.org$" . emacs) (t . "open -R \"%s\""))) + ;; Don't clobber recentf with agenda files (defun org-is-agenda-file (filename) (find (file-truename filename) org-agenda-files :key 'file-truename :test 'equal)) (pushnew 'org-is-agenda-file recentf-exclude) + ;; Don't track attachments + (push (format "/%s.+$" (regexp-quote org-attach-directory)) recentf-exclude) + ;; Remove highlights on ESC (defun doom*org-remove-occur-highlights (&rest args) (when (eq major-mode 'org-mode) (org-remove-occur-highlights))) (advice-add 'evil-force-normal-state :before 'doom*org-remove-occur-highlights) - ;; smartparens config - (sp-with-modes '(org-mode) - (sp-local-pair "*" "*" :unless '(sp-point-after-word-p sp-point-at-bol-p) :skip-match 'doom/sp-org-skip-asterisk) - (sp-local-pair "_" "_" :unless '(sp-point-before-word-p sp-point-after-word-p sp-point-before-symbol-p)) - (sp-local-pair "/" "/" :unless '(sp-point-before-word-p sp-point-after-word-p sp-point-before-symbol-p) :post-handlers '(("[d1]" "SPC"))) - (sp-local-pair "~" "~" :unless '(sp-point-before-word-p sp-point-after-word-p sp-point-before-symbol-p) :post-handlers '(("[d1]" "SPC"))) - (sp-local-pair "=" "=" :unless '(sp-point-before-word-p sp-point-after-word-p sp-point-before-symbol-p) :post-handlers '(("[d1]" "SPC"))) + ;; Don't reset org-hide! + (advice-add 'org-find-invisible-foreground :override 'ignore) - (sp-local-pair "\\[" "\\]" :post-handlers '(("| " "SPC"))) - (sp-local-pair "\\(" "\\)" :post-handlers '(("| " "SPC"))) - (sp-local-pair "$$" "$$" :post-handlers '((:add " | ")) :unless '(sp-point-at-bol-p)) - (sp-local-pair "{" nil)) + ;; Tame org-mode popups + ;; Ensures org-src-edit yields control of its buffer to shackle. + (defun org-src-switch-to-buffer (buffer context) + (pop-to-buffer buffer)) - (use-package org-bullets :commands (org-bullets-mode))) + ;; And these for org-todo, org-link and org-agenda + (defun org-pop-to-buffer-same-window (&optional buffer-or-name norecord label) + "Pop to buffer specified by BUFFER-OR-NAME in the selected window." + (display-buffer buffer-or-name)) + + (defun org-switch-to-buffer-other-window (&rest args) + (mapc (lambda (b) + (let ((buf (if (stringp b) (get-buffer-create b) b))) + (pop-to-buffer buf t t))) + args)) + + ;; Taming Org-agenda! + (defun doom/org-agenda-quit () + "Necessary to finagle org-agenda into shackle popups and behave properly on quit." + (interactive) + (if org-agenda-columns-active + (org-columns-quit) + (let ((buf (current-buffer))) + (and (not (eq org-agenda-window-setup 'current-window)) + (not (one-window-p)) + (delete-window)) + (kill-buffer buf) + (setq org-agenda-archives-mode nil + org-agenda-buffer nil)))) + + (after! org-agenda + (map! :map org-agenda-mode-map + :e "" 'doom/org-agenda-quit + :e "ESC" 'doom/org-agenda-quit + :e [escape] 'doom/org-agenda-quit + "q" 'doom/org-agenda-quit + "Q" 'doom/org-agenda-quit))) (defun doom|org-keybinds () (map! (:map org-mode-map @@ -347,7 +348,7 @@ :v "<" (λ! (org-metaleft) (evil-visual-restore)) :v ">" (λ! (org-metaright) (evil-visual-restore)) :n "-" 'org-cycle-list-bullet - :n [tab] 'org-cycle) + :m "" 'org-cycle) (:map org-src-mode-map :n "" (λ! (message "Exited") (org-edit-src-exit)))