-
Notifications
You must be signed in to change notification settings - Fork 5
/
org-kanban.el
105 lines (81 loc) · 3 KB
/
org-kanban.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
;;; org-kanban.el --- Org-mode kanban utility -*- lexical-binding: t; -*-
;; Unlicense
;; Author: Hagmonk <hagmonk@icloud.com>
;; URL: http://github.com/hagmonk/org-kanban
;; Keywords: outlines kanban org
;; Package-Requires: ((emacs "25") (org "9"))
;; Version: 0.1
;;; Commentary:
;; org-kanban implements a simple kanban management technique
;;; Code:
(defgroup org-kanban nil
"Org-mode kanban helper"
:prefix "org-kanban-"
:group 'org)
(defun org-kanban--get-states ()
"REturn the list of headlines we should consider to be the
'states' of the Kanban board."
(save-excursion
(goto-char (point-min))
(unless (org-at-heading-p)
(outline-next-heading))
(message "Starting with parent %s" (org-entry-get 'nil "ITEM"))
(org-map-entries (lambda ()
(org-entry-get 'nil "ITEM"))
"LEVEL=2"
'tree)))
(defun org-kanban-refresh ()
"Urgh - this needs refactoring!"
(when-let ((local-kanban kanban-heading)
(local-buffer (current-buffer))
(base-buffer (buffer-base-buffer)))
(pop-to-buffer-same-window base-buffer)
(kill-buffer local-buffer)
(goto-char (point-min))
(goto-char (org-find-exact-headline-in-buffer local-kanban))
(let ((current-prefix-arg '(4)))
(call-interactively 'org-tree-to-indirect-buffer))
(setq-local kanban-heading local-kanban)
(let ((current-prefix-arg '(1)))
(org-cycle)
(org-cycle))))
(defun org-kanban--around-org-refile (orig-fun &rest args)
"Overrides for refile"
(save-excursion
(save-selected-window
(org-entry-put nil "REFILE_TIME" (format-time-string (org-time-stamp-format 'long nil)))
(apply orig-fun args)
(when (local-variable-p 'kanban-heading)
(cl-loop for w in (window-list) do
(select-window w)
(org-kanban-refresh))))))
(defun org-kanban--init-window (states)
"Sets up window splits based on the states provided. Sets
org-refile-targets to a locally useful value."
;; ensure trees are visible
(org-set-startup-visibility)
;; TODO: set this specifically to the provided states
(setq-local org-refile-targets '((nil :level . 2)))
(advice-add 'org-refile :around #'org-kanban--around-org-refile)
(setq org-indirect-buffer-display 'current-window)
(goto-char (point-min))
;; split the window enough times
(cl-loop repeat
(- (length states) 1)
do
(split-window-right))
;; for each state, narrow to an indirect buffer
(cl-loop for s in states
do
(goto-char (point-min))
(goto-char (org-find-exact-headline-in-buffer s))
(let ((current-prefix-arg '(4)))
(call-interactively 'org-tree-to-indirect-buffer))
(setq-local kanban-heading s)
(let ((current-prefix-arg '(1)))
(org-cycle)
(org-cycle))
(other-window 1)))
(defun org-kanban ()
(interactive)
(org-kanban--init-window (org-kanban--get-states)))