diff --git a/README.org b/README.org index 618cc99d..600201fc 100644 --- a/README.org +++ b/README.org @@ -9,6 +9,7 @@ - [[#keep-folders-clean][Keep Folders Clean]] - [[#ligatures][Ligatures]] - [[#keybindings][Keybindings]] + - [[#org-mode][Org Mode]] - [[#emoji][Emoji]] - [[#undo-tree][Undo-Tree]] - [[#undo-fu][Undo-Fu]] @@ -25,7 +26,6 @@ - [[#languages][Languages]] - [[#file-management][File Management]] - [[#ledger][Ledger]] - - [[#org-mode][Org Mode]] - [[#mu4e][MU4E]] - [[#calendar][Calendar]] - [[#org-caldav-sync][Org-Caldav-sync]] @@ -128,9 +128,6 @@ In order to have this config work on both my desktop with regular joe-schmoe mon #+end_src -#+RESULTS: -| (lambda (frame) (with-selected-frame frame (chris/set-font-faces))) | evil-init-esc | (closure (bootstrap-version t) (frame) (let ((old-frame (selected-frame)) (old-buffer (current-buffer))) (unwind-protect (progn (select-frame frame 'norecord) (setq doom-modeline-icon t)) (if (frame-live-p old-frame) (progn (select-frame old-frame 'norecord))) (if (buffer-live-p old-buffer) (progn (set-buffer old-buffer)))))) | doom-modeline-refresh-font-width-cache | doom-modeline-set-selected-window | doom-modeline-set-char-widths | (closure (t) (frame) (let ((old-frame (selected-frame)) (old-buffer (current-buffer))) (unwind-protect (progn (select-frame frame 'norecord) (chris/set-font-faces)) (if (frame-live-p old-frame) (progn (select-frame old-frame 'norecord))) (if (buffer-live-p old-buffer) (progn (set-buffer old-buffer)))))) | select-frame | aw--after-make-frame | - Then let's make sure line-numbers are relative and on. And let's turn on visual-line-mode globally. #+begin_src emacs-lisp (setq display-line-numbers-type 'relative) @@ -281,7 +278,7 @@ Let's make parens and other delimiters easier to tell apart by making nested one (use-package aggressive-indent :defer 1 :config - (global-aggressive-indent-mode +1)) + (aggressive-indent-mode -1)) #+end_src #+begin_src emacs-lisp @@ -393,6 +390,7 @@ This evil-collection package includes a lot of other evil based things. "f" '(:ignore t :which-key "file") "w" '(:ignore t :which-key "window") "s" '(:ignore t :which-key "search") + "i" '(:ignore t :which-key "insert") "o" '(:ignore t :which-key "open") "oa" '(:ignore t :which-key "org agenda") "of" '(:ignore t :which-key "elfeed") @@ -462,6 +460,551 @@ This evil-collection package includes a lot of other evil based things. (global-evil-surround-mode +1)) #+end_src +** Org Mode +Org-Mode needs to be loaded pretty high in the file so that we are ensuring things get picked up in the correct order. This has been a problem for me in the past so I prefer it right after setting some keybindings and then much later loading things like =roam= =super-agenda= and others. + +Let's start by creating a self contained function of what I'd like started on every org buffer. +#+begin_src emacs-lisp +(defun chris/org-mode-setup () + (interactive) + (org-indent-mode +1) + (toc-org-mode +1) + (visual-fill-column-mode +1) + (display-line-numbers-mode -1) + (variable-pitch-mode +1) + (flyspell-mode +1) + (setq visual-fill-column-width 100 + visual-fill-column-center-text t) + + ;;Let's make sure org-mode faces are inheriting fixed pitch faces. + (dolist (face '(org-block + org-block-begin-line + org-block-end-line + org-code + org-document-info-keyword + org-meta-line + org-table + org-date + org-verbatim)) + (set-face-attribute `,face nil :inherit 'fixed-pitch)) + + (set-face-attribute 'org-block-end-line nil :inherit 'org-block-begin-line) + (set-face-attribute 'org-quote nil :background "#242631" :inherit 'fixed-pitch)) + +(defun chris/org-agenda-setup () + (interactive) + (org-indent-mode +1) + (toc-org-mode +1) + (visual-fill-column-mode +1) + (display-line-numbers-mode -1) + (variable-pitch-mode -1) + (toggle-truncate-lines +1) + (setq visual-fill-column-width 120 + visual-fill-column-center-text t)) +#+end_src + +This is the use-package definition with a lot of customization. Need to setup auto tangle and make sure I have some structure templates for org-mode. + +Part of this config includes some special capture templates for my work as a youth minister. I create lessons through both org-mode and org-roam capture templates. The first part comes from org-roam, then the next is org-mode. +#+begin_src emacs-lisp +(use-package org + :straight t + :defer 1 + :config + (setq org-startup-indented t + org-edit-src-content-indentation 0 + org-agenda-sticky t + org-fontify-quote-and-verse-blocks t + org-src-preserve-indentation t + org-src-window-setup 'other-window + org-agenda-current-time-string "now >>>>>>>>>>>>>") + + (add-hook 'org-mode-hook 'chris/org-mode-setup) + + (org-babel-do-load-languages 'org-babel-load-languages + '((emacs-lisp . t) + (python . t) + (ditaa . t) + (shell . t) + (restclient . t))) + + (setq org-ditaa-jar-path "/usr/bin/ditaa") + + (require 'org-tempo) + (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) + (add-to-list 'org-structure-template-alist '("cl" . "src common-lisp")) + (add-to-list 'org-structure-template-alist '("py" . "src python")) + (add-to-list 'org-structure-template-alist '("sh" . "src shell")) + (add-to-list 'org-structure-template-alist '("yaml" . "src yaml")) + (add-to-list 'org-structure-template-alist '("yml" . "src yaml")) + (add-to-list 'org-structure-template-alist '("q" . "quote")) + (add-to-list 'org-structure-template-alist '("rc" . "src restclient")) + + (setq org-capture-templates + '(("t" "Personal todo" entry + (file "todo/todo.org") + (file ".templates/tasks.org") :prepend t) + ("n" "Personal notes" entry + (file "todo/notes.org") + "* %u %?\n%i\n%a" :prepend t) + ("j" "Journal" entry + (file+olp+datetree +org-capture-journal-file) + "* %U %?\n%i\n%a" :prepend t) + ("p" "TFC Plan" entry + (function chris/org-roam-capture-lesson-file) + (file ".templates/tfcplantemplate.org") + :prepend nil + :jump-to-captured t + :empty-lines 1) + ("P" "TFC Posts" entry + (file+headline "nvtfc_social_media.org" "Posts") + (file ".templates/posts.org") + :prepend t + :jump-to-captured t) + ("r" "Templates for projects") + ("rt" "Project-local todo" entry + (file+headline chris/project-todo "Inbox") + "* TODO %?\n%a\n%i\n\n" :prepend t) + ("rn" "Project-local notes" entry + (file+headline chris/project-todo "Notes") + "* %U %?\n%a\n%i\n\n" :prepend t) + ("rc" "Project-local changelog" entry + (file+headline chris/project-changelog "Changelog") + "* %U %?\n%a\n%i\n\n" :prepend t)) + org-capture-use-agenda-date t + org-agenda-timegrid-use-ampm t + org-agenda-show-inherited-tags nil + org-agenda-tags-column -100) + + (setq org-agenda-prefix-format '((agenda . " %i %?-12t% s") + (todo . " %i %-12:c") + (tags . " %i %-12:c") + (search . " %i %-12:c"))) + + (setq org-agenda-category-icon-alist + '(("todo" "~/org/icons/task.png" nil nil :ascent center) + ("lesson" "~/org/icons/book.png" nil nil :ascent center) + ("dev" "~/org/icons/coding.png" nil nil :ascent center) + ("TODO" "~/org/icons/coding.png" nil nil :ascent center))) + + (setq org-imenu-depth 4 + org-odt-styles-file "/home/chris/org/style.odt" + org-export-with-toc nil + org-export-with-author nil + org-todo-keywords + '((sequence "TODO(t)" "PROJ(p)" "STRT(s)" "WAIT(w)" "HOLD(h)" "|" "DONE(d)" "CNCL(c)") + (sequence "[ ](T)" "[-](S)" "[?](W)" "|" "[X](D)")) + org-agenda-files + '("/home/chris/org/todo/inbox.org" + "/home/chris/org/todo/notes.org" + "/home/chris/org/repetition.org" + "/home/chris/org/tfc_plans.org" + "/home/chris/org/ministry_team.org" + "/home/chris/org/todo/todo.org" + "/home/chris/org/newsletter.org" + "/home/chris/org/archive.org" + "/home/chris/org/nvtfc_social_media.org" + "/home/chris/dev/church-presenter/TODO.org" + "/home/chris/org/lessons/") + org-id-method 'ts + org-agenda-tags-column -75) + + (defun chris/org-columns-view () + "Turn on org-columns overlay and turn off olivetti-mode" + (interactive) + (goto-char (point-min)) + (org-content) + (org-columns) + (setq visual-fill-column-width 150)) + + (defun chris/org-columns-quit () + "Remove the org-columns overlay and turn on olivetti-mode" + (interactive) + (org-columns-quit) + (chris/org-mode-setup) + (setq visual-fill-column-width 100) + (setq visual-fill-column-width 100)) + + ;; (add-hook 'org-agenda-finalize-hook 'evil-normal-state) + (add-hook 'org-agenda-finalize-hook 'chris/org-agenda-setup) + + (advice-add 'org-agenda-todo :after #'org-save-all-org-buffers) + + (setq org-refile-targets '((org-agenda-files . (:maxlevel . 6)))) + + (setq org-agenda-window-setup 'current-window) + + (defun chris/org-agenda () + "create a window that houses my org-agenda" + (interactive) + (with-selected-frame (make-frame + '((name . "org-agenda") + (width . 100))) + (org-agenda-list))) + + (setq org-latex-packages-alist '(("margin=2cm" "geometry" nil))) + + :general + (chris/leader-keys + :states 'normal + :keymaps 'override + "c" 'org-capture + "rr" 'org-refile + "e" 'org-export-dispatch + "oa" 'org-agenda-list) + ('normal org-agenda-mode-map + "q" 'org-agenda-quit + "r" 'org-agenda-redo + "d" 'org-agenda-deadline + "s" 'org-agenda-schedule + "t" 'org-agenda-todo + "c" 'org-agenda-capture) + ('normal org-columns-map + "j" 'outline-next-heading + "h" 'outline-previous-heading + "q" 'chris/org-columns-quit) + ('normal org-mode-map + "RET" 'chris/org-dwim-at-point + "gC" 'chris/org-columns-view + "ge" 'org-edit-src-code + "gr" 'revert-buffer + "S" 'org-schedule + "t" 'org-todo) + ('insert org-mode-map + "C-i" 'completion-at-point) + ('normal 'org-src-mode-map + "q" 'org-edit-src-abort)) +#+end_src + +We need to create a lesson capture function to find our lesson files differently each time we run our TFC plan capture. This is the most unique part of my capture template. This function uses =org-roam-find-file= to pick the lesson file that I need to add my lesson plan to. This way the lesson itself is created before the plan. +#+begin_src emacs-lisp +(defun chris/org-roam-capture-lesson-file () + "Function to return the lesson file that is needed for TFC plan capture and move to correct position for plan insertion" + (interactive) + ;; (unless org-roam-mode (org-roam-mode +1)) + (let ((node (org-roam-node-read))) + (org-roam-node-visit node) + (goto-char (point-min)) + (search-forward "PLAN"))) +#+end_src + +#+begin_src emacs-lisp +(defun chris/project-todo () + (concat (projectile-project-root) "TODO.org")) +(defun chris/project-changelog () + (concat (projectile-project-root) "CHANGELOG.org")) +#+end_src + +We are also going to make our config auto-tangle. This is so helpful on saving the .org file tangles out the config automatically. +#+begin_src emacs-lisp +(defun chris/org-babel-tangle-config () + (when (string-equal (buffer-file-name) + (expand-file-name "README.org" user-emacs-directory)) + (let ((org-confirm-babel-evaluate nil)) + (org-babel-tangle)))) + +(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'chris/org-babel-tangle-config + :append :local))) +#+end_src + +We also need to add =evil-org= to make better keybindings. +#+begin_src emacs-lisp +(use-package evil-org + :ensure t + :after org + :hook (org-mode . (lambda () evil-org-mode)) + :config + ;; (add-to-list 'evil-digit-bound-motions 'evil-org-beginning-of-line) + ;; (evil-define-key 'motion 'evil-org-mode + ;; (kbd "0") 'evil-org-beginning-of-line) + (require 'evil-org-agenda) + (evil-org-agenda-set-keys)) +#+end_src + + +*** Org-Super-Agenda +Super Agenda gives me a really nice way of making the agenda view look a lot better with some better information included. +#+begin_src emacs-lisp +(use-package org-super-agenda + :after org + :init + (setq org-super-agenda-groups '((:name "📅 Today" + :time-grid t + :scheduled today) + (:name "Due Today" + :deadline today) + (:name "Important" + :priority "A") + (:name "Development" + :category "TODO" + :category "dev") + (:name "Overdue" + :time-grid t + :scheduled past + :deadline past) + (:name "Due soon" + :deadline future))) + :config + (org-super-agenda-mode +1) + (setq org-super-agenda-header-map nil)) +#+end_src + +*** Org-Roam +Here we are going to add org-roam. This is a note-takers paradise by adding an automatic backlinking function. + +Basic Org-Roam setup. We select the directory and the basic width of the Org-Roam buffer so that it doesn't take too much space on my laptop. We also want to exclude certain files from Org-Roam. All files are synced between machines using syncthing and kept in a version history. I'd like to exclude the version history from Org-Roam using =org-roam-file-exclude-regexp=. + +We also need to setup some capture templates to use some specific setups with my journalling. These include a space for my [[file:../../org/homework_for_life.org][Homework For Life]], tasks for the day, and how I can love on my family. +#+BEGIN_SRC emacs-lisp +(use-package org-roam + :after org + :ensure t + :init + (setq org-roam-v2-ack t) + :config + (setq org-roam-directory "~/org" + org-roam-buffer-width 0.25 + org-roam-file-exclude-regexp ".stversion.*\|.stfolder.*\|.*~.*\|.*sync.*" + org-roam-db-location "~/.dotemacs/org-roam.db" + org-roam-completion-everywhere t + org-roam-capture-templates + '(("d" "default" plain "%?" + :if-new (file+head "${slug}.org" + "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n\nj ") + :unnarrowed t) + ("b" "bible" plain "%?" + :if-new (file+head "${slug}.org" + "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n- tags %^G\n\n* %?") + :unnarrowed t) + ("l" "TFC Lesson" plain (file ".templates/lessontemplate.org") + :if-new (file+head "lessons/${slug}.org" + "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n") + :unnarrowed t)) + org-roam-dailies-capture-templates + '(("d" "daily" plain #'org-roam-capture--get-point "" + :immediate-finish t + :file-name "%<%Y-%m-%d>" + :head "#+TITLE: %<%Y-%m-%d>\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n\n* HFL\n* Tasks\n* Family\n** How Do I Love Abbie?") + ("b" "biblical daily" plain #'org-roam-capture--get-point "" + :immediate-finish t + :file-name "%<%Y-%m-%d>-bib" + :head "#+TITLE: %<%Y-%m-%d> - Biblical\n#+AUTHOR: Chris Cochrun"))) + (org-roam-setup) + :general + (chris/leader-keys + :states 'normal + :keymaps 'override + "nf" '(org-roam-node-find :which-key "org roam ff") + "nr" 'org-roam-buffer-toggle + "ni" 'org-roam-node-insert + "nc" 'org-roam-capture + "njt" 'org-roam-dailies-capture-today + "ng" 'org-roam-graph)) + +#+END_SRC + + +Org-Roam server. This let's me visualize my notes. +In order to use it, I need to go to http://localhost:8080 +#+BEGIN_SRC emacs-lisp +(use-package websocket) +(use-package org-roam-ui + :straight (:host github :repo "org-roam/org-roam-ui" :files ("*.el" "out")) + :after org-roam + :config + (setq org-roam-ui-sync-theme t + org-roam-ui-follow t + org-roam-ui-update-on-save t + org-roam-ui-open-on-start t)) + +#+END_SRC + +*** Org-Superstar +Org-Superstar makes the stars at the beginning of the line in =org-mode= a lot prettier. +#+begin_src emacs-lisp +(use-package org-superstar + :after org + :config + (org-superstar-mode +1) + (setq org-superstar-headline-bullets-list '("\u25c9" "\u25c8" "" "\u25ce" "\u272c" "\u25c7" "\u2749" "\u2719" "\u2756")) + (setq org-superstar-item-bullet-alist '((?- . ?\u25b8) + (?+ . ?\u2749) + (?* . ?\u25c9))) + (set-face-attribute 'org-superstar-item nil :inherit 'org-level-3) + (add-hook 'org-mode-hook 'org-superstar-mode)) +#+end_src + +*** Org Modern +#+BEGIN_SRC emacs-lisp :tangle no +(use-package org-modern + :straight (:host github :repo "minad/org-modern")) +#+END_SRC +*** Org DWIM +I've stolen most of this code from Doom Emacs but we want to create a dwim-at-point function for Org-Mode that will fit under the =RET= key. This allows us to do a bunch of different functions depending on the context of point. +#+begin_src emacs-lisp +(defun chris/org-dwim-at-point (&optional arg) + "Do-what-I-mean at point. + +If on a: +- checkbox list item or todo heading: toggle it. +- clock: update its time. +- headline: cycle ARCHIVE subtrees, toggle latex fragments and inline images in + subtree; update statistics cookies/checkboxes and ToCs. +- footnote reference: jump to the footnote's definition +- footnote definition: jump to the first reference of this footnote +- table-row or a TBLFM: recalculate the table's formulas +- table-cell: clear it and go into insert mode. If this is a formula cell, + recaluclate it instead. +- babel-call: execute the source block +- statistics-cookie: update it. +- latex fragment: toggle it. +- link: follow it +- otherwise, refresh all inline images in current tree." + (interactive "P") + (let* ((context (org-element-context)) + (type (org-element-type context))) + ;; skip over unimportant contexts + (while (and context (memq type '(verbatim code bold italic underline strike-through subscript superscript))) + (setq context (org-element-property :parent context) + type (org-element-type context))) + (pcase type + (`headline + (cond ((memq (bound-and-true-p org-goto-map) + (current-active-maps)) + (org-goto-ret)) + ((and (fboundp 'toc-org-insert-toc) + (member "TOC" (org-get-tags))) + (toc-org-insert-toc) + (message "Updating table of contents")) + ((string= "ARCHIVE" (car-safe (org-get-tags))) + (org-force-cycle-archived)) + ((or (org-element-property :todo-type context) + (org-element-property :scheduled context)) + (org-todo + (if (eq (org-element-property :todo-type context) 'done) + (or (car (chris/org-get-todo-keywords-for (org-element-property :todo-keyword context))) + 'todo) + 'done)))) + ;; Update any metadata or inline previews in this subtree + (org-update-checkbox-count) + (org-update-parent-todo-statistics) + (when (and (fboundp 'toc-org-insert-toc) + (member "TOC" (org-get-tags))) + (toc-org-insert-toc) + (message "Updating table of contents")) + (let* ((beg (if (org-before-first-heading-p) + (line-beginning-position) + (save-excursion (org-back-to-heading) (point)))) + (end (if (org-before-first-heading-p) + (line-end-position) + (save-excursion (org-end-of-subtree) (point)))) + (overlays (ignore-errors (overlays-in beg end))) + (latex-overlays + (cl-find-if (lambda (o) (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay)) + overlays)) + (image-overlays + (cl-find-if (lambda (o) (overlay-get o 'org-image-overlay)) + overlays))) + (chris/org--toggle-inline-images-in-subtree beg end) + (if (or image-overlays latex-overlays) + (org-clear-latex-preview beg end) + (org--latex-preview-region beg end)))) + + (`clock (org-clock-update-time-maybe)) + + (`footnote-reference + (org-footnote-goto-definition (org-element-property :label context))) + + (`footnote-definition + (org-footnote-goto-previous-reference (org-element-property :label context))) + + ((or `planning `timestamp) + (org-follow-timestamp-link)) + + ((or `table `table-row) + (if (org-at-TBLFM-p) + (org-table-calc-current-TBLFM) + (ignore-errors + (save-excursion + (goto-char (org-element-property :contents-begin context)) + (org-call-with-arg 'org-table-recalculate (or arg t)))))) + + (`table-cell + (org-table-blank-field) + (org-table-recalculate arg) + (when (and (string-empty-p (string-trim (org-table-get-field))) + (bound-and-true-p evil-local-mode)) + (evil-change-state 'insert))) + + (`babel-call + (org-babel-lob-execute-maybe)) + + (`statistics-cookie + (save-excursion (org-update-statistics-cookies arg))) + + ((or `src-block `inline-src-block) + (org-babel-execute-src-block)) + + ((or `latex-fragment `latex-environment) + (org-latex-preview)) + + (`link + (let* ((lineage (org-element-lineage context '(link) t)) + (path (org-element-property :path lineage))) + (if (or (equal (org-element-property :type lineage) "img") + (and path (image-type-from-file-name path))) + (chris/org--toggle-inline-images-in-subtree + (org-element-property :begin lineage) + (org-element-property :end lineage)) + (org-open-at-point arg)))) + + (`paragraph + (let ((match (and (org-at-item-checkbox-p) (match-string 1)))) + (org-toggle-checkbox))) + + (_ + (if (or (org-in-regexp org-ts-regexp-both nil t) + (org-in-regexp org-tsr-regexp-both nil t) + (org-in-regexp org-link-any-re nil t)) + (call-interactively #'org-open-at-point) + (chris/org--toggle-inline-images-in-subtree + (org-element-property :begin context) + (org-element-property :end context))))))) + + +(defun chris/org-get-todo-keywords-for (&optional keyword) + "Returns the list of todo keywords that KEYWORD belongs to." + (when keyword + (cl-loop for (type . keyword-spec) + in (cl-remove-if-not #'listp org-todo-keywords) + for keywords = + (mapcar (lambda (x) (if (string-match "^\\([^(]+\\)(" x) + (match-string 1 x) + x)) + keyword-spec) + if (eq type 'sequence) + if (member keyword keywords) + return keywords))) + +(defun chris/org--toggle-inline-images-in-subtree (&optional beg end refresh) + "Refresh inline image previews in the current heading/tree." + (let ((beg (or beg + (if (org-before-first-heading-p) + (line-beginning-position) + (save-excursion (org-back-to-heading) (point))))) + (end (or end + (if (org-before-first-heading-p) + (line-end-position) + (save-excursion (org-end-of-subtree) (point))))) + (overlays (cl-remove-if-not (lambda (ov) (overlay-get ov 'org-image-overlay)) + (ignore-errors (overlays-in beg end))))) + (dolist (ov overlays nil) + (delete-overlay ov) + (setq org-inline-image-overlays (delete ov org-inline-image-overlays))) + (when (or refresh (not overlays)) + (org-display-inline-images t t beg end) + t))) +#+end_src ** Emoji In order to render color emojis I'll use =unicode-fonts=. #+begin_src emacs-lisp @@ -482,7 +1025,7 @@ Or maybe I'll use =emojify=. (chris/leader-keys :states 'normal :keymaps 'override - "se" '(emojify-insert-emoji :which-key "insert emoji"))) + "ie" '(emojify-insert-emoji :which-key "insert emoji"))) #+end_src ** Undo-Tree @@ -1531,549 +2074,6 @@ Ledger mode (use-package ledger-mode) #+end_src -** Org Mode -Let's start by creating a self contained function of what I'd like started on every org buffer. -#+begin_src emacs-lisp -(defun chris/org-mode-setup () - (interactive) - (org-indent-mode +1) - (toc-org-mode +1) - (visual-fill-column-mode +1) - (display-line-numbers-mode -1) - (variable-pitch-mode +1) - (setq visual-fill-column-width 100 - visual-fill-column-center-text t) - - ;;Let's make sure org-mode faces are inheriting fixed pitch faces. - (dolist (face '(org-block - org-block-begin-line - org-block-end-line - org-code - org-document-info-keyword - org-meta-line - org-table - org-date - org-verbatim)) - (set-face-attribute `,face nil :inherit 'fixed-pitch)) - - (set-face-attribute 'org-block-end-line nil :inherit 'org-block-begin-line) - (set-face-attribute 'org-quote nil :background "#242631" :inherit 'fixed-pitch)) - -(defun chris/org-agenda-setup () - (interactive) - (org-indent-mode +1) - (toc-org-mode +1) - (visual-fill-column-mode +1) - (display-line-numbers-mode -1) - (variable-pitch-mode -1) - (toggle-truncate-lines +1) - (setq visual-fill-column-width 120 - visual-fill-column-center-text t)) -#+end_src - -This is the use-package definition with a lot of customization. Need to setup auto tangle and make sure I have some structure templates for org-mode. - -Part of this config includes some special capture templates for my work as a youth minister. I create lessons through both org-mode and org-roam capture templates. The first part comes from org-roam, then the next is org-mode. -#+begin_src emacs-lisp -(use-package org - :straight t - :defer 1 - :config - (setq org-startup-indented t - org-edit-src-content-indentation 0 - org-agenda-sticky t - org-fontify-quote-and-verse-blocks t - org-src-preserve-indentation t - org-src-window-setup 'other-window - org-agenda-current-time-string "now >>>>>>>>>>>>>") - - (add-hook 'org-mode-hook 'chris/org-mode-setup) - - (org-babel-do-load-languages 'org-babel-load-languages - '((emacs-lisp . t) - (python . t) - (ditaa . t) - (shell . t) - (restclient . t))) - - (setq org-ditaa-jar-path "/usr/bin/ditaa") - - (require 'org-tempo) - (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) - (add-to-list 'org-structure-template-alist '("cl" . "src common-lisp")) - (add-to-list 'org-structure-template-alist '("py" . "src python")) - (add-to-list 'org-structure-template-alist '("sh" . "src shell")) - (add-to-list 'org-structure-template-alist '("yaml" . "src yaml")) - (add-to-list 'org-structure-template-alist '("yml" . "src yaml")) - (add-to-list 'org-structure-template-alist '("q" . "quote")) - (add-to-list 'org-structure-template-alist '("rc" . "src restclient")) - - (setq org-capture-templates - '(("t" "Personal todo" entry - (file "todo/todo.org") - (file ".templates/tasks.org") :prepend t) - ("n" "Personal notes" entry - (file "todo/notes.org") - "* %u %?\n%i\n%a" :prepend t) - ("j" "Journal" entry - (file+olp+datetree +org-capture-journal-file) - "* %U %?\n%i\n%a" :prepend t) - ("p" "TFC Plan" entry - (function chris/org-roam-capture-lesson-file) - (file ".templates/tfcplantemplate.org") - :prepend nil - :jump-to-captured t - :empty-lines 1) - ("P" "TFC Posts" entry - (file+headline "nvtfc_social_media.org" "Posts") - (file ".templates/posts.org") - :prepend t - :jump-to-captured t) - ("r" "Templates for projects") - ("rt" "Project-local todo" entry - (file+headline chris/project-todo "Inbox") - "* TODO %?\n%a\n%i\n\n" :prepend t) - ("rn" "Project-local notes" entry - (file+headline chris/project-todo "Notes") - "* %U %?\n%a\n%i\n\n" :prepend t) - ("rc" "Project-local changelog" entry - (file+headline chris/project-changelog "Changelog") - "* %U %?\n%a\n%i\n\n" :prepend t)) - org-capture-use-agenda-date t - org-agenda-timegrid-use-ampm t - org-agenda-show-inherited-tags nil - org-agenda-tags-column -100) - - (setq org-agenda-prefix-format '((agenda . " %i %?-12t% s") - (todo . " %i %-12:c") - (tags . " %i %-12:c") - (search . " %i %-12:c"))) - - (setq org-agenda-category-icon-alist - '(("todo" "~/org/icons/task.png" nil nil :ascent center) - ("lesson" "~/org/icons/book.png" nil nil :ascent center) - ("dev" "~/org/icons/coding.png" nil nil :ascent center) - ("TODO" "~/org/icons/coding.png" nil nil :ascent center))) - - (setq org-imenu-depth 4 - org-odt-styles-file "/home/chris/org/style.odt" - org-export-with-toc nil - org-export-with-author nil - org-todo-keywords - '((sequence "TODO(t)" "PROJ(p)" "STRT(s)" "WAIT(w)" "HOLD(h)" "|" "DONE(d)" "CNCL(c)") - (sequence "[ ](T)" "[-](S)" "[?](W)" "|" "[X](D)")) - org-agenda-files - '("/home/chris/org/todo/inbox.org" - "/home/chris/org/todo/notes.org" - "/home/chris/org/repetition.org" - "/home/chris/org/tfc_plans.org" - "/home/chris/org/ministry_team.org" - "/home/chris/org/todo/todo.org" - "/home/chris/org/newsletter.org" - "/home/chris/org/archive.org" - "/home/chris/org/nvtfc_social_media.org" - "/home/chris/dev/church-presenter/TODO.org" - "/home/chris/org/lessons/") - org-id-method 'ts - org-agenda-tags-column -75) - - (defun chris/org-columns-view () - "Turn on org-columns overlay and turn off olivetti-mode" - (interactive) - (goto-char (point-min)) - (org-content) - (org-columns) - (setq visual-fill-column-width 150)) - - (defun chris/org-columns-quit () - "Remove the org-columns overlay and turn on olivetti-mode" - (interactive) - (org-columns-quit) - (chris/org-mode-setup) - (setq visual-fill-column-width 100) - (setq visual-fill-column-width 100)) - - (add-hook 'org-agenda-finalize-hook 'evil-normal-state) - (add-hook 'org-agenda-finalize-hook 'chris/org-agenda-setup) - - (advice-add 'org-agenda-todo :after #'org-save-all-org-buffers) - - (setq org-refile-targets '((org-agenda-files . (:maxlevel . 6)))) - - (setq org-agenda-window-setup 'current-window) - - (defun chris/org-agenda () - "create a window that houses my org-agenda" - (interactive) - (with-selected-frame (make-frame - '((name . "org-agenda") - (width . 100))) - (org-agenda-list))) - - (setq org-latex-packages-alist '(("margin=2cm" "geometry" nil))) - - :general - (chris/leader-keys - :states 'normal - :keymaps 'override - "c" 'org-capture - "rr" 'org-refile - "e" 'org-export-dispatch - "oa" 'org-agenda-list) - ('normal org-agenda-mode-map - "q" 'org-agenda-quit - "r" 'org-agenda-redo - "d" 'org-agenda-deadline - "s" 'org-agenda-schedule - "t" 'org-agenda-todo - "c" 'org-agenda-capture) - ('normal org-columns-map - "j" 'outline-next-heading - "h" 'outline-previous-heading - "q" 'chris/org-columns-quit) - ('normal org-mode-map - "RET" 'chris/org-dwim-at-point - "gC" 'chris/org-columns-view - "ge" 'org-edit-src-code - "gr" 'revert-buffer - "S" 'org-schedule - "t" 'org-todo) - ('insert org-mode-map - "C-i" 'completion-at-point) - ('normal 'org-src-mode-map - "q" 'org-edit-src-abort)) -#+end_src - -We need to create a lesson capture function to find our lesson files differently each time we run our TFC plan capture. This is the most unique part of my capture template. This function uses =org-roam-find-file= to pick the lesson file that I need to add my lesson plan to. This way the lesson itself is created before the plan. -#+begin_src emacs-lisp -(defun chris/org-roam-capture-lesson-file () - "Function to return the lesson file that is needed for TFC plan capture and move to correct position for plan insertion" - (interactive) - ;; (unless org-roam-mode (org-roam-mode +1)) - (let ((node (org-roam-node-read))) - (org-roam-node-visit node) - (goto-char (point-min)) - (search-forward "PLAN"))) -#+end_src - -#+begin_src emacs-lisp -(defun chris/project-todo () - (concat (projectile-project-root) "TODO.org")) -(defun chris/project-changelog () - (concat (projectile-project-root) "CHANGELOG.org")) -#+end_src - -We are also going to make our config auto-tangle. This is so helpful on saving the .org file tangles out the config automatically. -#+begin_src emacs-lisp -(defun chris/org-babel-tangle-config () - (when (string-equal (buffer-file-name) - (expand-file-name "README.org" user-emacs-directory)) - (let ((org-confirm-babel-evaluate nil)) - (org-babel-tangle)))) - -(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'chris/org-babel-tangle-config - :append :local))) -#+end_src - - -We also need to add =evil-org= to make better keybindings. -#+begin_src emacs-lisp -(use-package evil-org - :ensure t - :after org - :hook (org-mode . (lambda () evil-org-mode)) - :config - (add-to-list 'evil-digit-bound-motions 'evil-org-beginning-of-line) - (evil-define-key 'motion 'evil-org-mode - (kbd "0") 'evil-org-beginning-of-line) - (require 'evil-org-agenda) - (evil-org-agenda-set-keys)) -#+end_src - - -*** Org-Super-Agenda -Super Agenda gives me a really nice way of making the agenda view look a lot better with some better information included. -#+begin_src emacs-lisp -(use-package org-super-agenda - :after org - :init - (setq org-super-agenda-groups '((:name "📅 Today" - :time-grid t - :scheduled today) - (:name "Due Today" - :deadline today) - (:name "Important" - :priority "A") - (:name "Development" - :category "TODO" - :category "dev") - (:name "Overdue" - :time-grid t - :scheduled past - :deadline past) - (:name "Due soon" - :deadline future))) - :config - (org-super-agenda-mode +1) - (setq org-super-agenda-header-map nil)) -#+end_src - -*** Org-Roam -Here we are going to add org-roam. This is a note-takers paradise by adding an automatic backlinking function. - -Basic Org-Roam setup. We select the directory and the basic width of the Org-Roam buffer so that it doesn't take too much space on my laptop. We also want to exclude certain files from Org-Roam. All files are synced between machines using syncthing and kept in a version history. I'd like to exclude the version history from Org-Roam using =org-roam-file-exclude-regexp=. - -We also need to setup some capture templates to use some specific setups with my journalling. These include a space for my [[file:../../org/homework_for_life.org][Homework For Life]], tasks for the day, and how I can love on my family. -#+BEGIN_SRC emacs-lisp -(use-package org-roam - :after org - :ensure t - :init - (setq org-roam-v2-ack t) - :config - (setq org-roam-directory "~/org" - org-roam-buffer-width 0.25 - org-roam-file-exclude-regexp ".stversion.*\|.stfolder.*\|.*~.*\|.*sync.*" - org-roam-db-location "~/.dotemacs/org-roam.db" - org-roam-completion-everywhere t - org-roam-capture-templates - '(("d" "default" plain "%?" - :if-new (file+head "${slug}.org" - "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n\nj ") - :unnarrowed t) - ("b" "bible" plain "%?" - :if-new (file+head "${slug}.org" - "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n- tags %^G\n\n* %?") - :unnarrowed t) - ("l" "TFC Lesson" plain (file ".templates/lessontemplate.org") - :if-new (file+head "lessons/${slug}.org" - "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n") - :unnarrowed t)) - org-roam-dailies-capture-templates - '(("d" "daily" plain #'org-roam-capture--get-point "" - :immediate-finish t - :file-name "%<%Y-%m-%d>" - :head "#+TITLE: %<%Y-%m-%d>\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n\n* HFL\n* Tasks\n* Family\n** How Do I Love Abbie?") - ("b" "biblical daily" plain #'org-roam-capture--get-point "" - :immediate-finish t - :file-name "%<%Y-%m-%d>-bib" - :head "#+TITLE: %<%Y-%m-%d> - Biblical\n#+AUTHOR: Chris Cochrun"))) - (org-roam-setup) - :general - (chris/leader-keys - :states 'normal - :keymaps 'override - "nf" '(org-roam-node-find :which-key "org roam ff") - "nr" 'org-roam-buffer-toggle - "ni" 'org-roam-node-insert - "nc" 'org-roam-capture - "njt" 'org-roam-dailies-capture-today - "ng" 'org-roam-graph)) - -#+END_SRC - - -Org-Roam server. This let's me visualize my notes. -In order to use it, I need to go to http://localhost:8080 -#+BEGIN_SRC emacs-lisp -(use-package websocket) -(use-package org-roam-ui - :straight (:host github :repo "org-roam/org-roam-ui" :files ("*.el" "out")) - :after org-roam - :config - (setq org-roam-ui-sync-theme t - org-roam-ui-follow t - org-roam-ui-update-on-save t - org-roam-ui-open-on-start t)) - -#+END_SRC - -*** Org-Superstar -Org-Superstar makes the stars at the beginning of the line in =org-mode= a lot prettier. -#+begin_src emacs-lisp -(use-package org-superstar - :after org - :config - (org-superstar-mode +1) - (setq org-superstar-headline-bullets-list '("\u25c9" "\u25c8" "" "\u25ce" "\u272c" "\u25c7" "\u2749" "\u2719" "\u2756")) - (setq org-superstar-item-bullet-alist '((?- . ?\u25b8) - (?+ . ?\u2749) - (?* . ?\u25c9))) - (set-face-attribute 'org-superstar-item nil :inherit 'org-level-3) - (add-hook 'org-mode-hook 'org-superstar-mode)) -#+end_src - -*** Org Modern -#+BEGIN_SRC emacs-lisp :tangle no -(use-package org-modern - :straight (:host github :repo "minad/org-modern")) -#+END_SRC -*** Org DWIM -I've stolen most of this code from Doom Emacs but we want to create a dwim-at-point function for Org-Mode that will fit under the =RET= key. This allows us to do a bunch of different functions depending on the context of point. -#+begin_src emacs-lisp -(defun chris/org-dwim-at-point (&optional arg) - "Do-what-I-mean at point. - -If on a: -- checkbox list item or todo heading: toggle it. -- clock: update its time. -- headline: cycle ARCHIVE subtrees, toggle latex fragments and inline images in - subtree; update statistics cookies/checkboxes and ToCs. -- footnote reference: jump to the footnote's definition -- footnote definition: jump to the first reference of this footnote -- table-row or a TBLFM: recalculate the table's formulas -- table-cell: clear it and go into insert mode. If this is a formula cell, - recaluclate it instead. -- babel-call: execute the source block -- statistics-cookie: update it. -- latex fragment: toggle it. -- link: follow it -- otherwise, refresh all inline images in current tree." - (interactive "P") - (let* ((context (org-element-context)) - (type (org-element-type context))) - ;; skip over unimportant contexts - (while (and context (memq type '(verbatim code bold italic underline strike-through subscript superscript))) - (setq context (org-element-property :parent context) - type (org-element-type context))) - (pcase type - (`headline - (cond ((memq (bound-and-true-p org-goto-map) - (current-active-maps)) - (org-goto-ret)) - ((and (fboundp 'toc-org-insert-toc) - (member "TOC" (org-get-tags))) - (toc-org-insert-toc) - (message "Updating table of contents")) - ((string= "ARCHIVE" (car-safe (org-get-tags))) - (org-force-cycle-archived)) - ((or (org-element-property :todo-type context) - (org-element-property :scheduled context)) - (org-todo - (if (eq (org-element-property :todo-type context) 'done) - (or (car (chris/org-get-todo-keywords-for (org-element-property :todo-keyword context))) - 'todo) - 'done)))) - ;; Update any metadata or inline previews in this subtree - (org-update-checkbox-count) - (org-update-parent-todo-statistics) - (when (and (fboundp 'toc-org-insert-toc) - (member "TOC" (org-get-tags))) - (toc-org-insert-toc) - (message "Updating table of contents")) - (let* ((beg (if (org-before-first-heading-p) - (line-beginning-position) - (save-excursion (org-back-to-heading) (point)))) - (end (if (org-before-first-heading-p) - (line-end-position) - (save-excursion (org-end-of-subtree) (point)))) - (overlays (ignore-errors (overlays-in beg end))) - (latex-overlays - (cl-find-if (lambda (o) (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay)) - overlays)) - (image-overlays - (cl-find-if (lambda (o) (overlay-get o 'org-image-overlay)) - overlays))) - (chris/org--toggle-inline-images-in-subtree beg end) - (if (or image-overlays latex-overlays) - (org-clear-latex-preview beg end) - (org--latex-preview-region beg end)))) - - (`clock (org-clock-update-time-maybe)) - - (`footnote-reference - (org-footnote-goto-definition (org-element-property :label context))) - - (`footnote-definition - (org-footnote-goto-previous-reference (org-element-property :label context))) - - ((or `planning `timestamp) - (org-follow-timestamp-link)) - - ((or `table `table-row) - (if (org-at-TBLFM-p) - (org-table-calc-current-TBLFM) - (ignore-errors - (save-excursion - (goto-char (org-element-property :contents-begin context)) - (org-call-with-arg 'org-table-recalculate (or arg t)))))) - - (`table-cell - (org-table-blank-field) - (org-table-recalculate arg) - (when (and (string-empty-p (string-trim (org-table-get-field))) - (bound-and-true-p evil-local-mode)) - (evil-change-state 'insert))) - - (`babel-call - (org-babel-lob-execute-maybe)) - - (`statistics-cookie - (save-excursion (org-update-statistics-cookies arg))) - - ((or `src-block `inline-src-block) - (org-babel-execute-src-block)) - - ((or `latex-fragment `latex-environment) - (org-latex-preview)) - - (`link - (let* ((lineage (org-element-lineage context '(link) t)) - (path (org-element-property :path lineage))) - (if (or (equal (org-element-property :type lineage) "img") - (and path (image-type-from-file-name path))) - (chris/org--toggle-inline-images-in-subtree - (org-element-property :begin lineage) - (org-element-property :end lineage)) - (org-open-at-point arg)))) - - (`paragraph - (let ((match (and (org-at-item-checkbox-p) (match-string 1)))) - (org-toggle-checkbox))) - - (_ - (if (or (org-in-regexp org-ts-regexp-both nil t) - (org-in-regexp org-tsr-regexp-both nil t) - (org-in-regexp org-link-any-re nil t)) - (call-interactively #'org-open-at-point) - (chris/org--toggle-inline-images-in-subtree - (org-element-property :begin context) - (org-element-property :end context))))))) - - -(defun chris/org-get-todo-keywords-for (&optional keyword) - "Returns the list of todo keywords that KEYWORD belongs to." - (when keyword - (cl-loop for (type . keyword-spec) - in (cl-remove-if-not #'listp org-todo-keywords) - for keywords = - (mapcar (lambda (x) (if (string-match "^\\([^(]+\\)(" x) - (match-string 1 x) - x)) - keyword-spec) - if (eq type 'sequence) - if (member keyword keywords) - return keywords))) - -(defun chris/org--toggle-inline-images-in-subtree (&optional beg end refresh) - "Refresh inline image previews in the current heading/tree." - (let ((beg (or beg - (if (org-before-first-heading-p) - (line-beginning-position) - (save-excursion (org-back-to-heading) (point))))) - (end (or end - (if (org-before-first-heading-p) - (line-end-position) - (save-excursion (org-end-of-subtree) (point))))) - (overlays (cl-remove-if-not (lambda (ov) (overlay-get ov 'org-image-overlay)) - (ignore-errors (overlays-in beg end))))) - (dolist (ov overlays nil) - (delete-overlay ov) - (setq org-inline-image-overlays (delete ov org-inline-image-overlays))) - (when (or refresh (not overlays)) - (org-display-inline-images t t beg end) - t))) -#+end_src ** MU4E #+begin_src emacs-lisp (use-package mu4e diff --git a/init.el b/init.el index 80817d5e..00286a04 100644 --- a/init.el +++ b/init.el @@ -134,7 +134,7 @@ (use-package aggressive-indent :defer 1 :config - (global-aggressive-indent-mode +1)) + (aggressive-indent-mode -1)) (use-package adaptive-wrap :defer t) @@ -224,6 +224,7 @@ "f" '(:ignore t :which-key "file") "w" '(:ignore t :which-key "window") "s" '(:ignore t :which-key "search") + "i" '(:ignore t :which-key "insert") "o" '(:ignore t :which-key "open") "oa" '(:ignore t :which-key "org agenda") "of" '(:ignore t :which-key "elfeed") @@ -288,6 +289,497 @@ :config (global-evil-surround-mode +1)) +(defun chris/org-mode-setup () + (interactive) + (org-indent-mode +1) + (toc-org-mode +1) + (visual-fill-column-mode +1) + (display-line-numbers-mode -1) + (variable-pitch-mode +1) + (flyspell-mode +1) + (setq visual-fill-column-width 100 + visual-fill-column-center-text t) + + ;;Let's make sure org-mode faces are inheriting fixed pitch faces. + (dolist (face '(org-block + org-block-begin-line + org-block-end-line + org-code + org-document-info-keyword + org-meta-line + org-table + org-date + org-verbatim)) + (set-face-attribute `,face nil :inherit 'fixed-pitch)) + + (set-face-attribute 'org-block-end-line nil :inherit 'org-block-begin-line) + (set-face-attribute 'org-quote nil :background "#242631" :inherit 'fixed-pitch)) + +(defun chris/org-agenda-setup () + (interactive) + (org-indent-mode +1) + (toc-org-mode +1) + (visual-fill-column-mode +1) + (display-line-numbers-mode -1) + (variable-pitch-mode -1) + (toggle-truncate-lines +1) + (setq visual-fill-column-width 120 + visual-fill-column-center-text t)) + +(use-package org + :straight t + :defer 1 + :config + (setq org-startup-indented t + org-edit-src-content-indentation 0 + org-agenda-sticky t + org-fontify-quote-and-verse-blocks t + org-src-preserve-indentation t + org-src-window-setup 'other-window + org-agenda-current-time-string "now >>>>>>>>>>>>>") + + (add-hook 'org-mode-hook 'chris/org-mode-setup) + + (org-babel-do-load-languages 'org-babel-load-languages + '((emacs-lisp . t) + (python . t) + (ditaa . t) + (shell . t) + (restclient . t))) + + (setq org-ditaa-jar-path "/usr/bin/ditaa") + + (require 'org-tempo) + (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) + (add-to-list 'org-structure-template-alist '("cl" . "src common-lisp")) + (add-to-list 'org-structure-template-alist '("py" . "src python")) + (add-to-list 'org-structure-template-alist '("sh" . "src shell")) + (add-to-list 'org-structure-template-alist '("yaml" . "src yaml")) + (add-to-list 'org-structure-template-alist '("yml" . "src yaml")) + (add-to-list 'org-structure-template-alist '("q" . "quote")) + (add-to-list 'org-structure-template-alist '("rc" . "src restclient")) + + (setq org-capture-templates + '(("t" "Personal todo" entry + (file "todo/todo.org") + (file ".templates/tasks.org") :prepend t) + ("n" "Personal notes" entry + (file "todo/notes.org") + "* %u %?\n%i\n%a" :prepend t) + ("j" "Journal" entry + (file+olp+datetree +org-capture-journal-file) + "* %U %?\n%i\n%a" :prepend t) + ("p" "TFC Plan" entry + (function chris/org-roam-capture-lesson-file) + (file ".templates/tfcplantemplate.org") + :prepend nil + :jump-to-captured t + :empty-lines 1) + ("P" "TFC Posts" entry + (file+headline "nvtfc_social_media.org" "Posts") + (file ".templates/posts.org") + :prepend t + :jump-to-captured t) + ("r" "Templates for projects") + ("rt" "Project-local todo" entry + (file+headline chris/project-todo "Inbox") + "* TODO %?\n%a\n%i\n\n" :prepend t) + ("rn" "Project-local notes" entry + (file+headline chris/project-todo "Notes") + "* %U %?\n%a\n%i\n\n" :prepend t) + ("rc" "Project-local changelog" entry + (file+headline chris/project-changelog "Changelog") + "* %U %?\n%a\n%i\n\n" :prepend t)) + org-capture-use-agenda-date t + org-agenda-timegrid-use-ampm t + org-agenda-show-inherited-tags nil + org-agenda-tags-column -100) + + (setq org-agenda-prefix-format '((agenda . " %i %?-12t% s") + (todo . " %i %-12:c") + (tags . " %i %-12:c") + (search . " %i %-12:c"))) + + (setq org-agenda-category-icon-alist + '(("todo" "~/org/icons/task.png" nil nil :ascent center) + ("lesson" "~/org/icons/book.png" nil nil :ascent center) + ("dev" "~/org/icons/coding.png" nil nil :ascent center) + ("TODO" "~/org/icons/coding.png" nil nil :ascent center))) + + (setq org-imenu-depth 4 + org-odt-styles-file "/home/chris/org/style.odt" + org-export-with-toc nil + org-export-with-author nil + org-todo-keywords + '((sequence "TODO(t)" "PROJ(p)" "STRT(s)" "WAIT(w)" "HOLD(h)" "|" "DONE(d)" "CNCL(c)") + (sequence "[ ](T)" "[-](S)" "[?](W)" "|" "[X](D)")) + org-agenda-files + '("/home/chris/org/todo/inbox.org" + "/home/chris/org/todo/notes.org" + "/home/chris/org/repetition.org" + "/home/chris/org/tfc_plans.org" + "/home/chris/org/ministry_team.org" + "/home/chris/org/todo/todo.org" + "/home/chris/org/newsletter.org" + "/home/chris/org/archive.org" + "/home/chris/org/nvtfc_social_media.org" + "/home/chris/dev/church-presenter/TODO.org" + "/home/chris/org/lessons/") + org-id-method 'ts + org-agenda-tags-column -75) + + (defun chris/org-columns-view () + "Turn on org-columns overlay and turn off olivetti-mode" + (interactive) + (goto-char (point-min)) + (org-content) + (org-columns) + (setq visual-fill-column-width 150)) + + (defun chris/org-columns-quit () + "Remove the org-columns overlay and turn on olivetti-mode" + (interactive) + (org-columns-quit) + (chris/org-mode-setup) + (setq visual-fill-column-width 100) + (setq visual-fill-column-width 100)) + + ;; (add-hook 'org-agenda-finalize-hook 'evil-normal-state) + (add-hook 'org-agenda-finalize-hook 'chris/org-agenda-setup) + + (advice-add 'org-agenda-todo :after #'org-save-all-org-buffers) + + (setq org-refile-targets '((org-agenda-files . (:maxlevel . 6)))) + + (setq org-agenda-window-setup 'current-window) + + (defun chris/org-agenda () + "create a window that houses my org-agenda" + (interactive) + (with-selected-frame (make-frame + '((name . "org-agenda") + (width . 100))) + (org-agenda-list))) + + (setq org-latex-packages-alist '(("margin=2cm" "geometry" nil))) + + :general + (chris/leader-keys + :states 'normal + :keymaps 'override + "c" 'org-capture + "rr" 'org-refile + "e" 'org-export-dispatch + "oa" 'org-agenda-list) + ('normal org-agenda-mode-map + "q" 'org-agenda-quit + "r" 'org-agenda-redo + "d" 'org-agenda-deadline + "s" 'org-agenda-schedule + "t" 'org-agenda-todo + "c" 'org-agenda-capture) + ('normal org-columns-map + "j" 'outline-next-heading + "h" 'outline-previous-heading + "q" 'chris/org-columns-quit) + ('normal org-mode-map + "RET" 'chris/org-dwim-at-point + "gC" 'chris/org-columns-view + "ge" 'org-edit-src-code + "gr" 'revert-buffer + "S" 'org-schedule + "t" 'org-todo) + ('insert org-mode-map + "C-i" 'completion-at-point) + ('normal 'org-src-mode-map + "q" 'org-edit-src-abort)) + +(defun chris/org-roam-capture-lesson-file () + "Function to return the lesson file that is needed for TFC plan capture and move to correct position for plan insertion" + (interactive) + ;; (unless org-roam-mode (org-roam-mode +1)) + (let ((node (org-roam-node-read))) + (org-roam-node-visit node) + (goto-char (point-min)) + (search-forward "PLAN"))) + +(defun chris/project-todo () + (concat (projectile-project-root) "TODO.org")) +(defun chris/project-changelog () + (concat (projectile-project-root) "CHANGELOG.org")) + +(defun chris/org-babel-tangle-config () + (when (string-equal (buffer-file-name) + (expand-file-name "README.org" user-emacs-directory)) + (let ((org-confirm-babel-evaluate nil)) + (org-babel-tangle)))) + +(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'chris/org-babel-tangle-config + :append :local))) + +(use-package evil-org + :ensure t + :after org + :hook (org-mode . (lambda () evil-org-mode)) + :config + ;; (add-to-list 'evil-digit-bound-motions 'evil-org-beginning-of-line) + ;; (evil-define-key 'motion 'evil-org-mode + ;; (kbd "0") 'evil-org-beginning-of-line) + (require 'evil-org-agenda) + (evil-org-agenda-set-keys)) + +(use-package org-super-agenda + :after org + :init + (setq org-super-agenda-groups '((:name "📅 Today" + :time-grid t + :scheduled today) + (:name "Due Today" + :deadline today) + (:name "Important" + :priority "A") + (:name "Development" + :category "TODO" + :category "dev") + (:name "Overdue" + :time-grid t + :scheduled past + :deadline past) + (:name "Due soon" + :deadline future))) + :config + (org-super-agenda-mode +1) + (setq org-super-agenda-header-map nil)) + +(use-package org-roam + :after org + :ensure t + :init + (setq org-roam-v2-ack t) + :config + (setq org-roam-directory "~/org" + org-roam-buffer-width 0.25 + org-roam-file-exclude-regexp ".stversion.*\|.stfolder.*\|.*~.*\|.*sync.*" + org-roam-db-location "~/.dotemacs/org-roam.db" + org-roam-completion-everywhere t + org-roam-capture-templates + '(("d" "default" plain "%?" + :if-new (file+head "${slug}.org" + "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n\nj ") + :unnarrowed t) + ("b" "bible" plain "%?" + :if-new (file+head "${slug}.org" + "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n- tags %^G\n\n* %?") + :unnarrowed t) + ("l" "TFC Lesson" plain (file ".templates/lessontemplate.org") + :if-new (file+head "lessons/${slug}.org" + "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n") + :unnarrowed t)) + org-roam-dailies-capture-templates + '(("d" "daily" plain #'org-roam-capture--get-point "" + :immediate-finish t + :file-name "%<%Y-%m-%d>" + :head "#+TITLE: %<%Y-%m-%d>\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n\n* HFL\n* Tasks\n* Family\n** How Do I Love Abbie?") + ("b" "biblical daily" plain #'org-roam-capture--get-point "" + :immediate-finish t + :file-name "%<%Y-%m-%d>-bib" + :head "#+TITLE: %<%Y-%m-%d> - Biblical\n#+AUTHOR: Chris Cochrun"))) + (org-roam-setup) + :general + (chris/leader-keys + :states 'normal + :keymaps 'override + "nf" '(org-roam-node-find :which-key "org roam ff") + "nr" 'org-roam-buffer-toggle + "ni" 'org-roam-node-insert + "nc" 'org-roam-capture + "njt" 'org-roam-dailies-capture-today + "ng" 'org-roam-graph)) + +(use-package websocket) +(use-package org-roam-ui + :straight (:host github :repo "org-roam/org-roam-ui" :files ("*.el" "out")) + :after org-roam + :config + (setq org-roam-ui-sync-theme t + org-roam-ui-follow t + org-roam-ui-update-on-save t + org-roam-ui-open-on-start t)) + +(use-package org-superstar + :after org + :config + (org-superstar-mode +1) + (setq org-superstar-headline-bullets-list '("\u25c9" "\u25c8" "" "\u25ce" "\u272c" "\u25c7" "\u2749" "\u2719" "\u2756")) + (setq org-superstar-item-bullet-alist '((?- . ?\u25b8) + (?+ . ?\u2749) + (?* . ?\u25c9))) + (set-face-attribute 'org-superstar-item nil :inherit 'org-level-3) + (add-hook 'org-mode-hook 'org-superstar-mode)) + +(defun chris/org-dwim-at-point (&optional arg) + "Do-what-I-mean at point. + +If on a: +- checkbox list item or todo heading: toggle it. +- clock: update its time. +- headline: cycle ARCHIVE subtrees, toggle latex fragments and inline images in + subtree; update statistics cookies/checkboxes and ToCs. +- footnote reference: jump to the footnote's definition +- footnote definition: jump to the first reference of this footnote +- table-row or a TBLFM: recalculate the table's formulas +- table-cell: clear it and go into insert mode. If this is a formula cell, + recaluclate it instead. +- babel-call: execute the source block +- statistics-cookie: update it. +- latex fragment: toggle it. +- link: follow it +- otherwise, refresh all inline images in current tree." + (interactive "P") + (let* ((context (org-element-context)) + (type (org-element-type context))) + ;; skip over unimportant contexts + (while (and context (memq type '(verbatim code bold italic underline strike-through subscript superscript))) + (setq context (org-element-property :parent context) + type (org-element-type context))) + (pcase type + (`headline + (cond ((memq (bound-and-true-p org-goto-map) + (current-active-maps)) + (org-goto-ret)) + ((and (fboundp 'toc-org-insert-toc) + (member "TOC" (org-get-tags))) + (toc-org-insert-toc) + (message "Updating table of contents")) + ((string= "ARCHIVE" (car-safe (org-get-tags))) + (org-force-cycle-archived)) + ((or (org-element-property :todo-type context) + (org-element-property :scheduled context)) + (org-todo + (if (eq (org-element-property :todo-type context) 'done) + (or (car (chris/org-get-todo-keywords-for (org-element-property :todo-keyword context))) + 'todo) + 'done)))) + ;; Update any metadata or inline previews in this subtree + (org-update-checkbox-count) + (org-update-parent-todo-statistics) + (when (and (fboundp 'toc-org-insert-toc) + (member "TOC" (org-get-tags))) + (toc-org-insert-toc) + (message "Updating table of contents")) + (let* ((beg (if (org-before-first-heading-p) + (line-beginning-position) + (save-excursion (org-back-to-heading) (point)))) + (end (if (org-before-first-heading-p) + (line-end-position) + (save-excursion (org-end-of-subtree) (point)))) + (overlays (ignore-errors (overlays-in beg end))) + (latex-overlays + (cl-find-if (lambda (o) (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay)) + overlays)) + (image-overlays + (cl-find-if (lambda (o) (overlay-get o 'org-image-overlay)) + overlays))) + (chris/org--toggle-inline-images-in-subtree beg end) + (if (or image-overlays latex-overlays) + (org-clear-latex-preview beg end) + (org--latex-preview-region beg end)))) + + (`clock (org-clock-update-time-maybe)) + + (`footnote-reference + (org-footnote-goto-definition (org-element-property :label context))) + + (`footnote-definition + (org-footnote-goto-previous-reference (org-element-property :label context))) + + ((or `planning `timestamp) + (org-follow-timestamp-link)) + + ((or `table `table-row) + (if (org-at-TBLFM-p) + (org-table-calc-current-TBLFM) + (ignore-errors + (save-excursion + (goto-char (org-element-property :contents-begin context)) + (org-call-with-arg 'org-table-recalculate (or arg t)))))) + + (`table-cell + (org-table-blank-field) + (org-table-recalculate arg) + (when (and (string-empty-p (string-trim (org-table-get-field))) + (bound-and-true-p evil-local-mode)) + (evil-change-state 'insert))) + + (`babel-call + (org-babel-lob-execute-maybe)) + + (`statistics-cookie + (save-excursion (org-update-statistics-cookies arg))) + + ((or `src-block `inline-src-block) + (org-babel-execute-src-block)) + + ((or `latex-fragment `latex-environment) + (org-latex-preview)) + + (`link + (let* ((lineage (org-element-lineage context '(link) t)) + (path (org-element-property :path lineage))) + (if (or (equal (org-element-property :type lineage) "img") + (and path (image-type-from-file-name path))) + (chris/org--toggle-inline-images-in-subtree + (org-element-property :begin lineage) + (org-element-property :end lineage)) + (org-open-at-point arg)))) + + (`paragraph + (let ((match (and (org-at-item-checkbox-p) (match-string 1)))) + (org-toggle-checkbox))) + + (_ + (if (or (org-in-regexp org-ts-regexp-both nil t) + (org-in-regexp org-tsr-regexp-both nil t) + (org-in-regexp org-link-any-re nil t)) + (call-interactively #'org-open-at-point) + (chris/org--toggle-inline-images-in-subtree + (org-element-property :begin context) + (org-element-property :end context))))))) + + +(defun chris/org-get-todo-keywords-for (&optional keyword) + "Returns the list of todo keywords that KEYWORD belongs to." + (when keyword + (cl-loop for (type . keyword-spec) + in (cl-remove-if-not #'listp org-todo-keywords) + for keywords = + (mapcar (lambda (x) (if (string-match "^\\([^(]+\\)(" x) + (match-string 1 x) + x)) + keyword-spec) + if (eq type 'sequence) + if (member keyword keywords) + return keywords))) + +(defun chris/org--toggle-inline-images-in-subtree (&optional beg end refresh) + "Refresh inline image previews in the current heading/tree." + (let ((beg (or beg + (if (org-before-first-heading-p) + (line-beginning-position) + (save-excursion (org-back-to-heading) (point))))) + (end (or end + (if (org-before-first-heading-p) + (line-end-position) + (save-excursion (org-end-of-subtree) (point))))) + (overlays (cl-remove-if-not (lambda (ov) (overlay-get ov 'org-image-overlay)) + (ignore-errors (overlays-in beg end))))) + (dolist (ov overlays nil) + (delete-overlay ov) + (setq org-inline-image-overlays (delete ov org-inline-image-overlays))) + (when (or refresh (not overlays)) + (org-display-inline-images t t beg end) + t))) + (use-package unicode-fonts :ensure t :config @@ -302,7 +794,7 @@ (chris/leader-keys :states 'normal :keymaps 'override - "se" '(emojify-insert-emoji :which-key "insert emoji"))) + "ie" '(emojify-insert-emoji :which-key "insert emoji"))) (global-auto-revert-mode 1) (setq global-auto-revert-non-file-buffers t) @@ -927,496 +1419,6 @@ targets." (use-package ledger-mode) -(defun chris/org-mode-setup () - (interactive) - (org-indent-mode +1) - (toc-org-mode +1) - (visual-fill-column-mode +1) - (display-line-numbers-mode -1) - (variable-pitch-mode +1) - (setq visual-fill-column-width 100 - visual-fill-column-center-text t) - - ;;Let's make sure org-mode faces are inheriting fixed pitch faces. - (dolist (face '(org-block - org-block-begin-line - org-block-end-line - org-code - org-document-info-keyword - org-meta-line - org-table - org-date - org-verbatim)) - (set-face-attribute `,face nil :inherit 'fixed-pitch)) - - (set-face-attribute 'org-block-end-line nil :inherit 'org-block-begin-line) - (set-face-attribute 'org-quote nil :background "#242631" :inherit 'fixed-pitch)) - -(defun chris/org-agenda-setup () - (interactive) - (org-indent-mode +1) - (toc-org-mode +1) - (visual-fill-column-mode +1) - (display-line-numbers-mode -1) - (variable-pitch-mode -1) - (toggle-truncate-lines +1) - (setq visual-fill-column-width 120 - visual-fill-column-center-text t)) - -(use-package org - :straight t - :defer 1 - :config - (setq org-startup-indented t - org-edit-src-content-indentation 0 - org-agenda-sticky t - org-fontify-quote-and-verse-blocks t - org-src-preserve-indentation t - org-src-window-setup 'other-window - org-agenda-current-time-string "now >>>>>>>>>>>>>") - - (add-hook 'org-mode-hook 'chris/org-mode-setup) - - (org-babel-do-load-languages 'org-babel-load-languages - '((emacs-lisp . t) - (python . t) - (ditaa . t) - (shell . t) - (restclient . t))) - - (setq org-ditaa-jar-path "/usr/bin/ditaa") - - (require 'org-tempo) - (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) - (add-to-list 'org-structure-template-alist '("cl" . "src common-lisp")) - (add-to-list 'org-structure-template-alist '("py" . "src python")) - (add-to-list 'org-structure-template-alist '("sh" . "src shell")) - (add-to-list 'org-structure-template-alist '("yaml" . "src yaml")) - (add-to-list 'org-structure-template-alist '("yml" . "src yaml")) - (add-to-list 'org-structure-template-alist '("q" . "quote")) - (add-to-list 'org-structure-template-alist '("rc" . "src restclient")) - - (setq org-capture-templates - '(("t" "Personal todo" entry - (file "todo/todo.org") - (file ".templates/tasks.org") :prepend t) - ("n" "Personal notes" entry - (file "todo/notes.org") - "* %u %?\n%i\n%a" :prepend t) - ("j" "Journal" entry - (file+olp+datetree +org-capture-journal-file) - "* %U %?\n%i\n%a" :prepend t) - ("p" "TFC Plan" entry - (function chris/org-roam-capture-lesson-file) - (file ".templates/tfcplantemplate.org") - :prepend nil - :jump-to-captured t - :empty-lines 1) - ("P" "TFC Posts" entry - (file+headline "nvtfc_social_media.org" "Posts") - (file ".templates/posts.org") - :prepend t - :jump-to-captured t) - ("r" "Templates for projects") - ("rt" "Project-local todo" entry - (file+headline chris/project-todo "Inbox") - "* TODO %?\n%a\n%i\n\n" :prepend t) - ("rn" "Project-local notes" entry - (file+headline chris/project-todo "Notes") - "* %U %?\n%a\n%i\n\n" :prepend t) - ("rc" "Project-local changelog" entry - (file+headline chris/project-changelog "Changelog") - "* %U %?\n%a\n%i\n\n" :prepend t)) - org-capture-use-agenda-date t - org-agenda-timegrid-use-ampm t - org-agenda-show-inherited-tags nil - org-agenda-tags-column -100) - - (setq org-agenda-prefix-format '((agenda . " %i %?-12t% s") - (todo . " %i %-12:c") - (tags . " %i %-12:c") - (search . " %i %-12:c"))) - - (setq org-agenda-category-icon-alist - '(("todo" "~/org/icons/task.png" nil nil :ascent center) - ("lesson" "~/org/icons/book.png" nil nil :ascent center) - ("dev" "~/org/icons/coding.png" nil nil :ascent center) - ("TODO" "~/org/icons/coding.png" nil nil :ascent center))) - - (setq org-imenu-depth 4 - org-odt-styles-file "/home/chris/org/style.odt" - org-export-with-toc nil - org-export-with-author nil - org-todo-keywords - '((sequence "TODO(t)" "PROJ(p)" "STRT(s)" "WAIT(w)" "HOLD(h)" "|" "DONE(d)" "CNCL(c)") - (sequence "[ ](T)" "[-](S)" "[?](W)" "|" "[X](D)")) - org-agenda-files - '("/home/chris/org/todo/inbox.org" - "/home/chris/org/todo/notes.org" - "/home/chris/org/repetition.org" - "/home/chris/org/tfc_plans.org" - "/home/chris/org/ministry_team.org" - "/home/chris/org/todo/todo.org" - "/home/chris/org/newsletter.org" - "/home/chris/org/archive.org" - "/home/chris/org/nvtfc_social_media.org" - "/home/chris/dev/church-presenter/TODO.org" - "/home/chris/org/lessons/") - org-id-method 'ts - org-agenda-tags-column -75) - - (defun chris/org-columns-view () - "Turn on org-columns overlay and turn off olivetti-mode" - (interactive) - (goto-char (point-min)) - (org-content) - (org-columns) - (setq visual-fill-column-width 150)) - - (defun chris/org-columns-quit () - "Remove the org-columns overlay and turn on olivetti-mode" - (interactive) - (org-columns-quit) - (chris/org-mode-setup) - (setq visual-fill-column-width 100) - (setq visual-fill-column-width 100)) - - (add-hook 'org-agenda-finalize-hook 'evil-normal-state) - (add-hook 'org-agenda-finalize-hook 'chris/org-agenda-setup) - - (advice-add 'org-agenda-todo :after #'org-save-all-org-buffers) - - (setq org-refile-targets '((org-agenda-files . (:maxlevel . 6)))) - - (setq org-agenda-window-setup 'current-window) - - (defun chris/org-agenda () - "create a window that houses my org-agenda" - (interactive) - (with-selected-frame (make-frame - '((name . "org-agenda") - (width . 100))) - (org-agenda-list))) - - (setq org-latex-packages-alist '(("margin=2cm" "geometry" nil))) - - :general - (chris/leader-keys - :states 'normal - :keymaps 'override - "c" 'org-capture - "rr" 'org-refile - "e" 'org-export-dispatch - "oa" 'org-agenda-list) - ('normal org-agenda-mode-map - "q" 'org-agenda-quit - "r" 'org-agenda-redo - "d" 'org-agenda-deadline - "s" 'org-agenda-schedule - "t" 'org-agenda-todo - "c" 'org-agenda-capture) - ('normal org-columns-map - "j" 'outline-next-heading - "h" 'outline-previous-heading - "q" 'chris/org-columns-quit) - ('normal org-mode-map - "RET" 'chris/org-dwim-at-point - "gC" 'chris/org-columns-view - "ge" 'org-edit-src-code - "gr" 'revert-buffer - "S" 'org-schedule - "t" 'org-todo) - ('insert org-mode-map - "C-i" 'completion-at-point) - ('normal 'org-src-mode-map - "q" 'org-edit-src-abort)) - -(defun chris/org-roam-capture-lesson-file () - "Function to return the lesson file that is needed for TFC plan capture and move to correct position for plan insertion" - (interactive) - ;; (unless org-roam-mode (org-roam-mode +1)) - (let ((node (org-roam-node-read))) - (org-roam-node-visit node) - (goto-char (point-min)) - (search-forward "PLAN"))) - -(defun chris/project-todo () - (concat (projectile-project-root) "TODO.org")) -(defun chris/project-changelog () - (concat (projectile-project-root) "CHANGELOG.org")) - -(defun chris/org-babel-tangle-config () - (when (string-equal (buffer-file-name) - (expand-file-name "README.org" user-emacs-directory)) - (let ((org-confirm-babel-evaluate nil)) - (org-babel-tangle)))) - -(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'chris/org-babel-tangle-config - :append :local))) - -(use-package evil-org - :ensure t - :after org - :hook (org-mode . (lambda () evil-org-mode)) - :config - (add-to-list 'evil-digit-bound-motions 'evil-org-beginning-of-line) - (evil-define-key 'motion 'evil-org-mode - (kbd "0") 'evil-org-beginning-of-line) - (require 'evil-org-agenda) - (evil-org-agenda-set-keys)) - -(use-package org-super-agenda - :after org - :init - (setq org-super-agenda-groups '((:name "📅 Today" - :time-grid t - :scheduled today) - (:name "Due Today" - :deadline today) - (:name "Important" - :priority "A") - (:name "Development" - :category "TODO" - :category "dev") - (:name "Overdue" - :time-grid t - :scheduled past - :deadline past) - (:name "Due soon" - :deadline future))) - :config - (org-super-agenda-mode +1) - (setq org-super-agenda-header-map nil)) - -(use-package org-roam - :after org - :ensure t - :init - (setq org-roam-v2-ack t) - :config - (setq org-roam-directory "~/org" - org-roam-buffer-width 0.25 - org-roam-file-exclude-regexp ".stversion.*\|.stfolder.*\|.*~.*\|.*sync.*" - org-roam-db-location "~/.dotemacs/org-roam.db" - org-roam-completion-everywhere t - org-roam-capture-templates - '(("d" "default" plain "%?" - :if-new (file+head "${slug}.org" - "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n\nj ") - :unnarrowed t) - ("b" "bible" plain "%?" - :if-new (file+head "${slug}.org" - "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n- tags %^G\n\n* %?") - :unnarrowed t) - ("l" "TFC Lesson" plain (file ".templates/lessontemplate.org") - :if-new (file+head "lessons/${slug}.org" - "#+TITLE: ${title}\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n") - :unnarrowed t)) - org-roam-dailies-capture-templates - '(("d" "daily" plain #'org-roam-capture--get-point "" - :immediate-finish t - :file-name "%<%Y-%m-%d>" - :head "#+TITLE: %<%Y-%m-%d>\n#+AUTHOR: Chris Cochrun\n#+CREATED: %<%D - %I:%M %p>\n\n* HFL\n* Tasks\n* Family\n** How Do I Love Abbie?") - ("b" "biblical daily" plain #'org-roam-capture--get-point "" - :immediate-finish t - :file-name "%<%Y-%m-%d>-bib" - :head "#+TITLE: %<%Y-%m-%d> - Biblical\n#+AUTHOR: Chris Cochrun"))) - (org-roam-setup) - :general - (chris/leader-keys - :states 'normal - :keymaps 'override - "nf" '(org-roam-node-find :which-key "org roam ff") - "nr" 'org-roam-buffer-toggle - "ni" 'org-roam-node-insert - "nc" 'org-roam-capture - "njt" 'org-roam-dailies-capture-today - "ng" 'org-roam-graph)) - -(use-package websocket) -(use-package org-roam-ui - :straight (:host github :repo "org-roam/org-roam-ui" :files ("*.el" "out")) - :after org-roam - :config - (setq org-roam-ui-sync-theme t - org-roam-ui-follow t - org-roam-ui-update-on-save t - org-roam-ui-open-on-start t)) - -(use-package org-superstar - :after org - :config - (org-superstar-mode +1) - (setq org-superstar-headline-bullets-list '("\u25c9" "\u25c8" "" "\u25ce" "\u272c" "\u25c7" "\u2749" "\u2719" "\u2756")) - (setq org-superstar-item-bullet-alist '((?- . ?\u25b8) - (?+ . ?\u2749) - (?* . ?\u25c9))) - (set-face-attribute 'org-superstar-item nil :inherit 'org-level-3) - (add-hook 'org-mode-hook 'org-superstar-mode)) - -(defun chris/org-dwim-at-point (&optional arg) - "Do-what-I-mean at point. - -If on a: -- checkbox list item or todo heading: toggle it. -- clock: update its time. -- headline: cycle ARCHIVE subtrees, toggle latex fragments and inline images in - subtree; update statistics cookies/checkboxes and ToCs. -- footnote reference: jump to the footnote's definition -- footnote definition: jump to the first reference of this footnote -- table-row or a TBLFM: recalculate the table's formulas -- table-cell: clear it and go into insert mode. If this is a formula cell, - recaluclate it instead. -- babel-call: execute the source block -- statistics-cookie: update it. -- latex fragment: toggle it. -- link: follow it -- otherwise, refresh all inline images in current tree." - (interactive "P") - (let* ((context (org-element-context)) - (type (org-element-type context))) - ;; skip over unimportant contexts - (while (and context (memq type '(verbatim code bold italic underline strike-through subscript superscript))) - (setq context (org-element-property :parent context) - type (org-element-type context))) - (pcase type - (`headline - (cond ((memq (bound-and-true-p org-goto-map) - (current-active-maps)) - (org-goto-ret)) - ((and (fboundp 'toc-org-insert-toc) - (member "TOC" (org-get-tags))) - (toc-org-insert-toc) - (message "Updating table of contents")) - ((string= "ARCHIVE" (car-safe (org-get-tags))) - (org-force-cycle-archived)) - ((or (org-element-property :todo-type context) - (org-element-property :scheduled context)) - (org-todo - (if (eq (org-element-property :todo-type context) 'done) - (or (car (chris/org-get-todo-keywords-for (org-element-property :todo-keyword context))) - 'todo) - 'done)))) - ;; Update any metadata or inline previews in this subtree - (org-update-checkbox-count) - (org-update-parent-todo-statistics) - (when (and (fboundp 'toc-org-insert-toc) - (member "TOC" (org-get-tags))) - (toc-org-insert-toc) - (message "Updating table of contents")) - (let* ((beg (if (org-before-first-heading-p) - (line-beginning-position) - (save-excursion (org-back-to-heading) (point)))) - (end (if (org-before-first-heading-p) - (line-end-position) - (save-excursion (org-end-of-subtree) (point)))) - (overlays (ignore-errors (overlays-in beg end))) - (latex-overlays - (cl-find-if (lambda (o) (eq (overlay-get o 'org-overlay-type) 'org-latex-overlay)) - overlays)) - (image-overlays - (cl-find-if (lambda (o) (overlay-get o 'org-image-overlay)) - overlays))) - (chris/org--toggle-inline-images-in-subtree beg end) - (if (or image-overlays latex-overlays) - (org-clear-latex-preview beg end) - (org--latex-preview-region beg end)))) - - (`clock (org-clock-update-time-maybe)) - - (`footnote-reference - (org-footnote-goto-definition (org-element-property :label context))) - - (`footnote-definition - (org-footnote-goto-previous-reference (org-element-property :label context))) - - ((or `planning `timestamp) - (org-follow-timestamp-link)) - - ((or `table `table-row) - (if (org-at-TBLFM-p) - (org-table-calc-current-TBLFM) - (ignore-errors - (save-excursion - (goto-char (org-element-property :contents-begin context)) - (org-call-with-arg 'org-table-recalculate (or arg t)))))) - - (`table-cell - (org-table-blank-field) - (org-table-recalculate arg) - (when (and (string-empty-p (string-trim (org-table-get-field))) - (bound-and-true-p evil-local-mode)) - (evil-change-state 'insert))) - - (`babel-call - (org-babel-lob-execute-maybe)) - - (`statistics-cookie - (save-excursion (org-update-statistics-cookies arg))) - - ((or `src-block `inline-src-block) - (org-babel-execute-src-block)) - - ((or `latex-fragment `latex-environment) - (org-latex-preview)) - - (`link - (let* ((lineage (org-element-lineage context '(link) t)) - (path (org-element-property :path lineage))) - (if (or (equal (org-element-property :type lineage) "img") - (and path (image-type-from-file-name path))) - (chris/org--toggle-inline-images-in-subtree - (org-element-property :begin lineage) - (org-element-property :end lineage)) - (org-open-at-point arg)))) - - (`paragraph - (let ((match (and (org-at-item-checkbox-p) (match-string 1)))) - (org-toggle-checkbox))) - - (_ - (if (or (org-in-regexp org-ts-regexp-both nil t) - (org-in-regexp org-tsr-regexp-both nil t) - (org-in-regexp org-link-any-re nil t)) - (call-interactively #'org-open-at-point) - (chris/org--toggle-inline-images-in-subtree - (org-element-property :begin context) - (org-element-property :end context))))))) - - -(defun chris/org-get-todo-keywords-for (&optional keyword) - "Returns the list of todo keywords that KEYWORD belongs to." - (when keyword - (cl-loop for (type . keyword-spec) - in (cl-remove-if-not #'listp org-todo-keywords) - for keywords = - (mapcar (lambda (x) (if (string-match "^\\([^(]+\\)(" x) - (match-string 1 x) - x)) - keyword-spec) - if (eq type 'sequence) - if (member keyword keywords) - return keywords))) - -(defun chris/org--toggle-inline-images-in-subtree (&optional beg end refresh) - "Refresh inline image previews in the current heading/tree." - (let ((beg (or beg - (if (org-before-first-heading-p) - (line-beginning-position) - (save-excursion (org-back-to-heading) (point))))) - (end (or end - (if (org-before-first-heading-p) - (line-end-position) - (save-excursion (org-end-of-subtree) (point))))) - (overlays (cl-remove-if-not (lambda (ov) (overlay-get ov 'org-image-overlay)) - (ignore-errors (overlays-in beg end))))) - (dolist (ov overlays nil) - (delete-overlay ov) - (setq org-inline-image-overlays (delete ov org-inline-image-overlays))) - (when (or refresh (not overlays)) - (org-display-inline-images t t beg end) - t))) - (use-package mu4e :ensure nil :config