summaryrefslogtreecommitdiff
path: root/modules/org-agenda-config.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/org-agenda-config.el')
-rw-r--r--modules/org-agenda-config.el425
1 files changed, 182 insertions, 243 deletions
diff --git a/modules/org-agenda-config.el b/modules/org-agenda-config.el
index 016fffcc..f15e5503 100644
--- a/modules/org-agenda-config.el
+++ b/modules/org-agenda-config.el
@@ -5,277 +5,216 @@
;; Agenda views are tied to the F8 (fate) key.
-;; f8 - DAILY SCHEDULE containing a events with a scheduled date or deadline of
-;; the current day. This is followed by...
-;; - TASK LIST containing tasks from all agenda sources.
+;; f8 - MAIN AGENDA which organizes all tasks and events into:
+;; - all unfinished priority A tasks
+;; - the weekly schedule, including the habit consistency graph
+;; - all priority B and C tasks
-;; C-f8 - TASK LIST containing all tasks from all agenda sources
+;; C-f8 - TASK LIST containing all tasks from all agenda targets.
-;; M-f8 - TASK LIST containing all tasks from the current org-mode buffer.
+;; M-f8 - TASK LIST containing all tasks from just the current org-mode buffer.
;; NOTE:
;; Files that contain information relevant to the agenda will be found in the
;; following places: the schedule-file, org-roam notes tagged as 'Projects' and
;; project todo.org files found in project-dir and code-dir.
-;; How the agenda is created:
-;; The inbox and schedule files are always included first. However, in order to
-;; stay current, the files containing agenda information are queried before
-;; calling the functions in the section org-agenda functions to display the
-;; data. This way, any newly created events from project todo.org files, or
-;; org-roam Project files will be included.
-
;;; Code:
-(with-eval-after-load 'org-roam
-
- ;; ----------------------------- Org TODO Settings ---------------------------
-
- (setq org-todo-keywords '((sequence "TODO(t)" "PROJECT(p)" "DOING(i)"
- "WAITING(w)" "VERIFY(v)" "STALLED(s)"
- "DELEGATED(x)" "|"
- "FAILED(f)" "DONE(d)" "CANCELLED(c)")))
-
- (setq org-todo-keyword-faces
- '(("TODO" . "green")
- ("PROJECT" . "blue")
- ("DOING" . "yellow")
- ("WAITING" . "white")
- ("VERIFY" . "orange")
- ("STALLED" . "light blue")
- ("DELEGATED" . "green")
- ("FAILED" . "red")
- ("DONE" . "dark grey")
- ("CANCELLED" . "dark grey")))
-
- (setq org-highest-priority ?A)
- (setq org-lowest-priority ?D)
- (setq org-default-priority ?D)
- (setq org-priority-faces '((?A . (:foreground "Cyan" :weight bold))
- (?B . (:foreground "Yellow"))
- (?C . (:foreground "Green"))
- (?D . (:foreground "Grey"))))
-
- (setq org-enforce-todo-dependencies t)
- (setq org-enforce-todo-checkbox-dependencies t)
- (setq org-deadline-warning-days 7) ;; warn me w/in a week of deadlines
- (setq org-log-done nil) ;; don't log when tasks was done
-
- ;; inherit parents properties (no schedules or deadlines)
- (setq org-use-property-inheritance t)
-
- ;; ------------------ Org TODO Next/Previous Set Keybindings -----------------
-
- (add-hook 'org-agenda-mode-hook (lambda ()
- (local-set-key (kbd "s-<right>") #'org-agenda-todo-nextset)
- (local-set-key (kbd "s-<left>") #'org-agenda-todo-previousset)))
-
- ;; ------------------------------ Org Super Agenda -----------------------------
-
- (use-package org-super-agenda
- :config (org-super-agenda-mode))
-
-;;;; ORG AGENDA VIEW DEFINITIONS
- (defun cj/agenda-today-view()
- "This agenda from all tasks that are scheduled or have a deadline."
- (setq org-super-agenda-groups
- '((:log t) ; Automatically named "Log"
- (:name "SCHEDULED AND DUE"
- :time-grid t
- :deadline past
- :deadline today
- :scheduled past
- :scheduled today)
- (:habit t)
- (:name "DUE SOON"
- :deadline future)
- (:name "LESS IMPORTANT"
- :scheduled future
- :order 100)
- (:discard (:anything t)))))
-
- (defun cj/agenda-all-view()
- "This agenda is built from all tasks."
- (setq org-super-agenda-groups
- '(
- (:name "Ready To Go"
- :todo "STAGED"
- :todo "READY"
- :order 5)
- (:name "Due Today"
- :deadline past
- :deadline today
- :order 2)
- (:name "Empty Projects"
- :todo "PROJECT"
- :order 85)
- (:name "Delegated"
- :todo "DELEGATED"
- :order 50)
- (:name "Scheduled Later"
- :scheduled future
- :order 75)
- (:name "Scheduled Today"
- :scheduled today
- :scheduled past
- :order 4)
- (:name "In Progress"
- :todo "DOING"
- :order 7)
- (:name "High Priority"
- :priority "A"
- :order 10)
- (:name "Waiting"
- :todo "WAITING"
- :order 60)
- (:name "Upcoming"
- :deadline future
- :order 30)
- (:name "Next Priority"
- :priority "B"
- :order 70)
- (:name "Everything Else"
- :anything t
- :order 90))))
-
- ;; ------------------------------ Add Agenda Time ------------------------------
-
- (defun cj/add-agenda-time (s)
- "Add an event with time S to appear underneath the line-at-point.
-This allows a line to show in an agenda without being scheduled or a deadline."
- (interactive "sTime: ")
- (defvar cj/timeformat "%Y-%m-%d %a")
- (org-end-of-line)
- (save-excursion
- (open-line 1)
- (forward-line 1)
- (insert (concat "<" (format-time-string cj/timeformat (current-time)) " " s ">" ))))
-
- (global-set-key (kbd "M-t") #'cj/add-agenda-time)
-
- ;; ---------------------------- Org Agenda Settings ----------------------------
-
+(use-package org-agenda
+ :ensure nil ;; built-in
+ :after (org org-roam)
+ :config
(setq org-agenda-prefix-format '((agenda . " %i %-25:c%?-12t% s")
(timeline . " % s")
- (todo . " %i %-25:c")
- (tags . " %i %-12:c")
- (search . " %i %-12:c")))
+ (todo . " %i %-25:c")
+ (tags . " %i %-12:c")
+ (search . " %i %-12:c")))
(setq org-agenda-dim-blocked-tasks 'invisible)
(setq org-agenda-skip-scheduled-if-done nil)
- (setq org-agenda-skip-include-deadlines t)
(setq org-agenda-remove-tags t)
(setq org-agenda-compact-blocks t)
- ;; ------------------------ Add Files To Org Agenda List -----------------------
- ;; finds files named 'todo.org' (case insensitive) and adds them to
- ;; org-agenda-files list.
+ ;; display the agenda from the bottom
+ (add-to-list 'display-buffer-alist
+ '("\\*Org Agenda\\*"
+ (display-buffer-reuse-mode-window display-buffer-below-selected)
+ (dedicated . t)
+ (window-height . fit-window-to-buffer)))
- (defun cj/add-files-to-org-agenda-files (directory)
- "Recursively searches for files named 'todo.org',
- Searches in DIRECTORY and adds them to org-project-files."
- (interactive "D")
- (setq org-agenda-files
- (append (directory-files-recursively directory
- "^[Tt][Oo][Dd][Oo]\\.[Oo][Rr][Gg]$" t)
- org-agenda-files)))
+ ;; reset s-left/right each time org-agenda is enabled
+ (add-hook 'org-agenda-mode-hook (lambda ()
+ (local-set-key (kbd "s-<right>") #'org-agenda-todo-nextset)
+ (local-set-key (kbd "s-<left>")
+ #'org-agenda-todo-previousset)))
+ ;; build org-agenda-list for the first time after emacs init completes.
+ (add-hook 'emacs-startup-hook #'cj/build-org-agenda-list))
- ;; NOTE: the following functions require org-roam functionality
- (with-eval-after-load 'org-roam-config
- ;; ---------------------------- Rebuild Org Agenda ---------------------------
+;; ------------------------ Add Files To Org Agenda List -----------------------
+;; finds files named 'todo.org' (case insensitive) and adds them to
+;; org-agenda-files list.
- (defun cj/build-org-agenda-list ()
- "Rebuilds the org agenda list.
-Begins with the inbox-file and schedule-file, then searches for org-roam
-Projects and adds all todo.org files from code and project directories."
- (interactive)
- ;; reset org-agenda-files to inbox-file
- (setq org-agenda-files (list inbox-file schedule-file))
- (let ((new-files
- (append
- (cj/org-roam-list-notes-by-tag "Project"))))
- (dolist (file new-files)
- (unless (member file org-agenda-files)
- (setq org-agenda-files (cons file org-agenda-files)))))
+(defun cj/add-files-to-org-agenda-files-list (directory)
+ "Search for files named \\='todo.org\\=' add them to org-project-files.
+DIRECTORY is a string of the path to begin the search."
+ (interactive "D")
+ (setq org-agenda-files
+ (append (directory-files-recursively directory
+ "^[Tt][Oo][Dd][Oo]\\.[Oo][Rr][Gg]$" t)
+ org-agenda-files)))
- (cj/add-files-to-org-agenda-files projects-dir)
- (cj/add-files-to-org-agenda-files code-dir))
+;; ---------------------------- Rebuild Org Agenda ---------------------------
+;; builds the org agenda list from all agenda targets.
+;; agenda targets is the schedule, project todos, inbox, and org roam projects.
- ;; build org-agenda-list for the first time once emacs init is complete.
- (add-hook 'emacs-startup-hook 'cj/build-org-agenda-list)
-
- ;; ------------------------ Org Agenda Display Functions -----------------------
-
- (defun cj/agenda-all-agenda-files-day ()
- "Display an \'org-agenda\' schedule with tasks covering today.
+(defun cj/build-org-agenda-list ()
+ "Rebuilds the org agenda list.
+Begins with the inbox-file and schedule-file, then searches for org-roam
+Projects and adds all todo.org files from code and project directories."
+ (interactive)
+ ;; reset org-agenda-files to inbox-file
+ (setq org-agenda-files (list inbox-file schedule-file))
+ (let ((new-files
+ (append
+ (cj/org-roam-list-notes-by-tag "Project"))))
+ (dolist (file new-files)
+ (unless (member file org-agenda-files)
+ (setq org-agenda-files (cons file org-agenda-files)))))
+
+ (cj/add-files-to-org-agenda-files-list projects-dir)
+ (cj/add-files-to-org-agenda-files-list code-dir))
+
+;; ------------------------------ Agenda List All ------------------------------
+;; an agenda listing tasks from all available agenda targets.
+
+(defun cj/todo-list-all-agenda-files ()
+ "Displays an \\='org-agenda\\=' todo list.
The contents of the agenda will be built from org-project-files and org-roam
files that have project in their filetag."
- (interactive)
- (cj/build-org-agenda-list)
- (setq org-agenda-span 'day)
- (cj/agenda-today-view)
- (org-agenda "a" "a"))
- (global-set-key (kbd "<f8>") #'cj/agenda-all-agenda-files-day)
+ (interactive)
+ (cj/build-org-agenda-list)
+ (org-agenda "a" "t"))
+(global-set-key (kbd "C-<f8>") #'cj/todo-list-all-agenda-files)
+
+;; ------------------------- Agenda List Current Buffer ------------------------
+;; an agenda listing tasks from just the current buffer.
+
+(defun cj/todo-list-from-this-buffer ()
+ "Displays an \\='org-agenda\\=' todo list built from the current buffer.
+If the current buffer isn't an org buffer, inform the user."
+ (interactive)
+ (if (eq major-mode 'org-mode)
+ (let ((org-agenda-files (list buffer-file-name)))
+ (org-agenda "a" "t"))
+ (message (concat "Your org agenda request based on '" (buffer-name (current-buffer))
+ "' failed because it's not an org buffer."))))
+(global-set-key (kbd "M-<f8>") #'cj/todo-list-from-this-buffer)
+
+;; -------------------------------- Main Agenda --------------------------------
+;; my custom agenda command from all available agenda targets. adapted from:
+;; https://blog.aaronbieber.com/2016/09/24/an-agenda-for-life-with-org-mode.html
+
+(defvar cj/main-agenda-hipri-title "\nHIGH PRIORITY UNRESOLVED TASKS\n"
+ "String to announce the high priority section of the main agenda.")
+
+(defvar cj/main-agenda-schedule-title "\nSCHEDULE\n"
+ "String to announce the schedule section of the main agenda.")
+
+(defvar cj/main-agenda-tasks-title "\nPRIORITY B AND C\n"
+ "String to announce the schedule section of the main agenda.")
+
+(defun cj/org-skip-subtree-if-habit ()
+ "Skip an agenda entry if it has a STYLE property equal to \"habit\"."
+ (let ((subtree-end (save-excursion (org-end-of-subtree t))))
+ (if (string= (org-entry-get nil "STYLE") "habit")
+ subtree-end
+ nil)))
+
+(defun cj/org-skip-subtree-if-priority (priority)
+ "Skip an agenda subtree if it has a priority of PRIORITY.
+PRIORITY may be one of the characters ?A, ?B, or ?C."
+ (let ((subtree-end (save-excursion (org-end-of-subtree t)))
+ (pri-value (* 1000 (- org-lowest-priority priority)))
+ (pri-current (org-get-priority (thing-at-point 'line t))))
+ (if (= pri-value pri-current)
+ subtree-end
+ nil)))
+
+(defun cj/org-skip-subtree-if-keyword (keywords)
+ "Skip an agenda subtree if it has a TODO keyword in KEYWORDS.
+KEYWORDS must be a list of strings."
+ (let ((subtree-end (save-excursion (org-end-of-subtree t))))
+ (if (member (org-get-todo-state) keywords)
+ subtree-end
+ nil)))
+
+(setq org-agenda-custom-commands
+ '(("d" "Daily Agenda with Tasks"
+ ((tags "PRIORITY=\"A\""
+ ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
+ (org-agenda-overriding-header cj/main-agenda-hipri-title)))
+ (agenda "" ((org-agenda-ndays 1)
+ (org-agenda-overriding-header cj/main-agenda-schedule-title)))
+ (alltodo ""
+ ((org-agenda-skip-function '(or (cj/org-skip-subtree-if-habit)
+ (cj/org-skip-subtree-if-priority ?A)
+ (cj/org-skip-subtree-if-priority ?D)
+ (cj/org-skip-subtree-if-keyword '("PROJECT"))
+ (org-agenda-skip-if nil '(scheduled deadline))))
+ (org-agenda-overriding-header cj/main-agenda-tasks-title))))
+ ((org-agenda-compact-blocks nil)))))
+
+
+ (defun cj/main-agenda-display ()
+ "Display the main \'org-agenda\' display.
+This uses all org-agenda targes and presents three sections:
+- all unfinished priority A tasks
+- the weekly schedule, including the habit consistency graph
+- all priority B and C tasks"
+ (interactive)
+ (cj/build-org-agenda-list)
+ (org-agenda "a" "d"))
+(global-set-key (kbd "<f8>") #'cj/main-agenda-display)
+;; ------------------------- Add Timestamp To Org Entry ------------------------
+;; simply adds a timestamp to put the org entry on an agenda
- (defun cj/agenda-all-agenda-files-week ()
- "Display an 'org-agenda' schedule with tasks covering this week.
-The contents of the agenda will be built from org-project-files and org-roam
-files that have project in their filetag."
- (interactive)
- (cj/build-org-agenda-list)
- (setq org-agenda-span 'week)
- (cj/agenda-today-view)
- (org-agenda "a" "a"))
- (global-set-key (kbd "s-<f8>") #'cj/agenda-all-agenda-files-week)
-
- (defun cj/todo-list-all-agenda-files ()
- "Displays an 'org-agenda' todo list.
-The contents of the agenda will be built from org-project-files and org-roam
-files that have project in their filetag."
- (interactive)
- (cj/build-org-agenda-list)
- (cj/agenda-all-view)
- (org-agenda "a" "t"))
- (global-set-key (kbd "C-<f8>") #'cj/todo-list-all-agenda-files)
-
- (defun cj/todo-list-from-this-buffer ()
- "Displays an 'org-agenda' todo list built from the current buffer.
- If the current buffer isn't an org buffer, inform the user."
- (interactive)
- (if (eq major-mode 'org-mode)
- (let ((org-agenda-files (list buffer-file-name)))
- (cj/agenda-all-view)
- (org-agenda "a" "t"))
- (message (concat "Your org agenda request based on '" (buffer-name (current-buffer))
- "' failed because it's not an org buffer."))))
- (global-set-key (kbd "M-<f8>") #'cj/todo-list-from-this-buffer)
-
- ;; --------------------------- Notifications / Alerts --------------------------
- ;; send libnotify notifications about agenda items
-
- (use-package alert
- :defer .5
- :config
- (setq alert-fade-time 10) ;; secs to vanish alert
- (setq alert-default-style 'libnotify)) ;; work with dunst
-
- (use-package org-alert
- :defer .5
- :bind
- ("C-c A" . org-alert-check)
- :config
- (setq alert-default-style 'libnotify) ;; work with dunst
- (setq org-alert-interval 300) ;; seconds checks agenda is checked (300 = 5 mins)
- (setq org-alert-notify-cutoff 5) ;; minutes before a deadline to send alert
- (setq org-alert-notify-after-event-cutoff 10) ;; mins post deadline to stop alerts
- (setq org-alert-notification-title "Reminder")
- (org-alert-enable))
-
-
- ) ;; end with-eval-after-load 'org-roam-config
- ) ;; end with-eval-after-load 'org-roam
+(defun cj/add-timestamp-to-org-entry (s)
+ "Add an event with time S to appear underneath the line-at-point.
+This allows a line to show in an agenda without being scheduled or a deadline."
+ (interactive "sTime: ")
+ (defvar cj/timeformat "%Y-%m-%d %a")
+ (org-end-of-line)
+ (save-excursion
+ (open-line 1)
+ (forward-line 1)
+ (insert (concat "<" (format-time-string cj/timeformat (current-time)) " " s ">" ))))
+(global-set-key (kbd "M-t") #'cj/add-timestamp-to-org-entry)
+
+;; --------------------------- Notifications / Alerts --------------------------
+;; send libnotify notifications about agenda items
+
+(use-package alert
+ :defer .5
+ :after org-agenda
+ :config
+ (setq alert-fade-time 10) ;; secs to vanish alert
+ (setq alert-default-style 'libnotify)) ;; work with dunst
+
+(use-package org-alert
+ :defer .5
+ :after alert
+ :bind
+ ("C-c A" . org-alert-check)
+ :config
+ (setq alert-default-style 'libnotify) ;; work with dunst
+ (setq org-alert-interval 180) ;; seconds between agenda checks (180 = 3 mins)
+ (setq org-alert-notify-cutoff 5) ;; minutes before a deadline to send alert
+ (setq org-alert-notify-after-event-cutoff 10) ;; mins post deadline to stop alerts
+ (setq org-alert-notification-title "Reminder")
+ (org-alert-enable))
(provide 'org-agenda-config)
;;; org-agenda-config.el ends here