-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathinit-org.el
389 lines (303 loc) · 13.9 KB
/
init-org.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
;;; init-org.el --- Org-mode config -*- lexical-binding: t -*-
;;; Commentary:
;; Among settings for many aspects of `org-mode', this code includes
;; an opinionated setup for the Getting Things Done (GTD) system based
;; around the Org Agenda. I have an "inbox.org" file with a header
;; including
;; #+CATEGORY: Inbox
;; #+FILETAGS: INBOX
;; and then set this file as `org-default-notes-file'. Captured org
;; items will then go into this file with the file-level tag, and can
;; be refiled to other locations as necessary.
;; Those other locations are generally other org files, which should
;; be added to `org-agenda-files-list' (along with "inbox.org" org).
;; With that done, there's then an agenda view, accessible via the
;; `org-agenda' command, which gives a convenient overview.
;; `org-todo-keywords' is customised here to provide corresponding
;; TODO states, which should make sense to GTD adherents.
;;; Code:
(when *is-a-mac*
(maybe-require-package 'grab-mac-link))
(maybe-require-package 'org-cliplink)
(define-key global-map (kbd "C-c l") 'org-store-link)
(define-key global-map (kbd "C-c a") 'org-agenda)
(defvar sanityinc/org-global-prefix-map (make-sparse-keymap)
"A keymap for handy global access to org helpers, particularly clocking.")
(define-key sanityinc/org-global-prefix-map (kbd "j") 'org-clock-goto)
(define-key sanityinc/org-global-prefix-map (kbd "l") 'org-clock-in-last)
(define-key sanityinc/org-global-prefix-map (kbd "i") 'org-clock-in)
(define-key sanityinc/org-global-prefix-map (kbd "o") 'org-clock-out)
(define-key global-map (kbd "C-c o") sanityinc/org-global-prefix-map)
;; Various preferences
(setq org-log-done t
org-edit-timestamp-down-means-later t
org-hide-emphasis-markers t
org-catch-invisible-edits 'show
org-export-coding-system 'utf-8
org-fast-tag-selection-single-key 'expert
org-html-validation-link nil
org-export-kill-product-buffer-when-displayed t
org-tags-column 80)
;; Lots of stuff from http://doc.norang.ca/org-mode.html
;; Re-align tags when window shape changes
(with-eval-after-load 'org-agenda
(add-hook 'org-agenda-mode-hook
(lambda () (add-hook 'window-configuration-change-hook 'org-agenda-align-tags nil t))))
(maybe-require-package 'writeroom-mode)
(define-minor-mode prose-mode
"Set up a buffer for prose editing.
This enables or modifies a number of settings so that the
experience of editing prose is a little more like that of a
typical word processor."
:init-value nil :lighter " Prose" :keymap nil
(if prose-mode
(progn
(when (fboundp 'writeroom-mode)
(writeroom-mode 1))
(setq truncate-lines nil)
(setq word-wrap t)
(setq cursor-type 'bar)
(when (eq major-mode 'org)
(kill-local-variable 'buffer-face-mode-face))
(buffer-face-mode 1)
;;(delete-selection-mode 1)
(setq-local blink-cursor-interval 0.6)
(setq-local show-trailing-whitespace nil)
(setq-local line-spacing 0.2)
(setq-local electric-pair-mode nil)
(ignore-errors (flyspell-mode 1))
(visual-line-mode 1))
(kill-local-variable 'truncate-lines)
(kill-local-variable 'word-wrap)
(kill-local-variable 'cursor-type)
(kill-local-variable 'blink-cursor-interval)
(kill-local-variable 'show-trailing-whitespace)
(kill-local-variable 'line-spacing)
(kill-local-variable 'electric-pair-mode)
(buffer-face-mode -1)
;; (delete-selection-mode -1)
(flyspell-mode -1)
(visual-line-mode -1)
(when (fboundp 'writeroom-mode)
(writeroom-mode 0))))
;;(add-hook 'org-mode-hook 'buffer-face-mode)
(setq org-support-shift-select t)
;;; Capturing
(global-set-key (kbd "C-c c") 'org-capture)
(setq org-capture-templates
`(("t" "todo" entry (file "") ; "" => `org-default-notes-file'
"* NEXT %?\n%U\n" :clock-resume t)
("n" "note" entry (file "")
"* %? :NOTE:\n%U\n%a\n" :clock-resume t)
))
;;; Refiling
(setq org-refile-use-cache nil)
;; Targets include this file and any file contributing to the agenda - up to 5 levels deep
(setq org-refile-targets '((nil :maxlevel . 5) (org-agenda-files :maxlevel . 5)))
(with-eval-after-load 'org-agenda
(add-to-list 'org-agenda-after-show-hook 'org-show-entry))
(advice-add 'org-refile :after (lambda (&rest _) (org-save-all-org-buffers)))
;; Exclude DONE state tasks from refile targets
(defun sanityinc/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 'sanityinc/verify-refile-target)
(defun sanityinc/org-refile-anywhere (&optional goto default-buffer rfloc msg)
"A version of `org-refile' which allows refiling to any subtree."
(interactive "P")
(let ((org-refile-target-verify-function))
(org-refile goto default-buffer rfloc msg)))
(defun sanityinc/org-agenda-refile-anywhere (&optional goto rfloc no-update)
"A version of `org-agenda-refile' which allows refiling to any subtree."
(interactive "P")
(let ((org-refile-target-verify-function))
(org-agenda-refile goto rfloc no-update)))
;; Targets start with the file name - allows creating level 1 tasks
;;(setq org-refile-use-outline-path (quote file))
(setq org-refile-use-outline-path t)
(setq org-outline-path-complete-in-steps nil)
;; Allow refile to create parent tasks with confirmation
(setq org-refile-allow-creating-parent-nodes 'confirm)
;;; To-do settings
(setq org-todo-keywords
(quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!/!)")
(sequence "PROJECT(p)" "|" "DONE(d!/!)" "CANCELLED(c@/!)")
(sequence "WAITING(w@/!)" "DELEGATED(e!)" "HOLD(h)" "|" "CANCELLED(c@/!)")))
org-todo-repeat-to-state "NEXT")
(setq org-todo-keyword-faces
(quote (("NEXT" :inherit warning)
("PROJECT" :inherit font-lock-string-face))))
;;; Agenda views
(setq-default org-agenda-clockreport-parameter-plist '(:link t :maxlevel 3))
(let ((active-project-match "-INBOX/PROJECT"))
(setq org-stuck-projects
`(,active-project-match ("NEXT")))
(setq org-agenda-compact-blocks t
org-agenda-sticky t
org-agenda-start-on-weekday nil
org-agenda-span 'day
org-agenda-include-diary nil
org-agenda-sorting-strategy
'((agenda habit-down time-up user-defined-up effort-up category-keep)
(todo category-up effort-up)
(tags category-up effort-up)
(search category-up))
org-agenda-window-setup 'current-window
org-agenda-custom-commands
`(("N" "Notes" tags "NOTE"
((org-agenda-overriding-header "Notes")
(org-tags-match-list-sublevels t)))
("g" "GTD"
((agenda "" nil)
(tags "INBOX"
((org-agenda-overriding-header "Inbox")
(org-tags-match-list-sublevels nil)))
(stuck ""
((org-agenda-overriding-header "Stuck Projects")
(org-agenda-tags-todo-honor-ignore-options t)
(org-tags-match-list-sublevels t)
(org-agenda-todo-ignore-scheduled 'future)))
(tags-todo "-INBOX"
((org-agenda-overriding-header "Next Actions")
(org-agenda-tags-todo-honor-ignore-options t)
(org-agenda-todo-ignore-scheduled 'future)
(org-agenda-skip-function
'(lambda ()
(or (org-agenda-skip-subtree-if 'todo '("HOLD" "WAITING"))
(org-agenda-skip-entry-if 'nottodo '("NEXT")))))
(org-tags-match-list-sublevels t)
(org-agenda-sorting-strategy
'(todo-state-down effort-up category-keep))))
(tags-todo ,active-project-match
((org-agenda-overriding-header "Projects")
(org-tags-match-list-sublevels t)
(org-agenda-sorting-strategy
'(category-keep))))
(tags-todo "-INBOX/-NEXT"
((org-agenda-overriding-header "Orphaned Tasks")
(org-agenda-tags-todo-honor-ignore-options t)
(org-agenda-todo-ignore-scheduled 'future)
(org-agenda-skip-function
'(lambda ()
(or (org-agenda-skip-subtree-if 'todo '("PROJECT" "HOLD" "WAITING" "DELEGATED"))
(org-agenda-skip-subtree-if 'nottododo '("TODO")))))
(org-tags-match-list-sublevels t)
(org-agenda-sorting-strategy
'(category-keep))))
(tags-todo "/WAITING"
((org-agenda-overriding-header "Waiting")
(org-agenda-tags-todo-honor-ignore-options t)
(org-agenda-todo-ignore-scheduled 'future)
(org-agenda-sorting-strategy
'(category-keep))))
(tags-todo "/DELEGATED"
((org-agenda-overriding-header "Delegated")
(org-agenda-tags-todo-honor-ignore-options t)
(org-agenda-todo-ignore-scheduled 'future)
(org-agenda-sorting-strategy
'(category-keep))))
(tags-todo "-INBOX"
((org-agenda-overriding-header "On Hold")
(org-agenda-skip-function
'(lambda ()
(or (org-agenda-skip-subtree-if 'todo '("WAITING"))
(org-agenda-skip-entry-if 'nottodo '("HOLD")))))
(org-tags-match-list-sublevels nil)
(org-agenda-sorting-strategy
'(category-keep))))
;; (tags-todo "-NEXT"
;; ((org-agenda-overriding-header "All other TODOs")
;; (org-match-list-sublevels t)))
)))))
(add-hook 'org-agenda-mode-hook 'hl-line-mode)
;;; Org clock
;; Save the running clock and all clock history when exiting Emacs, load it on startup
(with-eval-after-load 'org
(org-clock-persistence-insinuate))
(setq org-clock-persist t)
(setq org-clock-in-resume t)
;; Save clock data and notes in the LOGBOOK drawer
(setq org-clock-into-drawer t)
;; Save state changes in the LOGBOOK drawer
(setq org-log-into-drawer t)
;; Removes clocked tasks with 0:00 duration
(setq org-clock-out-remove-zero-time-clocks t)
;; Show clock sums as hours and minutes, not "n days" etc.
(setq org-time-clocksum-format
'(:hours "%d" :require-hours t :minutes ":%02d" :require-minutes t))
;;; Show the clocked-in task - if any - in the header line
(defun sanityinc/show-org-clock-in-header-line ()
(setq-default header-line-format '((" " org-mode-line-string " "))))
(defun sanityinc/hide-org-clock-from-header-line ()
(setq-default header-line-format nil))
(add-hook 'org-clock-in-hook 'sanityinc/show-org-clock-in-header-line)
(add-hook 'org-clock-out-hook 'sanityinc/hide-org-clock-from-header-line)
(add-hook 'org-clock-cancel-hook 'sanityinc/hide-org-clock-from-header-line)
(with-eval-after-load 'org-clock
(define-key org-clock-mode-line-map [header-line mouse-2] 'org-clock-goto)
(define-key org-clock-mode-line-map [header-line mouse-1] 'org-clock-menu))
(when (and *is-a-mac* (file-directory-p "/Applications/org-clock-statusbar.app"))
(add-hook 'org-clock-in-hook
(lambda () (call-process "/usr/bin/osascript" nil 0 nil "-e"
(concat "tell application \"org-clock-statusbar\" to clock in \"" org-clock-current-task "\""))))
(add-hook 'org-clock-out-hook
(lambda () (call-process "/usr/bin/osascript" nil 0 nil "-e"
"tell application \"org-clock-statusbar\" to clock out"))))
;; TODO: warn about inconsistent items, e.g. TODO inside non-PROJECT
;; TODO: nested projects!
;;; Archiving
(setq org-archive-mark-done nil)
(setq org-archive-location "%s_archive::* Archive")
(require-package 'org-pomodoro)
(setq org-pomodoro-keep-killed-pomodoro-time t)
(with-eval-after-load 'org-agenda
(define-key org-agenda-mode-map (kbd "P") 'org-pomodoro))
;; ;; Show iCal calendars in the org agenda
;; (when (and *is-a-mac* (require 'org-mac-iCal nil t))
;; (setq org-agenda-include-diary t
;; org-agenda-custom-commands
;; '(("I" "Import diary from iCal" agenda ""
;; ((org-agenda-mode-hook #'org-mac-iCal)))))
;; (add-hook 'org-agenda-cleanup-fancy-diary-hook
;; (lambda ()
;; (goto-char (point-min))
;; (save-excursion
;; (while (re-search-forward "^[a-z]" nil t)
;; (goto-char (match-beginning 0))
;; (insert "0:00-24:00 ")))
;; (while (re-search-forward "^ [a-z]" nil t)
;; (goto-char (match-beginning 0))
;; (save-excursion
;; (re-search-backward "^[0-9]+:[0-9]+-[0-9]+:[0-9]+ " nil t))
;; (insert (match-string 0))))))
(with-eval-after-load 'org
(define-key org-mode-map (kbd "C-M-<up>") 'org-up-element)
(when *is-a-mac*
(define-key org-mode-map (kbd "M-h") nil)
(define-key org-mode-map (kbd "C-c g") 'grab-mac-link)))
(with-eval-after-load 'org
(org-babel-do-load-languages
'org-babel-load-languages
(seq-filter
(lambda (pair)
(locate-library (concat "ob-" (symbol-name (car pair)))))
'((R . t)
(ditaa . t)
(dot . t)
(emacs-lisp . t)
(gnuplot . t)
(haskell . nil)
(latex . t)
(ledger . t)
(ocaml . nil)
(octave . t)
(plantuml . t)
(python . t)
(ruby . t)
(screen . nil)
(sh . t) ;; obsolete
(shell . t)
(sql . t)
(sqlite . t)))))
(provide 'init-org)
;;; init-org.el ends here