clean up org to make sense

This commit is contained in:
petrucci4prez 2018-07-21 02:24:45 -04:00
parent 18a247f6ac
commit 9d4d22be5d
1 changed files with 215 additions and 231 deletions

428
conf.org
View File

@ -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