Org-DWIM-at-point for RET key

This commit is contained in:
Chris Cochrun 2021-02-22 11:04:59 -06:00
parent 5cec642a0b
commit 4787fccfa9
2 changed files with 527 additions and 130 deletions

View file

@ -264,7 +264,9 @@ This evil-collection package includes a lot of other evil based things.
"ss" '(consult-line :which-key "consult search") "ss" '(consult-line :which-key "consult search")
"ww" '(other-window :which-key "other window") "ww" '(other-window :which-key "other window")
"wd" '(delete-window :which-key "other window") "wd" '(delete-window :which-key "other window")
)) )
(general-def 'minibuffer-local-map
"C-v" 'evil-paste-after))
#+end_src #+end_src
#+begin_src emacs-lisp #+begin_src emacs-lisp
@ -510,78 +512,110 @@ This is the use-package definition with a lot of customization. Need to setup au
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. 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 #+begin_src emacs-lisp
(use-package org (use-package org
:config :config
(setq org-startup-indented t (setq org-startup-indented t
org-edit-src-content-indentation 0) org-edit-src-content-indentation 0
org-agenda-sticky t)
(add-hook 'org-mode-hook 'chris/org-mode-setup) (add-hook 'org-mode-hook 'chris/org-mode-setup)
(org-babel-do-load-languages (org-babel-do-load-languages
'org-babel-load-languages 'org-babel-load-languages
'((emacs-lisp . t) '((emacs-lisp . t)
(python . t) (python . t)
(shell . t))) (shell . t)))
(require 'org-tempo) (require 'org-tempo)
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python")) (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 '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("q" . "quote")) (add-to-list 'org-structure-template-alist '("q" . "quote"))
(setq org-capture-templates (setq org-capture-templates
'(("t" "Personal todo" entry '(("t" "Personal todo" entry
(file+headline +org-capture-todo-file "Inbox") (file+headline +org-capture-todo-file "Inbox")
"* TODO %^{TODO name}\nSCHEDULED: %T\n%a\n%i%?" :prepend t) "* TODO %^{TODO name}\nSCHEDULED: %T\n%a\n%i%?" :prepend t)
("n" "Personal notes" entry ("n" "Personal notes" entry
(file+headline +org-capture-notes-file "Inbox") (file+headline +org-capture-notes-file "Inbox")
"* %u %?\n%i\n%a" :prepend t) "* %u %?\n%i\n%a" :prepend t)
("j" "Journal" entry ("j" "Journal" entry
(file+olp+datetree +org-capture-journal-file) (file+olp+datetree +org-capture-journal-file)
"* %U %?\n%i\n%a" :prepend t) "* %U %?\n%i\n%a" :prepend t)
("p" "TFC Plan" entry ("p" "TFC Plan" entry
(function chris/org-roam-capture-lesson-file) (function chris/org-roam-capture-lesson-file)
(file ".templates/tfcplantemplate.org") (file ".templates/tfcplantemplate.org")
:prepend nil :prepend nil
:jump-to-captured t :jump-to-captured t
:empty-lines 1) :empty-lines 1)
("r" "Templates for projects") ("r" "Templates for projects")
("rt" "Project-local todo" entry ("rt" "Project-local todo" entry
(file+headline +org-capture-project-todo-file "Inbox") (file+headline +org-capture-project-todo-file "Inbox")
"* TODO %?\n%i\n%a" :prepend t) "* TODO %?\n%i\n%a" :prepend t)
("rn" "Project-local notes" entry ("rn" "Project-local notes" entry
(file+headline +org-capture-project-notes-file "Inbox") (file+headline +org-capture-project-notes-file "Inbox")
"* %U %?\n%i\n%a" :prepend t) "* %U %?\n%i\n%a" :prepend t)
("rc" "Project-local changelog" entry ("rc" "Project-local changelog" entry
(file+headline +org-capture-project-changelog-file "Unreleased") (file+headline +org-capture-project-changelog-file "Unreleased")
"* %U %?\n%i\n%a" :prepend t) "* %U %?\n%i\n%a" :prepend t)
("o" "Centralized templates for projects") ("o" "Centralized templates for projects")
("ot" "Project todo" entry #'+org-capture-central-project-todo-file ("ot" "Project todo" entry #'+org-capture-central-project-todo-file
"* TODO %?\n %i\n %a" :heading "Tasks" :prepend nil) "* TODO %?\n %i\n %a" :heading "Tasks" :prepend nil)
("on" "Project notes" entry #'+org-capture-central-project-notes-file ("on" "Project notes" entry #'+org-capture-central-project-notes-file
"* %U %?\n %i\n %a" :heading "Notes" :prepend t) "* %U %?\n %i\n %a" :heading "Notes" :prepend t)
("oc" "Project changelog" entry #'+org-capture-central-project-changelog-file ("oc" "Project changelog" entry #'+org-capture-central-project-changelog-file
"* %U %?\n %i\n %a" :heading "Changelog" :prepend t)) "* %U %?\n %i\n %a" :heading "Changelog" :prepend t))
org-capture-use-agenda-date t) org-capture-use-agenda-date t)
;;(setq org-superstar-headline-bullets-list '("◉" "◈" "▸" "✬" "◎" "◇" "❉" "✙" "❖")) ;;(setq org-superstar-headline-bullets-list '("◉" "◈" "▸" "✬" "◎" "◇" "❉" "✙" "❖"))
(setq org-imenu-depth 4) (setq org-imenu-depth 4)
(setq org-odt-styles-file "/home/chris/org/style.odt") (setq org-odt-styles-file "/home/chris/org/style.odt")
(setq org-export-with-toc nil) (setq org-export-with-toc nil)
(setq org-export-with-author nil) (setq org-export-with-author nil)
(setq org-todo-keywords (setq org-todo-keywords
'((sequence "TODO(t)" "PROJ(p)" "STRT(s)" "WAIT(w)" "HOLD(h)" "|" "DONE(d)" "CNCL(c)") '((sequence "TODO(t)" "PROJ(p)" "STRT(s)" "WAIT(w)" "HOLD(h)" "|" "DONE(d)" "CNCL(c)")
(sequence "[ ](T)" "[-](S)" "[?](W)" "|" "[X](D)"))) (sequence "[ ](T)" "[-](S)" "[?](W)" "|" "[X](D)")))
(setq org-agenda-files (setq org-agenda-files
'("/home/chris/org/DMPREADME.org" "/home/chris/org/DMPTODO.org" "/home/chris/org/inbox.org" "/home/chris/org/notes.org" "/home/chris/org/repetition.org" "/home/chris/org/tasks.org" "/home/chris/org/tfc_plans.org" "/home/chris/org/ministry_team.org" "/home/chris/org/todo.org" "/home/chris/org/newsletter.org")) '("/home/chris/org/DMPREADME.org" "/home/chris/org/DMPTODO.org" "/home/chris/org/inbox.org" "/home/chris/org/notes.org" "/home/chris/org/repetition.org" "/home/chris/org/tasks.org" "/home/chris/org/tfc_plans.org" "/home/chris/org/ministry_team.org" "/home/chris/org/todo.org" "/home/chris/org/newsletter.org"))
(setq org-id-method 'ts) (setq org-id-method 'ts)
:general
(chris/leader-keys "o a" 'org-agenda (defun chris/org-columns-view ()
"c" 'org-capture "Turn on org-columns overlay and turn off olivetti-mode"
"so" 'consult-imenu)) (interactive)
(org-columns)
(olivetti-mode -1))
(defun chris/org-columns-quit ()
"Remove the org-columns overlay and turn on olivetti-mode"
(interactive)
(org-columns-quit)
(olivetti-mode +1))
(defun chris/org-toggle-todo-and-mark-time ()
"Mark the time of finishing task and mark it as done."
(interactive)
(save-excursion
(org-back-to-heading t) ;; Make sure command works even if point is
;; below target heading
(cond ((looking-at "\*+ TODO")
(org-todo "DONE"))
((looking-at "\*+ DONE")
(org-todo "TODO"))
(t (message "Can only toggle between TODO and DONE.")))))
:general
(chris/leader-keys "o a" 'org-agenda
"c" 'org-capture
"so" 'consult-imenu)
('normal org-agenda-mode-map
"q" 'org-agenda-quit)
('normal org-columns-map
"j" 'outline-next-heading
"h" 'outline-previous-heading)
('normal org-mode-map
"RET" 'chris/org-dwim-at-point))
#+end_src #+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. 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.
@ -709,6 +743,172 @@ In order to use it, I need to go to http://localhost:8080
(org-superstar-mode +1) (org-superstar-mode +1)
(setq org-superstar-headline-bullets-list '("\u25c9" "\u25c8" "\u25b8" "\u25ce" "\u272c" "\u25c7" "\u2749" "\u2719" "\u2756"))) (setq org-superstar-headline-bullets-list '("\u25c9" "\u25c8" "\u25b8" "\u25ce" "\u272c" "\u25c7" "\u2749" "\u2719" "\u2756")))
#+end_src #+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
** Calendar ** Calendar
#+begin_src emacs-lisp #+begin_src emacs-lisp

325
init.el
View file

@ -163,7 +163,9 @@
"ss" '(consult-line :which-key "consult search") "ss" '(consult-line :which-key "consult search")
"ww" '(other-window :which-key "other window") "ww" '(other-window :which-key "other window")
"wd" '(delete-window :which-key "other window") "wd" '(delete-window :which-key "other window")
)) )
(general-def 'minibuffer-local-map
"C-v" 'evil-paste-after))
(use-package evil-escape (use-package evil-escape
:after evil :after evil
@ -280,78 +282,110 @@
(display-line-numbers-mode -1)) (display-line-numbers-mode -1))
(use-package org (use-package org
:config :config
(setq org-startup-indented t (setq org-startup-indented t
org-edit-src-content-indentation 0) org-edit-src-content-indentation 0
org-agenda-sticky t)
(add-hook 'org-mode-hook 'chris/org-mode-setup) (add-hook 'org-mode-hook 'chris/org-mode-setup)
(org-babel-do-load-languages (org-babel-do-load-languages
'org-babel-load-languages 'org-babel-load-languages
'((emacs-lisp . t) '((emacs-lisp . t)
(python . t) (python . t)
(shell . t))) (shell . t)))
(require 'org-tempo) (require 'org-tempo)
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python")) (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 '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("q" . "quote")) (add-to-list 'org-structure-template-alist '("q" . "quote"))
(setq org-capture-templates (setq org-capture-templates
'(("t" "Personal todo" entry '(("t" "Personal todo" entry
(file+headline +org-capture-todo-file "Inbox") (file+headline +org-capture-todo-file "Inbox")
"* TODO %^{TODO name}\nSCHEDULED: %T\n%a\n%i%?" :prepend t) "* TODO %^{TODO name}\nSCHEDULED: %T\n%a\n%i%?" :prepend t)
("n" "Personal notes" entry ("n" "Personal notes" entry
(file+headline +org-capture-notes-file "Inbox") (file+headline +org-capture-notes-file "Inbox")
"* %u %?\n%i\n%a" :prepend t) "* %u %?\n%i\n%a" :prepend t)
("j" "Journal" entry ("j" "Journal" entry
(file+olp+datetree +org-capture-journal-file) (file+olp+datetree +org-capture-journal-file)
"* %U %?\n%i\n%a" :prepend t) "* %U %?\n%i\n%a" :prepend t)
("p" "TFC Plan" entry ("p" "TFC Plan" entry
(function chris/org-roam-capture-lesson-file) (function chris/org-roam-capture-lesson-file)
(file ".templates/tfcplantemplate.org") (file ".templates/tfcplantemplate.org")
:prepend nil :prepend nil
:jump-to-captured t :jump-to-captured t
:empty-lines 1) :empty-lines 1)
("r" "Templates for projects") ("r" "Templates for projects")
("rt" "Project-local todo" entry ("rt" "Project-local todo" entry
(file+headline +org-capture-project-todo-file "Inbox") (file+headline +org-capture-project-todo-file "Inbox")
"* TODO %?\n%i\n%a" :prepend t) "* TODO %?\n%i\n%a" :prepend t)
("rn" "Project-local notes" entry ("rn" "Project-local notes" entry
(file+headline +org-capture-project-notes-file "Inbox") (file+headline +org-capture-project-notes-file "Inbox")
"* %U %?\n%i\n%a" :prepend t) "* %U %?\n%i\n%a" :prepend t)
("rc" "Project-local changelog" entry ("rc" "Project-local changelog" entry
(file+headline +org-capture-project-changelog-file "Unreleased") (file+headline +org-capture-project-changelog-file "Unreleased")
"* %U %?\n%i\n%a" :prepend t) "* %U %?\n%i\n%a" :prepend t)
("o" "Centralized templates for projects") ("o" "Centralized templates for projects")
("ot" "Project todo" entry #'+org-capture-central-project-todo-file ("ot" "Project todo" entry #'+org-capture-central-project-todo-file
"* TODO %?\n %i\n %a" :heading "Tasks" :prepend nil) "* TODO %?\n %i\n %a" :heading "Tasks" :prepend nil)
("on" "Project notes" entry #'+org-capture-central-project-notes-file ("on" "Project notes" entry #'+org-capture-central-project-notes-file
"* %U %?\n %i\n %a" :heading "Notes" :prepend t) "* %U %?\n %i\n %a" :heading "Notes" :prepend t)
("oc" "Project changelog" entry #'+org-capture-central-project-changelog-file ("oc" "Project changelog" entry #'+org-capture-central-project-changelog-file
"* %U %?\n %i\n %a" :heading "Changelog" :prepend t)) "* %U %?\n %i\n %a" :heading "Changelog" :prepend t))
org-capture-use-agenda-date t) org-capture-use-agenda-date t)
;;(setq org-superstar-headline-bullets-list '("◉" "◈" "▸" "✬" "◎" "◇" "❉" "✙" "❖")) ;;(setq org-superstar-headline-bullets-list '("◉" "◈" "▸" "✬" "◎" "◇" "❉" "✙" "❖"))
(setq org-imenu-depth 4) (setq org-imenu-depth 4)
(setq org-odt-styles-file "/home/chris/org/style.odt") (setq org-odt-styles-file "/home/chris/org/style.odt")
(setq org-export-with-toc nil) (setq org-export-with-toc nil)
(setq org-export-with-author nil) (setq org-export-with-author nil)
(setq org-todo-keywords (setq org-todo-keywords
'((sequence "TODO(t)" "PROJ(p)" "STRT(s)" "WAIT(w)" "HOLD(h)" "|" "DONE(d)" "CNCL(c)") '((sequence "TODO(t)" "PROJ(p)" "STRT(s)" "WAIT(w)" "HOLD(h)" "|" "DONE(d)" "CNCL(c)")
(sequence "[ ](T)" "[-](S)" "[?](W)" "|" "[X](D)"))) (sequence "[ ](T)" "[-](S)" "[?](W)" "|" "[X](D)")))
(setq org-agenda-files (setq org-agenda-files
'("/home/chris/org/DMPREADME.org" "/home/chris/org/DMPTODO.org" "/home/chris/org/inbox.org" "/home/chris/org/notes.org" "/home/chris/org/repetition.org" "/home/chris/org/tasks.org" "/home/chris/org/tfc_plans.org" "/home/chris/org/ministry_team.org" "/home/chris/org/todo.org" "/home/chris/org/newsletter.org")) '("/home/chris/org/DMPREADME.org" "/home/chris/org/DMPTODO.org" "/home/chris/org/inbox.org" "/home/chris/org/notes.org" "/home/chris/org/repetition.org" "/home/chris/org/tasks.org" "/home/chris/org/tfc_plans.org" "/home/chris/org/ministry_team.org" "/home/chris/org/todo.org" "/home/chris/org/newsletter.org"))
(setq org-id-method 'ts) (setq org-id-method 'ts)
:general
(chris/leader-keys "o a" 'org-agenda (defun chris/org-columns-view ()
"c" 'org-capture "Turn on org-columns overlay and turn off olivetti-mode"
"so" 'consult-imenu)) (interactive)
(org-columns)
(olivetti-mode -1))
(defun chris/org-columns-quit ()
"Remove the org-columns overlay and turn on olivetti-mode"
(interactive)
(org-columns-quit)
(olivetti-mode +1))
(defun chris/org-toggle-todo-and-mark-time ()
"Mark the time of finishing task and mark it as done."
(interactive)
(save-excursion
(org-back-to-heading t) ;; Make sure command works even if point is
;; below target heading
(cond ((looking-at "\*+ TODO")
(org-todo "DONE"))
((looking-at "\*+ DONE")
(org-todo "TODO"))
(t (message "Can only toggle between TODO and DONE.")))))
:general
(chris/leader-keys "o a" 'org-agenda
"c" 'org-capture
"so" 'consult-imenu)
('normal org-agenda-mode-map
"q" 'org-agenda-quit)
('normal org-columns-map
"j" 'outline-next-heading
"h" 'outline-previous-heading)
('normal org-mode-map
"RET" 'chris/org-dwim-at-point))
(defun chris/org-roam-capture-lesson-file () (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" "Function to return the lesson file that is needed for TFC plan capture and move to correct position for plan insertion"
@ -452,6 +486,169 @@
(org-superstar-mode +1) (org-superstar-mode +1)
(setq org-superstar-headline-bullets-list '("\u25c9" "\u25c8" "\u25b8" "\u25ce" "\u272c" "\u25c7" "\u2749" "\u2719" "\u2756"))) (setq org-superstar-headline-bullets-list '("\u25c9" "\u25c8" "\u25b8" "\u25ce" "\u272c" "\u25c7" "\u2749" "\u2719" "\u2756")))
(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 calfw (use-package calfw
:commands chris/calfw-calendar-open :commands chris/calfw-calendar-open
:config :config