clean up org to make sense
This commit is contained in:
parent
18a247f6ac
commit
9d4d22be5d
428
conf.org
428
conf.org
|
@ -374,10 +374,18 @@ NOTES:
|
||||||
git-commit-summary-max-length 50))
|
git-commit-summary-max-length 50))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
* org-mode
|
* org-mode
|
||||||
** basic
|
** major mode
|
||||||
|
*** general config
|
||||||
|
Enable some straightforward options:
|
||||||
|
- visual-line-mode: wrap text since I like to treat long lines as paragraphs
|
||||||
|
- org-indent-mode: indent each level for better visualization
|
||||||
|
- enable special behavior for header navigation, killing, and yanking (see these docs for details)
|
||||||
|
- logs should go in their own drawer called "LOGBOOK"
|
||||||
|
- DONE state should log the time
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(use-package org
|
(use-package org
|
||||||
:delight
|
:delight
|
||||||
|
;; source of indent-mode required here
|
||||||
(org-indent-mode nil org-indent)
|
(org-indent-mode nil org-indent)
|
||||||
(visual-line-mode)
|
(visual-line-mode)
|
||||||
:hook
|
:hook
|
||||||
|
@ -385,23 +393,20 @@ NOTES:
|
||||||
:config
|
:config
|
||||||
(setq org-startup-indented t
|
(setq org-startup-indented t
|
||||||
org-directory "~/Org"
|
org-directory "~/Org"
|
||||||
org-modules '(org-habit org-protocol))
|
org-modules '(org-habit org-protocol)
|
||||||
|
|
||||||
|
org-special-ctrl-a/e t
|
||||||
|
org-special-ctrl-k t
|
||||||
|
org-yank-adjusted-subtrees t
|
||||||
|
|
||||||
|
org-log-into-drawer "LOGBOOK"
|
||||||
|
org-log-done 'time)
|
||||||
|
|
||||||
(require 'org-protocol)
|
(require 'org-protocol)
|
||||||
(run-at-time "00:59" 3600 'org-save-all-org-buffers))
|
(run-at-time "00:59" 3600 'org-save-all-org-buffers))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** navigation
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(setq org-special-ctrl-a/e t)
|
|
||||||
(setq org-special-ctrl-k t)
|
|
||||||
(setq org-yank-adjusted-subtrees t)
|
|
||||||
#+END_SRC
|
|
||||||
** logging
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(setq org-log-into-drawer "LOGBOOK")
|
|
||||||
(setq org-log-done t)
|
|
||||||
#+END_SRC
|
|
||||||
** ui
|
|
||||||
*** bullets
|
*** bullets
|
||||||
|
These are just so much better to read
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(use-package org-bullets
|
(use-package org-bullets
|
||||||
:ensure t
|
:ensure t
|
||||||
|
@ -411,23 +416,112 @@ NOTES:
|
||||||
*** font height
|
*** font height
|
||||||
The fonts in org headings bug me, make them smaller and less invasive
|
The fonts in org headings bug me, make them smaller and less invasive
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/org-ui-heading-same-font-height ()
|
(add-hook 'org-mode-hook
|
||||||
|
(lambda ()
|
||||||
(let ((heading-height 1.15))
|
(let ((heading-height 1.15))
|
||||||
(set-face-attribute 'org-level-1 nil :weight 'bold :height heading-height)
|
(set-face-attribute 'org-level-1 nil :weight 'bold :height heading-height)
|
||||||
(set-face-attribute 'org-level-2 nil :weight 'semi-bold :height heading-height)
|
(set-face-attribute 'org-level-2 nil :weight 'semi-bold :height heading-height)
|
||||||
(set-face-attribute 'org-level-3 nil :weight 'normal :height heading-height)
|
(set-face-attribute 'org-level-3 nil :weight 'normal :height heading-height)
|
||||||
(set-face-attribute 'org-level-4 nil :weight 'normal :height heading-height)
|
(set-face-attribute 'org-level-4 nil :weight 'normal :height heading-height)
|
||||||
(set-face-attribute 'org-level-5 nil :weight 'normal :height heading-height)))
|
(set-face-attribute 'org-level-5 nil :weight 'normal :height heading-height))))
|
||||||
|
|
||||||
(add-hook 'org-mode-hook 'nd/org-ui-heading-same-font-height)
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** window splitting
|
*** src blocks
|
||||||
Org mode is great and all, but the windows never show up in the right place
|
#+BEGIN_SRC emacs-lisp
|
||||||
The solutions here are simple, but have the downside that the window sizing
|
(setq org-src-window-setup 'current-window
|
||||||
must be changed when tags/capture templates/todo items are changed.
|
org-src-fontify-natively t
|
||||||
This is because the buffer size is not known at window creation time
|
org-edit-src-content-indentation 0)
|
||||||
and I didn't feel like making a function to predict it
|
|
||||||
**** todo selection
|
(add-to-list 'org-structure-template-alist
|
||||||
|
'("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC"))
|
||||||
|
#+END_SRC
|
||||||
|
*** interactive commands
|
||||||
|
Some useful additional commands for org buffers
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun nd/mark-subtree-keyword (new-keyword &optional exclude)
|
||||||
|
"marks all tasks in a subtree with keyword unless original keyword
|
||||||
|
is in the optional argument exclude"
|
||||||
|
(let ((subtree-end (save-excursion (org-end-of-subtree t))))
|
||||||
|
(if (not (listp exclude))
|
||||||
|
(error "exlude must be a list if provided"))
|
||||||
|
(save-excursion
|
||||||
|
(while (< (point) subtree-end)
|
||||||
|
(let ((keyword (nd/is-todoitem-p)))
|
||||||
|
(if (and keyword (not (member keyword exclude)))
|
||||||
|
(org-todo new-keyword)))
|
||||||
|
(outline-next-heading)))))
|
||||||
|
|
||||||
|
(defun nd/mark-subtree-done ()
|
||||||
|
"marks all tasks in subtree as DONE unless they are already canc"
|
||||||
|
(interactive)
|
||||||
|
(nd/mark-subtree-keyword "DONE" '("CANC")))
|
||||||
|
|
||||||
|
(defun nd/org-clone-subtree-with-time-shift (n &optional shift)
|
||||||
|
"Like `org-clone-subtree-with-time-shift' except it resets checkboxes
|
||||||
|
and reverts all todo keywords to TODO"
|
||||||
|
(interactive "nNumber of clones to produce: ")
|
||||||
|
|
||||||
|
(let ((shift (or (org-entry-get nil "TIME_SHIFT" 'selective)
|
||||||
|
(read-from-minibuffer
|
||||||
|
"Date shift per clone (e.g. +1w, empty to copy unchanged): "))))
|
||||||
|
(condition-case err
|
||||||
|
(progn
|
||||||
|
(save-excursion
|
||||||
|
;; clone once and reset
|
||||||
|
(org-clone-subtree-with-time-shift 1 shift)
|
||||||
|
(org-forward-heading-same-level 1 t)
|
||||||
|
(org-reset-checkbox-state-subtree)
|
||||||
|
(nd/mark-subtree-keyword "TODO")
|
||||||
|
(call-interactively 'nd/org-log-delete)
|
||||||
|
(org-cycle)
|
||||||
|
;; clone reset tree again if we need more than one clone
|
||||||
|
(if (> n 1)
|
||||||
|
(let ((additional-trees (- n 1)))
|
||||||
|
(org-clone-subtree-with-time-shift additional-trees shift)
|
||||||
|
(dotimes (i additional-trees)
|
||||||
|
(org-forward-heading-same-level 1 t)
|
||||||
|
(org-cycle))))))
|
||||||
|
(error (message "%s" (error-message-string err))))))
|
||||||
|
|
||||||
|
(defun nd/org-log-delete ()
|
||||||
|
"Delete logbook drawer of subtree."
|
||||||
|
(interactive)
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (org-log-beginning))
|
||||||
|
(when (save-excursion
|
||||||
|
(save-match-data
|
||||||
|
(beginning-of-line 0)
|
||||||
|
(search-forward-regexp org-drawer-regexp)
|
||||||
|
(goto-char (match-beginning 1))
|
||||||
|
(looking-at "LOGBOOK")))
|
||||||
|
(org-mark-element)
|
||||||
|
(delete-region (region-beginning) (region-end))
|
||||||
|
(org-remove-empty-drawer-at (point)))))
|
||||||
|
#+END_SRC
|
||||||
|
** column view
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(setq org-columns-default-format
|
||||||
|
"%25ITEM %4TODO %TAGS %5Effort{:} %OWNER(OWN)")
|
||||||
|
|
||||||
|
(set-face-attribute 'org-column nil :background "#1e2023")
|
||||||
|
;; org-columns-summary-types
|
||||||
|
#+END_SRC
|
||||||
|
** calfw
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(use-package calfw
|
||||||
|
:ensure t
|
||||||
|
:config
|
||||||
|
(setq cfw:fchar-junction ?╋
|
||||||
|
cfw:fchar-vertical-line ?┃
|
||||||
|
cfw:fchar-horizontal-line ?━
|
||||||
|
cfw:fchar-left-junction ?┣
|
||||||
|
cfw:fchar-right-junction ?┫
|
||||||
|
cfw:fchar-top-junction ?┯
|
||||||
|
cfw:fchar-top-left-corner ?┏
|
||||||
|
cfw:fchar-top-right-corner ?┓))
|
||||||
|
#+END_SRC
|
||||||
|
** window splitting
|
||||||
|
Org mode is great and all, but the windows never show up in the right place. The solutions here are simple, but have the downside that the window sizing must be changed when tags/capture templates/todo items are changed. This is because the buffer size is not known at window creation time and I didn't feel like making a function to predict it
|
||||||
|
*** todo selection
|
||||||
I only need a teeny tiny window below my current window for todo selection
|
I only need a teeny tiny window below my current window for todo selection
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/org-todo-position (buffer alist)
|
(defun nd/org-todo-position (buffer alist)
|
||||||
|
@ -454,7 +548,7 @@ I only need a teeny tiny window below my current window for todo selection
|
||||||
|
|
||||||
(advice-add #'org-fast-todo-selection :around #'nd/org-todo-window-advice)
|
(advice-add #'org-fast-todo-selection :around #'nd/org-todo-window-advice)
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** tag selection
|
*** tag selection
|
||||||
By default, the tag selection window obliterates all but the current window...how disorienting :/
|
By default, the tag selection window obliterates all but the current window...how disorienting :/
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/org-tag-window-advice (orig-fn current inherited table &optional todo-table)
|
(defun nd/org-tag-window-advice (orig-fn current inherited table &optional todo-table)
|
||||||
|
@ -468,7 +562,7 @@ By default, the tag selection window obliterates all but the current window...ho
|
||||||
|
|
||||||
(advice-add #'org-fast-tag-selection :around #'nd/org-tag-window-advice)
|
(advice-add #'org-fast-tag-selection :around #'nd/org-tag-window-advice)
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** capture
|
*** capture
|
||||||
Capture should show up in the bottom of any currently active buffer
|
Capture should show up in the bottom of any currently active buffer
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/org-capture-position (buffer alist)
|
(defun nd/org-capture-position (buffer alist)
|
||||||
|
@ -488,16 +582,8 @@ Capture should show up in the bottom of any currently active buffer
|
||||||
|
|
||||||
(advice-add #'org-mks :around #'nd/org-capture-window-advice)
|
(advice-add #'org-mks :around #'nd/org-capture-window-advice)
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** src blocks
|
** gtd implementation
|
||||||
#+BEGIN_SRC emacs-lisp
|
*** todo states
|
||||||
(setq org-src-window-setup 'current-window
|
|
||||||
org-src-fontify-natively t
|
|
||||||
org-edit-src-content-indentation 0)
|
|
||||||
|
|
||||||
(add-to-list 'org-structure-template-alist
|
|
||||||
'("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC"))
|
|
||||||
#+END_SRC
|
|
||||||
** todo states
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(setq org-todo-keywords
|
(setq org-todo-keywords
|
||||||
'((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)")
|
'((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)")
|
||||||
|
@ -511,12 +597,12 @@ Capture should show up in the bottom of any currently active buffer
|
||||||
("HOLD" :foreground "violet" :weight bold)
|
("HOLD" :foreground "violet" :weight bold)
|
||||||
("CANC" :foreground "deep sky blue" :weight bold)))
|
("CANC" :foreground "deep sky blue" :weight bold)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** tags
|
*** tags
|
||||||
I use tags for agenda filtering. Very fast and simple. Each tag here starts with a symbol to define its group. Some groups are mutually exclusive, and each group has a different color. Any tag that is not part of these groups (eg some filetags in the few cases I use those) is easy to distinguish as it has the default tag color and is all caps.
|
I use tags for agenda filtering. Very fast and simple. Each tag here starts with a symbol to define its group. Some groups are mutually exclusive, and each group has a different color. Any tag that is not part of these groups (eg some filetags in the few cases I use those) is easy to distinguish as it has the default tag color and is all caps.
|
||||||
|
|
||||||
There are several types of tags I use:
|
There are several types of tags I use:
|
||||||
- location: a GTD contexts; these start with "@"
|
- location: a GTD context; these start with "@"
|
||||||
- tools: also a GTD contexts; these start with "#"
|
- tools: also a GTD context; these start with "#"
|
||||||
- attribute: useful flags for filtering; these start with "%"
|
- attribute: useful flags for filtering; these start with "%"
|
||||||
- life areas: key areas of life which define priorities and goals; these start with "_"
|
- life areas: key areas of life which define priorities and goals; these start with "_"
|
||||||
|
|
||||||
|
@ -563,21 +649,23 @@ NOTE: only these special chars; others make the tag chooser do weird things with
|
||||||
(nd/add-tag-face "PaleGoldenrod" "%")
|
(nd/add-tag-face "PaleGoldenrod" "%")
|
||||||
(nd/add-tag-face "violet" "_")
|
(nd/add-tag-face "violet" "_")
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** properties
|
*** properties
|
||||||
|
Add some useful properties:
|
||||||
|
- PARENT_TYPE: used for special groups of timestamped entries (iterators and periodicals).
|
||||||
|
- TIME_SHIFT: usually in conjunction with PARENT_TYPE, used as a shorthand when cloning subtrees to shift the time by a specified amount
|
||||||
|
- OWNER and GOAL: not currently used
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(add-to-list 'org-default-properties "PARENT_TYPE")
|
(mapc (lambda (i) (add-to-list 'org-default-properties i))
|
||||||
(add-to-list 'org-default-properties "OWNER")
|
'("PARENT_TYPE" "OWNER" "GOAL" "TIME_SHIFT"))
|
||||||
(add-to-list 'org-default-properties "GOAL")
|
|
||||||
(add-to-list 'org-default-properties "TIME_SHIFT")
|
|
||||||
|
|
||||||
(setq org-global-properties
|
(setq org-global-properties
|
||||||
'(("PARENT_TYPE_ALL" . "periodical iterator")
|
'(("PARENT_TYPE_ALL" . "periodical iterator")
|
||||||
("Effort_ALL" . "0:05 0:15 0:30 1:00 1:30 2:00 3:00 4:00 5:00 6:00")))
|
("Effort_ALL" . "0:05 0:15 0:30 1:00 1:30 2:00 3:00 4:00 5:00 6:00"))
|
||||||
|
|
||||||
;; TODO this may not be needed
|
org-use-property-inheritance
|
||||||
(setq org-use-property-inheritance '("PARENT_TYPE" "TIME_SHIFT"))
|
'("PARENT_TYPE" "TIME_SHIFT"))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** capture
|
*** capture
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(let ((capfile "~/Org/capture.org"))
|
(let ((capfile "~/Org/capture.org"))
|
||||||
(setq org-capture-templates
|
(setq org-capture-templates
|
||||||
|
@ -604,61 +692,65 @@ NOTE: only these special chars; others make the tag chooser do weird things with
|
||||||
"* %^{Title} :\\%note:\n[[%:link][%:description]]\n%U"
|
"* %^{Title} :\\%note:\n[[%:link][%:description]]\n%U"
|
||||||
:immediate-finish t))))
|
:immediate-finish t))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** refile
|
*** refile
|
||||||
*** targets
|
**** general
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(setq org-refile-targets (quote ((nil :maxlevel . 9)
|
(setq org-refile-targets '((nil :maxlevel . 9)
|
||||||
("~/Org/reference/idea.org" :maxlevel . 9)
|
("~/Org/reference/idea.org" :maxlevel . 9)
|
||||||
(org-agenda-files :maxlevel . 9))))
|
(org-agenda-files :maxlevel . 9))
|
||||||
|
org-refile-use-outline-path t
|
||||||
|
org-outline-path-complete-in-steps nil
|
||||||
|
org-refile-allow-creating-parent-nodes 'confirm
|
||||||
|
org-indirect-buffer-display 'current-window)
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** completion
|
**** exclude done states
|
||||||
|
No need to file under DONE or CANC states
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(setq org-refile-use-outline-path t)
|
(setq org-refile-target-verify-function
|
||||||
(setq org-outline-path-complete-in-steps nil)
|
(lambda () (not (member (nth 2 (org-heading-components)) org-done-keywords))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** node creation
|
*** clocking
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(setq org-refile-allow-creating-parent-nodes 'confirm)
|
|
||||||
#+END_SRC
|
|
||||||
*** use current window
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(setq org-indirect-buffer-display 'current-window)
|
|
||||||
#+END_SRC
|
|
||||||
*** exclude done states
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(defun nd/verify-refile-target ()
|
|
||||||
"Exclude todo keywords with a done state from refile targets"
|
|
||||||
(not (member (nth 2 (org-heading-components)) org-done-keywords)))
|
|
||||||
(setq org-refile-target-verify-function 'nd/verify-refile-target)
|
|
||||||
#+END_SRC
|
|
||||||
** habits
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(setq org-habit-graph-column 50)
|
|
||||||
#+END_SRC
|
|
||||||
** clocking
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** agenda
|
*** agenda
|
||||||
*** basic config
|
**** general config
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(setq org-agenda-files '("~/Org"
|
(setq org-agenda-files '("~/Org"
|
||||||
"~/Org/projects"
|
"~/Org/projects"
|
||||||
"~/Org/reference"))
|
"~/Org/reference")
|
||||||
;; (setq org-agenda-files '("~/Org/reference/agendatest.org"))
|
org-agenda-dim-blocked-tasks nil
|
||||||
(setq org-agenda-dim-blocked-tasks nil)
|
org-agenda-compact-blocks t
|
||||||
(setq org-agenda-compact-blocks t)
|
org-agenda-window-setup 'current-window
|
||||||
(setq org-agenda-window-setup 'current-window)
|
|
||||||
|
org-habit-graph-column 50
|
||||||
|
|
||||||
|
org-agenda-start-on-weekday 0
|
||||||
|
org-agenda-span 'day
|
||||||
|
org-agenda-current-time-string "### -- NOW -- ###"
|
||||||
|
org-agenda-time-grid '((daily today remove-match)
|
||||||
|
(0800 1000 1200 1200 1400 1600)
|
||||||
|
"......" "-----------------"))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** holidays and birthdays
|
**** right align tags
|
||||||
|
the agenda does not do this by default...it's annoying
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(setq holiday-bahai-holidays nil)
|
(add-hook 'org-finalize-agenda-hook
|
||||||
(setq holiday-hebrew-holidays nil)
|
(lambda () (setq org-agenda-tags-column (- 4 (window-width)))
|
||||||
(setq holiday-islamic-holidays nil)
|
(org-agenda-align-tags)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** task helper functions
|
**** holidays and birthdays
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(setq holiday-bahai-holidays nil
|
||||||
|
holiday-hebrew-holidays nil
|
||||||
|
holiday-oriental-holidays nil
|
||||||
|
holiday-islamic-holidays nil)
|
||||||
|
#+END_SRC
|
||||||
|
**** library
|
||||||
|
Since I am never totally satisfied with how the agenda works, I have a massive library of functions to filter and manipulate tasks (mostly for skip functions). I also have a few variables I set in order to toggle certain views
|
||||||
|
***** task helper functions
|
||||||
These are the building blocks for skip functions.
|
These are the building blocks for skip functions.
|
||||||
**** timestamps
|
****** timestamps
|
||||||
Each of these returns the timestamp if found.
|
Each of these returns the timestamp if found.
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/get-date-property (date-property)
|
(defun nd/get-date-property (date-property)
|
||||||
|
@ -712,7 +804,7 @@ no timestamp is found."
|
||||||
'nd/is-closed-heading-p
|
'nd/is-closed-heading-p
|
||||||
(- (* 60 60 24 nd/archive-delay-days))))
|
(- (* 60 60 24 nd/archive-delay-days))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** task level testing
|
****** task level testing
|
||||||
Each of these returns the keyword if true
|
Each of these returns the keyword if true
|
||||||
Doubles as a way to further test the todostate in downstream functions
|
Doubles as a way to further test the todostate in downstream functions
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
@ -733,7 +825,7 @@ Doubles as a way to further test the todostate in downstream functions
|
||||||
(defun nd/is-atomic-task-p ()
|
(defun nd/is-atomic-task-p ()
|
||||||
(and (not (nd/heading-has-parent 'nd/is-todoitem-p)) (nd/is-task-p)))
|
(and (not (nd/heading-has-parent 'nd/is-todoitem-p)) (nd/is-task-p)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** property testing
|
****** property testing
|
||||||
Returns t is heading matches a certian set of properties
|
Returns t is heading matches a certian set of properties
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/is-periodical-heading-p ()
|
(defun nd/is-periodical-heading-p ()
|
||||||
|
@ -753,7 +845,7 @@ Returns t is heading matches a certian set of properties
|
||||||
(defun nd/heading-has-tag-p (tag)
|
(defun nd/heading-has-tag-p (tag)
|
||||||
(member tag (org-get-tags-at)))
|
(member tag (org-get-tags-at)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** relational testing
|
****** relational testing
|
||||||
Returns t if heading has certain relationship to other headings
|
Returns t if heading has certain relationship to other headings
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/heading-has-children (heading-test)
|
(defun nd/heading-has-children (heading-test)
|
||||||
|
@ -790,7 +882,7 @@ Returns t if heading has certain relationship to other headings
|
||||||
(setq has-non-todoitem-parent t))))
|
(setq has-non-todoitem-parent t))))
|
||||||
(and has-todoitem-parent has-non-todoitem-parent)))
|
(and has-todoitem-parent has-non-todoitem-parent)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** project level testing
|
****** project level testing
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defconst nd/project-invalid-todostates
|
(defconst nd/project-invalid-todostates
|
||||||
'("WAIT" "NEXT")
|
'("WAIT" "NEXT")
|
||||||
|
@ -896,7 +988,7 @@ Returns t if heading has certain relationship to other headings
|
||||||
|
|
||||||
(t (error (concat "invalid keyword detected: " keyword))))))
|
(t (error (concat "invalid keyword detected: " keyword))))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** iterator testing
|
****** iterator testing
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defconst nd/iter-future-time (* 7 24 60 60))
|
(defconst nd/iter-future-time (* 7 24 60 60))
|
||||||
|
|
||||||
|
@ -926,7 +1018,7 @@ Returns t if heading has certain relationship to other headings
|
||||||
(outline-next-heading)))
|
(outline-next-heading)))
|
||||||
iter-status))
|
iter-status))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** periodical testing
|
****** periodical testing
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defconst nd/peri-future-time nd/iter-future-time)
|
(defconst nd/peri-future-time nd/iter-future-time)
|
||||||
|
|
||||||
|
@ -953,10 +1045,10 @@ Returns t if heading has certain relationship to other headings
|
||||||
(outline-next-heading)))
|
(outline-next-heading)))
|
||||||
peri-status))
|
peri-status))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** skip functions
|
***** skip functions
|
||||||
These are the primary means we use to sort through tasks. Note that we could do this with
|
These are the primary means we use to sort through tasks. Note that we could do this with
|
||||||
tags in the custom commands section but I find this easier to maintain and possibly faster.
|
tags in the custom commands section but I find this easier to maintain and possibly faster.
|
||||||
**** helper skip functions and macros
|
****** helper skip functions and macros
|
||||||
Subunits for skip functions. Not meant to be used or called from the custom commands api
|
Subunits for skip functions. Not meant to be used or called from the custom commands api
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/skip-heading ()
|
(defun nd/skip-heading ()
|
||||||
|
@ -985,7 +1077,7 @@ Subunits for skip functions. Not meant to be used or called from the custom comm
|
||||||
(if (not (and keyword ,test-fun))
|
(if (not (and keyword ,test-fun))
|
||||||
(nd/skip-heading)))))
|
(nd/skip-heading)))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** headings
|
****** headings
|
||||||
Skip functions for headings which may or may
|
Skip functions for headings which may or may
|
||||||
not be todo-items
|
not be todo-items
|
||||||
|
|
||||||
|
@ -1020,7 +1112,7 @@ section)
|
||||||
(nd/skip-heading)))))
|
(nd/skip-heading)))))
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** atomic tasks
|
****** atomic tasks
|
||||||
By definition these have no parents, so
|
By definition these have no parents, so
|
||||||
I don't need to worry about skipping over projects
|
I don't need to worry about skipping over projects
|
||||||
any todo state is valid and we only sort by done/canc
|
any todo state is valid and we only sort by done/canc
|
||||||
|
@ -1045,7 +1137,7 @@ any todo state is valid and we only sort by done/canc
|
||||||
(and (member keyword org-done-keywords)
|
(and (member keyword org-done-keywords)
|
||||||
(nd/is-archivable-heading-p))))
|
(nd/is-archivable-heading-p))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** periodicals
|
****** periodicals
|
||||||
These are headers marked with PARENT_TYPE=periodical
|
These are headers marked with PARENT_TYPE=periodical
|
||||||
property that have timestamped headers as children
|
property that have timestamped headers as children
|
||||||
which in turn may or may not have todo keywords.
|
which in turn may or may not have todo keywords.
|
||||||
|
@ -1071,7 +1163,7 @@ stale (all children in the past).
|
||||||
(not (nd/heading-has-children 'nd/is-periodical-heading-p))))
|
(not (nd/heading-has-children 'nd/is-periodical-heading-p))))
|
||||||
(nd/skip-heading))))
|
(nd/skip-heading))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** iterators
|
****** iterators
|
||||||
iterators are like projects but have additional status codes based on
|
iterators are like projects but have additional status codes based on
|
||||||
when the iterator will run out
|
when the iterator will run out
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
@ -1088,7 +1180,7 @@ when the iterator will run out
|
||||||
(not (or (nd/is-scheduled-heading-p)
|
(not (or (nd/is-scheduled-heading-p)
|
||||||
(nd/is-deadlined-heading-p)))))
|
(nd/is-deadlined-heading-p)))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** project tasks
|
****** project tasks
|
||||||
Since these are part of projects I need to assess
|
Since these are part of projects I need to assess
|
||||||
if the parent project is skippable, in which case
|
if the parent project is skippable, in which case
|
||||||
I jump to the next subtree
|
I jump to the next subtree
|
||||||
|
@ -1114,7 +1206,7 @@ which is dealt with similarly)
|
||||||
(nd/skip-heading)))
|
(nd/skip-heading)))
|
||||||
(nd/skip-heading)))))
|
(nd/skip-heading)))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** header-level errors
|
****** header-level errors
|
||||||
Some headers are invalid under certain conditions
|
Some headers are invalid under certain conditions
|
||||||
which I test here
|
which I test here
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
@ -1155,7 +1247,7 @@ which I test here
|
||||||
nd/is-task-p
|
nd/is-task-p
|
||||||
(not (nd/heading-has-effort-p))))
|
(not (nd/heading-has-effort-p))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** projects
|
****** projects
|
||||||
Projects are handled quite simply. They have statuscodes
|
Projects are handled quite simply. They have statuscodes
|
||||||
for which I test, and this can all be handled by one function.
|
for which I test, and this can all be handled by one function.
|
||||||
Note that this is used for "normal" projects as well as iterators
|
Note that this is used for "normal" projects as well as iterators
|
||||||
|
@ -1171,15 +1263,18 @@ Note that this is used for "normal" projects as well as iterators
|
||||||
(nd/skip-subtree))
|
(nd/skip-subtree))
|
||||||
(nd/skip-heading)))))
|
(nd/skip-heading)))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** interactive view functions
|
***** variables
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defvar nd/agenda-limit-project-toplevel t
|
(defvar nd/agenda-limit-project-toplevel t
|
||||||
"used to filter projects by all levels or top-level only")
|
"If true, filter projects by all levels or top level only.")
|
||||||
|
|
||||||
(defvar nd/agenda-hide-incubator-tags t
|
(defvar nd/agenda-hide-incubator-tags t
|
||||||
"used to filter incubator headings")
|
"If true, don't show incubator headings.")
|
||||||
|
#+END_SRC
|
||||||
|
***** interactive view functions
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/toggle-project-toplevel-display ()
|
(defun nd/toggle-project-toplevel-display ()
|
||||||
|
"Toggle all project headings and toplevel only headings in project blocks."
|
||||||
(interactive)
|
(interactive)
|
||||||
(setq nd/agenda-limit-project-toplevel (not nd/agenda-limit-project-toplevel))
|
(setq nd/agenda-limit-project-toplevel (not nd/agenda-limit-project-toplevel))
|
||||||
(when (equal major-mode 'org-agenda-mode)
|
(when (equal major-mode 'org-agenda-mode)
|
||||||
|
@ -1187,16 +1282,8 @@ Note that this is used for "normal" projects as well as iterators
|
||||||
(message "Showing %s project view in agenda"
|
(message "Showing %s project view in agenda"
|
||||||
(if nd/agenda-limit-project-toplevel "toplevel" "complete")))
|
(if nd/agenda-limit-project-toplevel "toplevel" "complete")))
|
||||||
|
|
||||||
(defun nd/toggle-agenda-var (var msg)
|
|
||||||
(interactive)
|
|
||||||
(set var (not (eval var)))
|
|
||||||
(when (equal major-mode 'org-agenda-mode)
|
|
||||||
(org-agenda-redo))
|
|
||||||
(message msg))
|
|
||||||
|
|
||||||
(defun nd/org-agenda-filter-non-context ()
|
(defun nd/org-agenda-filter-non-context ()
|
||||||
"A quick and dirty agenda filter that removes all
|
"Filter all tasks with context tags."
|
||||||
tasks with context tags"
|
|
||||||
(interactive)
|
(interactive)
|
||||||
(let* ((tags-list (mapcar #'car org-tag-alist))
|
(let* ((tags-list (mapcar #'car org-tag-alist))
|
||||||
(context-tags (append
|
(context-tags (append
|
||||||
|
@ -1206,7 +1293,7 @@ tasks with context tags"
|
||||||
(mapcar (lambda (tag) (concat "-" tag)) context-tags))
|
(mapcar (lambda (tag) (concat "-" tag)) context-tags))
|
||||||
(org-agenda-filter-apply org-agenda-tag-filter 'tag)))
|
(org-agenda-filter-apply org-agenda-tag-filter 'tag)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** agenda aesthetics
|
**** agenda aesthetics
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(setq org-agenda-tags-todo-honor-ignore-options t)
|
(setq org-agenda-tags-todo-honor-ignore-options t)
|
||||||
|
|
||||||
|
@ -1231,7 +1318,7 @@ tasks with context tags"
|
||||||
((> pa pb) +1)
|
((> pa pb) +1)
|
||||||
((< pa pb) -1)))))
|
((< pa pb) -1)))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** custom commands
|
**** custom commands
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun nd/org-agenda-filter-status (filter status-fun a-line)
|
(defun nd/org-agenda-filter-status (filter status-fun a-line)
|
||||||
"Filter for org-agenda-before-sorting-filter-function intended for
|
"Filter for org-agenda-before-sorting-filter-function intended for
|
||||||
|
@ -1424,109 +1511,6 @@ set as a text property for further sorting"
|
||||||
(org-agenda-prefix-format '((tags . " %-12:c %(format \"xxxx: \")")))
|
(org-agenda-prefix-format '((tags . " %-12:c %(format \"xxxx: \")")))
|
||||||
(org-agenda-sorting-strategy '(user-defined-down category-keep)))))))))
|
(org-agenda-sorting-strategy '(user-defined-down category-keep)))))))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** views
|
|
||||||
**** calendar display
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(setq org-agenda-start-on-weekday 0)
|
|
||||||
(setq org-agenda-span 'day)
|
|
||||||
(setq org-agenda-current-time-string "### -- NOW -- ###")
|
|
||||||
(setq org-agenda-time-grid '((daily today remove-match)
|
|
||||||
(0800 1000 1200 1200 1400 1600)
|
|
||||||
"......" "-----------------"))
|
|
||||||
#+End_src
|
|
||||||
**** right align tags
|
|
||||||
the agenda does not do this by default...it's annoying
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(add-hook 'org-finalize-agenda-hook 'place-agenda-tags)
|
|
||||||
(defun place-agenda-tags ()
|
|
||||||
"Put the agenda tags by the right border of the agenda window."
|
|
||||||
(setq org-agenda-tags-column (- 4 (window-width)))
|
|
||||||
(org-agenda-align-tags))
|
|
||||||
#+END_SRC
|
|
||||||
** column view
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(setq org-columns-default-format
|
|
||||||
"%25ITEM %4TODO %TAGS %5Effort{:} %OWNER(OWN)")
|
|
||||||
|
|
||||||
(set-face-attribute 'org-column nil :background "#1e2023")
|
|
||||||
;; org-columns-summary-types
|
|
||||||
#+END_SRC
|
|
||||||
** interactive commands
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(defun nd/mark-subtree-keyword (new-keyword &optional exclude)
|
|
||||||
"marks all tasks in a subtree with keyword unless original keyword
|
|
||||||
is in the optional argument exclude"
|
|
||||||
(let ((subtree-end (save-excursion (org-end-of-subtree t))))
|
|
||||||
(if (not (listp exclude))
|
|
||||||
(error "exlude must be a list if provided"))
|
|
||||||
(save-excursion
|
|
||||||
(while (< (point) subtree-end)
|
|
||||||
(let ((keyword (nd/is-todoitem-p)))
|
|
||||||
(if (and keyword (not (member keyword exclude)))
|
|
||||||
(org-todo new-keyword)))
|
|
||||||
(outline-next-heading)))))
|
|
||||||
|
|
||||||
(defun nd/mark-subtree-done ()
|
|
||||||
"marks all tasks in subtree as DONE unless they are already canc"
|
|
||||||
(interactive)
|
|
||||||
(nd/mark-subtree-keyword "DONE" '("CANC")))
|
|
||||||
|
|
||||||
(defun nd/org-clone-subtree-with-time-shift (n &optional shift)
|
|
||||||
"Like `org-clone-subtree-with-time-shift' except it resets checkboxes
|
|
||||||
and reverts all todo keywords to TODO"
|
|
||||||
(interactive "nNumber of clones to produce: ")
|
|
||||||
|
|
||||||
(let ((shift (or (org-entry-get nil "TIME_SHIFT" 'selective)
|
|
||||||
(read-from-minibuffer
|
|
||||||
"Date shift per clone (e.g. +1w, empty to copy unchanged): "))))
|
|
||||||
(condition-case err
|
|
||||||
(progn
|
|
||||||
(save-excursion
|
|
||||||
;; clone once and reset
|
|
||||||
(org-clone-subtree-with-time-shift 1 shift)
|
|
||||||
(org-forward-heading-same-level 1 t)
|
|
||||||
(org-reset-checkbox-state-subtree)
|
|
||||||
(nd/mark-subtree-keyword "TODO")
|
|
||||||
(call-interactively 'nd/org-log-delete)
|
|
||||||
(org-cycle)
|
|
||||||
;; clone reset tree again if we need more than one clone
|
|
||||||
(if (> n 1)
|
|
||||||
(let ((additional-trees (- n 1)))
|
|
||||||
(org-clone-subtree-with-time-shift additional-trees shift)
|
|
||||||
(dotimes (i additional-trees)
|
|
||||||
(org-forward-heading-same-level 1 t)
|
|
||||||
(org-cycle))))))
|
|
||||||
(error (message "%s" (error-message-string err))))))
|
|
||||||
|
|
||||||
(defun nd/org-log-delete ()
|
|
||||||
"Delete logbook drawer of subtree."
|
|
||||||
(interactive)
|
|
||||||
(save-excursion
|
|
||||||
(goto-char (org-log-beginning))
|
|
||||||
(when (save-excursion
|
|
||||||
(save-match-data
|
|
||||||
(beginning-of-line 0)
|
|
||||||
(search-forward-regexp org-drawer-regexp)
|
|
||||||
(goto-char (match-beginning 1))
|
|
||||||
(looking-at "LOGBOOK")))
|
|
||||||
(org-mark-element)
|
|
||||||
(delete-region (region-beginning) (region-end))
|
|
||||||
(org-remove-empty-drawer-at (point)))))
|
|
||||||
#+END_SRC
|
|
||||||
** calfw
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(use-package calfw
|
|
||||||
:ensure t
|
|
||||||
:config
|
|
||||||
(setq cfw:fchar-junction ?╋
|
|
||||||
cfw:fchar-vertical-line ?┃
|
|
||||||
cfw:fchar-horizontal-line ?━
|
|
||||||
cfw:fchar-left-junction ?┣
|
|
||||||
cfw:fchar-right-junction ?┫
|
|
||||||
cfw:fchar-top-junction ?┯
|
|
||||||
cfw:fchar-top-left-corner ?┏
|
|
||||||
cfw:fchar-top-right-corner ?┓))
|
|
||||||
#+END_SRC
|
|
||||||
* mu4e
|
* mu4e
|
||||||
only for gmail now
|
only for gmail now
|
||||||
** basic
|
** basic
|
||||||
|
|
Loading…
Reference in New Issue