From 492049470fa3d486d909f50ddca59b335c8a44bb Mon Sep 17 00:00:00 2001 From: Raul Benencia Date: Tue, 21 Feb 2023 19:44:16 -0800 Subject: emacs: reorganize org files --- .emacs | 3 - .emacs.local.d/lisp/packages/rul-org-agenda.el | 40 ++ .emacs.local.d/lisp/packages/rul-org-journal.el | 16 + .emacs.local.d/lisp/packages/rul-org-roam.el | 26 + .emacs.local.d/lisp/packages/rul-org.el | 528 +++++++++++++++++ .emacs.local.d/modes/org-journal.el | 14 - .emacs.local.d/modes/org-roam.el | 23 - .emacs.local.d/modes/org.el | 715 ------------------------ 8 files changed, 610 insertions(+), 755 deletions(-) create mode 100644 .emacs.local.d/lisp/packages/rul-org-agenda.el create mode 100644 .emacs.local.d/lisp/packages/rul-org-journal.el create mode 100644 .emacs.local.d/lisp/packages/rul-org-roam.el create mode 100644 .emacs.local.d/lisp/packages/rul-org.el delete mode 100644 .emacs.local.d/modes/org-journal.el delete mode 100644 .emacs.local.d/modes/org-roam.el delete mode 100644 .emacs.local.d/modes/org.el diff --git a/.emacs b/.emacs index 93ebb9b..2d9d0b2 100644 --- a/.emacs +++ b/.emacs @@ -23,9 +23,6 @@ (load-file "~/.emacs.local.d/modes/markdown.el") (load-file "~/.emacs.local.d/modes/magit.el") (load-file "~/.emacs.local.d/modes/notmuch.el") -(load-file "~/.emacs.local.d/modes/org.el") -(load-file "~/.emacs.local.d/modes/org-journal.el") -(load-file "~/.emacs.local.d/modes/org-roam.el") (load-file "~/.emacs.local.d/modes/projectile.el") (load-file "~/.emacs.local.d/modes/tabbar.el") (load-file "~/.emacs.local.d/modes/which-key.el") diff --git a/.emacs.local.d/lisp/packages/rul-org-agenda.el b/.emacs.local.d/lisp/packages/rul-org-agenda.el new file mode 100644 index 0000000..f978ea7 --- /dev/null +++ b/.emacs.local.d/lisp/packages/rul-org-agenda.el @@ -0,0 +1,40 @@ +(require 'org) + +(global-set-key (kbd "") #'org-agenda) +(global-set-key (kbd "C-c a") #'org-agenda) + +;; AGENDA VIEW ;; + +(setq org-agenda-files my-org-agenda-files) +(setq org-agenda-custom-commands my-org-agenda-custom-commands) + +;; Do not dim blocked tasks +(setq org-agenda-compact-blocks nil) +(setq org-agenda-dim-blocked-tasks nil) +(setq org-agenda-block-separator 61) + +;; Agenda log mode items to display (closed and state changes by default) +(setq org-agenda-log-mode-items (quote (closed state))) + +; For tag searches ignore tasks with scheduled and deadline dates +(setq org-agenda-tags-todo-honor-ignore-options t) + +;; Credits: https://200ok.ch/posts/2022-02-13_integrating_org_mode_agenda_into_other_calendar_apps.html +(defun org-agenda-export-to-ics () + ;; Run all custom agenda commands that have a file argument. + (org-batch-store-agenda-views) + + ;; Org mode correctly exports TODO keywords as VTODO events in ICS. + ;; However, some proprietary calendars do not really work with + ;; standards (looking at you Google), so VTODO is ignored and only + ;; VEVENT is read. + (with-current-buffer (find-file-noselect my-org-agenda-private-local-path) + (goto-char (point-min)) + (while (re-search-forward "VTODO" nil t) + (replace-match "VEVENT")) + (save-buffer)) + + ;; Copy the ICS file to a remote server (Tramp paths work). + (copy-file my-org-agenda-private-local-path my-org-agenda-private-remote-path t)) + +(provide 'rul-org-agenda) diff --git a/.emacs.local.d/lisp/packages/rul-org-journal.el b/.emacs.local.d/lisp/packages/rul-org-journal.el new file mode 100644 index 0000000..ab07a19 --- /dev/null +++ b/.emacs.local.d/lisp/packages/rul-org-journal.el @@ -0,0 +1,16 @@ +(use-package org-journal + :ensure t + :init + ;; Change default prefix key; needs to be set before loading org-journal + (setq org-journal-prefix-key "C-c j ") + (setq org-journal-file-format my-org-journal-file-format) + (setq org-journal-enable-agenda-integration t) + :config + (require 'rul-config-org) + (setq org-journal-dir my-org-journal-dir + org-journal-file-type my-org-journal-file-type + org-journal-time-prefix my-org-journal-time-prefix + org-journal-time-format my-org-journal-time-format + org-journal-date-format "%A, %d %B %Y")) + +(provide 'rul-org-journal) diff --git a/.emacs.local.d/lisp/packages/rul-org-roam.el b/.emacs.local.d/lisp/packages/rul-org-roam.el new file mode 100644 index 0000000..0184459 --- /dev/null +++ b/.emacs.local.d/lisp/packages/rul-org-roam.el @@ -0,0 +1,26 @@ +(use-package org-roam + :ensure t + :after rul-org + :custom + (org-roam-directory my-org-roam-directory) + :init + (setq org-roam-v2-ack t) + :bind (("C-c n l" . org-roam-buffer-toggle) + ("C-c n f" . org-roam-node-find) + ("C-c n i" . org-roam-node-insert)) + :config + (require 'rul-config-org) + (org-roam-setup) + (add-to-list 'display-buffer-alist + '("\\*org-roam\\*" + (display-buffer-in-direction) + (direction . right) + (window-width . 0.33) + (window-height . fit-window-to-buffer))) + (setq org-roam-mode-section-functions + (list #'org-roam-backlinks-section + #'org-roam-reflinks-section + #'org-roam-unlinked-references-section)) + ) + +(provide 'rul-org-roam) diff --git a/.emacs.local.d/lisp/packages/rul-org.el b/.emacs.local.d/lisp/packages/rul-org.el new file mode 100644 index 0000000..5c96906 --- /dev/null +++ b/.emacs.local.d/lisp/packages/rul-org.el @@ -0,0 +1,528 @@ +;; Debian packages: elpa-org elpa-org-bullets +;; Elpa packages: org-modern +(require 'org) +(require 'org-capture) +(require 'org-protocol) +(require 'org-habit) +(require 'org-bullets) + +(require 'org-modern) + +(require 'rul-config-org) +(require 'rul-org-agenda) + +(setq org-cycle-separator-lines 0) +(setq org-startup-indented t) +(setq org-hide-leading-stars nil) + +(add-hook 'org-mode-hook 'turn-off-auto-fill) +(add-hook 'org-mode-hook 'visual-line-mode) + +(setq org-startup-indented t + org-bullets-bullet-list '(" ") ;; no bullets, needs org-bullets package + org-pretty-entities nil + org-hide-emphasis-markers t + ;; show actually italicized text instead of /italicized text/ + org-fontify-whole-heading-line t + org-fontify-done-headline t + org-fontify-quote-and-verse-blocks t) + +;; ORG BINDINGS ;; +(global-set-key (kbd "C-c l") #'org-store-link) +(global-set-key (kbd "C-c c") #'org-capture) +(global-set-key (kbd "C-c s") #'org-schedule) + +;; ORG STATES ;; +(setq org-todo-keywords + (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") + (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "PHONE" "MEETING")))) + +(setq org-use-fast-todo-selection t) + +(setq org-todo-state-tags-triggers + (quote (("CANCELLED" ("CANCELLED" . t)) + ("WAITING" ("WAITING" . t)) + ("HOLD" ("WAITING") ("HOLD" . t)) + (done ("WAITING") ("HOLD")) + ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) + ("NEXT" ("WAITING") ("CANCELLED") ("HOLD")) + ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))) + +(setq org-enforce-todo-dependencies t) +(setq org-log-done (quote time)) +(setq org-log-redeadline (quote time)) +(setq org-log-reschedule (quote time)) + +;; CAPTURE ;; +(setq org-default-notes-file my-org-refile-path) +(setq org-capture-templates + (quote + ( + ("w" "Todo" entry (file+headline my-org-refile-path "Tasks") + "* TODO " + :empty-lines 1) + ("m" + "Capture incoming email" + entry + (file+headline my-org-refile-path "Incoming") + "* TODO Re: %:description\n\n Source: %u, %a\n" + :empty-lines 1) + ))) + +(add-hook 'org-capture-mode-hook 'delete-other-windows) +(setq my-org-protocol-flag nil) + +(defadvice org-capture-finalize (after delete-frame-at-end activate) + "Delete frame at remember finalization" + (progn (if my-org-protocol-flag (delete-frame)) + (setq my-org-protocol-flag nil))) + +(defadvice org-capture-kill (after delete-frame-at-end activate) + "Delete frame at remember abort" + (progn (if my-org-protocol-flag (delete-frame)) + (setq my-org-protocol-flag nil))) + +(defadvice org-protocol-capture (before set-org-protocol-flag activate) + (setq my-org-protocol-flag t)) + + +;; REFILE ;; + +; Targets include this file and any file contributing to the agenda - up to 3 levels deep +(setq org-refile-targets + '((nil :maxlevel . 3) + (org-agenda-files :maxlevel . 3))) + +; Targets complete directly with IDO +(setq org-outline-path-complete-in-steps nil) + +; Allow refile to create parent tasks with confirmation +(setq org-refile-allow-creating-parent-nodes (quote confirm)) + +(defun bh/is-project-p () + "Any task with a todo keyword subtask" + (save-restriction + (widen) + (let ((has-subtask) + (subtree-end (save-excursion (org-end-of-subtree t))) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (save-excursion + (forward-line 1) + (while (and (not has-subtask) + (< (point) subtree-end) + (re-search-forward "^\*+ " subtree-end t)) + (when (member (org-get-todo-state) org-todo-keywords-1) + (setq has-subtask t)))) + (and is-a-task has-subtask)))) + +(defun bh/is-project-subtree-p () + "Any task with a todo keyword that is in a project subtree. +Callers of this function already widen the buffer view." + (let ((task (save-excursion (org-back-to-heading 'invisible-ok) + (point)))) + (save-excursion + (bh/find-project-task) + (if (equal (point) task) + nil + t)))) + +(defun bh/is-task-p () + "Any task with a todo keyword and no subtask" + (save-restriction + (widen) + (let ((has-subtask) + (subtree-end (save-excursion (org-end-of-subtree t))) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (save-excursion + (forward-line 1) + (while (and (not has-subtask) + (< (point) subtree-end) + (re-search-forward "^\*+ " subtree-end t)) + (when (member (org-get-todo-state) org-todo-keywords-1) + (setq has-subtask t)))) + (and is-a-task (not has-subtask))))) + +(defun bh/is-subproject-p () + "Any task which is a subtask of another project" + (let ((is-subproject) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (save-excursion + (while (and (not is-subproject) (org-up-heading-safe)) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq is-subproject t)))) + (and is-a-task is-subproject))) + +(defun bh/list-sublevels-for-projects-indented () + "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. + This is normally used by skipping functions where this variable is already local to the agenda." + (if (marker-buffer org-agenda-restrict-begin) + (setq org-tags-match-list-sublevels 'indented) + (setq org-tags-match-list-sublevels nil)) + nil) + +(defun bh/list-sublevels-for-projects () + "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. + This is normally used by skipping functions where this variable is already local to the agenda." + (if (marker-buffer org-agenda-restrict-begin) + (setq org-tags-match-list-sublevels t) + (setq org-tags-match-list-sublevels nil)) + nil) + +(defvar bh/hide-scheduled-and-waiting-next-tasks t) + +(defun bh/toggle-next-task-display () + (interactive) + (setq bh/hide-scheduled-and-waiting-next-tasks (not bh/hide-scheduled-and-waiting-next-tasks)) + (when (equal major-mode 'org-agenda-mode) + (org-agenda-redo)) + (message "%s WAITING and SCHEDULED NEXT Tasks" (if bh/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) + +(defun bh/skip-stuck-projects () + "Skip trees that are not stuck projects" + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (if (bh/is-project-p) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (has-next )) + (save-excursion + (forward-line 1) + (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) + (unless (member "WAITING" (org-get-tags-at)) + (setq has-next t)))) + (if has-next + nil + next-headline)) ; a stuck project, has subtasks but no next task + nil)))) + +(defun bh/skip-non-stuck-projects () + "Skip trees that are not stuck projects" + ;; (bh/list-sublevels-for-projects-indented) + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (if (bh/is-project-p) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (has-next )) + (save-excursion + (forward-line 1) + (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) + (unless (member "WAITING" (org-get-tags-at)) + (setq has-next t)))) + (if has-next + next-headline + nil)) ; a stuck project, has subtasks but no next task + next-headline)))) + +(defun bh/skip-non-projects () + "Skip trees that are not projects" + ;; (bh/list-sublevels-for-projects-indented) + (if (save-excursion (bh/skip-non-stuck-projects)) + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((bh/is-project-p) + nil) + ((and (bh/is-project-subtree-p) (not (bh/is-task-p))) + nil) + (t + subtree-end)))) + (save-excursion (org-end-of-subtree t)))) + +(defun bh/skip-non-tasks () + "Show non-project tasks. +Skip project and sub-project tasks, habits, and project related tasks." + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (cond + ((bh/is-task-p) + nil) + (t + next-headline))))) + +(defun bh/skip-project-trees-and-habits () + "Skip trees that are projects" + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((bh/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + (t + nil))))) + +(defun bh/skip-projects-and-habits-and-single-tasks () + "Skip trees that are projects, tasks that are habits, single non-project tasks" + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (cond + ((org-is-habit-p) + next-headline) + ((and bh/hide-scheduled-and-waiting-next-tasks + (member "WAITING" (org-get-tags-at))) + next-headline) + ((bh/is-project-p) + next-headline) + ((and (bh/is-task-p) (not (bh/is-project-subtree-p))) + next-headline) + (t + nil))))) + +(defun bh/skip-project-tasks-maybe () + "Show tasks related to the current restriction. +When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. +When not restricted, skip project and sub-project tasks, habits, and project related tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (next-headline (save-excursion (or (outline-next-heading) (point-max)))) + (limit-to-project (marker-buffer org-agenda-restrict-begin))) + (cond + ((bh/is-project-p) + next-headline) + ((org-is-habit-p) + subtree-end) + ((and (not limit-to-project) + (bh/is-project-subtree-p)) + subtree-end) + ((and limit-to-project + (bh/is-project-subtree-p) + (member (org-get-todo-state) (list "NEXT"))) + subtree-end) + (t + nil))))) + +(defun bh/skip-project-tasks () + "Show non-project tasks. +Skip project and sub-project tasks, habits, and project related tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((bh/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + ((bh/is-project-subtree-p) + subtree-end) + (t + nil))))) + +(defun bh/skip-non-project-tasks () + "Show project tasks. +Skip project and sub-project tasks, habits, and loose non-project tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (cond + ((bh/is-project-p) + next-headline) + ((org-is-habit-p) + subtree-end) + ((and (bh/is-project-subtree-p) + (member (org-get-todo-state) (list "NEXT"))) + subtree-end) + ((not (bh/is-project-subtree-p)) + subtree-end) + (t + nil))))) + +(defun bh/skip-projects-and-habits () + "Skip trees that are projects and tasks that are habits" + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((bh/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + (t + nil))))) + +(defun bh/skip-non-subprojects () + "Skip trees that are not projects" + (let ((next-headline (save-excursion (outline-next-heading)))) + (if (bh/is-subproject-p) + nil + next-headline))) + +;; CLOCKING ;; +;; Resume clocking task when emacs is restarted +(org-clock-persistence-insinuate) +;; +;; Show lot of clocking history so it's easy to pick items off the C-F11 list +(setq org-clock-history-length 23) +;; Resume clocking task on clock-in if the clock is open +(setq org-clock-in-resume t) +;; Change tasks to NEXT when clocking in +(setq org-clock-in-switch-to-state 'bh/clock-in-to-next) +;; Separate drawers for clocking and logs +(setq org-drawers (quote ("PROPERTIES" "LOGBOOK"))) +;; Save clock data and state changes and notes in the LOGBOOK drawer +(setq org-clock-into-drawer t) +;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration +(setq org-clock-out-remove-zero-time-clocks t) +;; Clock out when moving task to a done state +(setq org-clock-out-when-done t) +;; Save the running clock and all clock history when exiting Emacs, load it on startup +(setq org-clock-persist t) +;; Do not prompt to resume an active clock +(setq org-clock-persist-query-resume nil) +;; Enable auto clock resolution for finding open clocks +(setq org-clock-auto-clock-resolution (quote when-no-clock-is-running)) +;; Include current clocking task in clock reports +(setq org-clock-report-include-clocking-task t) + + +(setq bh/keep-clock-running nil) + +(defun bh/clock-in-to-next (kw) + "Switch a task from TODO to NEXT when clocking in. +Skips capture tasks, projects, and subprojects. +Switch projects and subprojects from NEXT back to TODO" + (when (not (and (boundp 'org-capture-mode) org-capture-mode)) + (cond + ((and (member (org-get-todo-state) (list "TODO")) + (bh/is-task-p)) + "NEXT") + ((and (member (org-get-todo-state) (list "NEXT")) + (bh/is-project-p)) + "TODO")))) + +(defun bh/find-project-task () + "Move point to the parent (project) task if any" + (save-restriction + (widen) + (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) + (while (org-up-heading-safe) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq parent-task (point)))) + (goto-char parent-task) + parent-task))) + +(defun bh/punch-in (arg) + "Start continuous clocking and set the default task to the +selected task. If no task is selected set the Organization task +as the default task." + (interactive "p") + (setq bh/keep-clock-running t) + (if (equal major-mode 'org-agenda-mode) + ;; + ;; We're in the agenda + ;; + (let* ((marker (org-get-at-bol 'org-hd-marker)) + (tags (org-with-point-at marker (org-get-tags-at)))) + (if (and (eq arg 4) tags) + (org-agenda-clock-in '(16)) + (bh/clock-in-organization-task-as-default))) + ;; + ;; We are not in the agenda + ;; + (save-restriction + (widen) + ; Find the tags on the current task + (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4)) + (org-clock-in '(16)) + (bh/clock-in-organization-task-as-default))))) + +(defun bh/punch-out () + (interactive) + (setq bh/keep-clock-running nil) + (when (org-clock-is-active) + (org-clock-out)) + (org-agenda-remove-restriction-lock)) + +(defun bh/clock-in-default-task () + (save-excursion + (org-with-point-at org-clock-default-task + (org-clock-in)))) + +(defun bh/clock-in-parent-task () + "Move point to the parent (project) task if any and clock in" + (let ((parent-task)) + (save-excursion + (save-restriction + (widen) + (while (and (not parent-task) (org-up-heading-safe)) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq parent-task (point)))) + (if parent-task + (org-with-point-at parent-task + (org-clock-in)) + (when bh/keep-clock-running + (bh/clock-in-default-task))))))) + +(defvar bh/organization-task-id "eb155a82-92b2-4f25-a3c6-0304591af2f9") + +(defun bh/clock-in-organization-task-as-default () + (interactive) + (org-with-point-at (org-id-find bh/organization-task-id 'marker) + (org-clock-in '(16)))) + +(defun bh/clock-out-maybe () + (when (and bh/keep-clock-running + (not org-clock-clocking-in) + (marker-buffer org-clock-default-task) + (not org-clock-resolving-clocks-due-to-idleness)) + (bh/clock-in-parent-task))) + +(add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append) + + +;; ORG REPORTS ;; +; Set default column view headings: Task Effort Clock_Summary +(setq org-columns-default-format "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM") + +(defun my-org-clocktable-indent-string (level) + (if (= level 1) + "" + (let ((str "^")) + (while (> level 2) + (setq level (1- level) + str (concat str "--"))) + (concat str "-> ")))) + +(advice-add 'org-clocktable-indent-string :override #'my-org-clocktable-indent-string) + +(setq org-clock-clocktable-default-properties '(:maxlevel 4 :scope file :formula %)) + +; global Effort estimate values +; global STYLE property values for completion +(setq org-global-properties (quote (("Effort_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00") + ("STYLE_ALL" . "habit")))) + +;; TAGS ;; +; Tags with fast selection keys +(setq org-tag-alist (quote ((:startgroup) + ("@errand" . ?e) + ("@office" . ?o) + ("@home" . ?H) + (:endgroup) + ("WAITING" . ?w) + ("HOLD" . ?h) + ("PERSONAL" . ?P) + ("WORK" . ?W) + ("ORG" . ?O) + ("NOTE" . ?n) + ("CANCELLED" . ?c) + ("FLAGGED" . ??)))) + +(setq org-stuck-projects + '("+LEVEL=2+PROJECT/-MAYBE-DONE" ("NEXT") ("@shop") + "\\")) + +; Allow setting single tags without the menu +(setq org-fast-tag-selection-single-key (quote expert)) + +;; org-modern +(add-hook 'org-mode-hook 'org-modern-mode) +(add-hook 'org-agenda-finalize-hook #'org-modern-agenda) + +(provide 'rul-org) diff --git a/.emacs.local.d/modes/org-journal.el b/.emacs.local.d/modes/org-journal.el deleted file mode 100644 index 7bf217d..0000000 --- a/.emacs.local.d/modes/org-journal.el +++ /dev/null @@ -1,14 +0,0 @@ -(use-package org-journal - :ensure t - :init - ;; Change default prefix key; needs to be set before loading org-journal - (setq org-journal-prefix-key "C-c j ") - (setq org-journal-file-format my-org-journal-file-format) - (setq org-journal-enable-agenda-integration t) - :config - (require 'rul-config-org) - (setq org-journal-dir my-org-journal-dir - org-journal-file-type my-org-journal-file-type - org-journal-time-prefix my-org-journal-time-prefix - org-journal-time-format my-org-journal-time-format - org-journal-date-format "%A, %d %B %Y")) diff --git a/.emacs.local.d/modes/org-roam.el b/.emacs.local.d/modes/org-roam.el deleted file mode 100644 index 422eb93..0000000 --- a/.emacs.local.d/modes/org-roam.el +++ /dev/null @@ -1,23 +0,0 @@ -(use-package org-roam - :ensure t - :custom - (org-roam-directory my-org-roam-directory) - :init - (setq org-roam-v2-ack t) - :bind (("C-c n l" . org-roam-buffer-toggle) - ("C-c n f" . org-roam-node-find) - ("C-c n i" . org-roam-node-insert)) - :config - (require 'rul-config-org) - (org-roam-setup) - (add-to-list 'display-buffer-alist - '("\\*org-roam\\*" - (display-buffer-in-direction) - (direction . right) - (window-width . 0.33) - (window-height . fit-window-to-buffer))) - (setq org-roam-mode-section-functions - (list #'org-roam-backlinks-section - #'org-roam-reflinks-section - #'org-roam-unlinked-references-section)) - ) diff --git a/.emacs.local.d/modes/org.el b/.emacs.local.d/modes/org.el deleted file mode 100644 index c22047e..0000000 --- a/.emacs.local.d/modes/org.el +++ /dev/null @@ -1,715 +0,0 @@ -;; Debian packages: elpa-org elpa-org-bullets -;; Elpa packages: org-modern -(require 'org-capture) -(require 'org-protocol) -(require 'org-habit) -(require 'org-bullets) - -(require 'org-modern) - -(require 'rul-config-org) - -;; -------- -;; Org mode -;; -------- - -(require 'org) - -(setq org-cycle-separator-lines 0) -(setq org-startup-indented t) -(setq org-hide-leading-stars nil) - -(add-hook 'org-mode-hook 'turn-off-auto-fill) -(add-hook 'org-mode-hook 'visual-line-mode) - -(setq org-startup-indented t - org-bullets-bullet-list '(" ") ;; no bullets, needs org-bullets package - org-pretty-entities nil - org-hide-emphasis-markers t - ;; show actually italicized text instead of /italicized text/ - org-fontify-whole-heading-line t - org-fontify-done-headline t - org-fontify-quote-and-verse-blocks t) - -;; ORG BINDINGS ;; -(global-set-key (kbd "") #'org-agenda) -(global-set-key (kbd "C-c a") #'org-agenda) -(global-set-key (kbd "C-c l") #'org-store-link) -(global-set-key (kbd "C-c c") #'org-capture) -(global-set-key (kbd "C-c s") #'org-schedule) - -;; ORG STATES ;; -(setq org-todo-keywords - (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") - (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "PHONE" "MEETING")))) - -(setq org-use-fast-todo-selection t) - -(setq org-todo-state-tags-triggers - (quote (("CANCELLED" ("CANCELLED" . t)) - ("WAITING" ("WAITING" . t)) - ("HOLD" ("WAITING") ("HOLD" . t)) - (done ("WAITING") ("HOLD")) - ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) - ("NEXT" ("WAITING") ("CANCELLED") ("HOLD")) - ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))) - -(setq org-enforce-todo-dependencies t) -(setq org-log-done (quote time)) -(setq org-log-redeadline (quote time)) -(setq org-log-reschedule (quote time)) - -;; CAPTURE ;; -(setq org-default-notes-file my-org-refile-path) -(setq org-capture-templates - (quote - ( - ("w" "Todo" entry (file+headline my-org-refile-path "Tasks") - "* TODO " - :empty-lines 1) - ("m" - "Capture incoming email" - entry - (file+headline my-org-refile-path "Incoming") - "* TODO Re: %:description\n\n Source: %u, %a\n" - :empty-lines 1) - ))) - -(add-hook 'org-capture-mode-hook 'delete-other-windows) -(setq my-org-protocol-flag nil) - -(defadvice org-capture-finalize (after delete-frame-at-end activate) - "Delete frame at remember finalization" - (progn (if my-org-protocol-flag (delete-frame)) - (setq my-org-protocol-flag nil))) - -(defadvice org-capture-kill (after delete-frame-at-end activate) - "Delete frame at remember abort" - (progn (if my-org-protocol-flag (delete-frame)) - (setq my-org-protocol-flag nil))) - -(defadvice org-protocol-capture (before set-org-protocol-flag activate) - (setq my-org-protocol-flag t)) - - -;; REFILE ;; - -; Targets include this file and any file contributing to the agenda - up to 3 levels deep -(setq org-refile-targets - '((nil :maxlevel . 3) - (org-agenda-files :maxlevel . 3))) - -; Targets complete directly with IDO -(setq org-outline-path-complete-in-steps nil) - -; Allow refile to create parent tasks with confirmation -(setq org-refile-allow-creating-parent-nodes (quote confirm)) - -;; AGENDA VIEW ;; - -;; Based on Prot's config: -;; https://protesilaos.com/codelog/2021-12-09-emacs-org-block-agenda/ -(setq my-org-agenda-custom-commands - `( - ("X" "Export files" agenda "-CANCELLED" - ((org-agenda-with-colors nil) - (org-agenda-prefix-format "%t %s") - (org-agenda-current-time-string ,(car (last org-agenda-time-grid))) - (org-agenda-fontify-priorities nil) - (org-agenda-remove-tags t)) - ,(list my-org-agenda-private-local-path)) - ("P" "Projects and tasks" - ( - (agenda "" ( - (org-agenda-overriding-header "šŸ“Œ Today's agenda\n") - (org-agenda-span 1) - (org-deadline-warning-days 0) - (org-agenda-block-separator nil) - (org-scheduled-past-days 0) - (org-agenda-skip-function '(org-agenda-skip-subtree-if - 'regexp "EVENT")) - ;; We don't need the `org-agenda-date-today' - ;; highlight because that only has a practical - ;; utility in multi-day views. - (org-agenda-day-face-function (lambda (date) 'org-agenda-date)) - (org-agenda-format-date "%A %-e %B %Y") - )) - (tags-todo "-HOLD-CANCELLED/!" - ((org-agenda-overriding-header "\nšŸŸ¢ Projects") - (org-agenda-skip-function 'bh/skip-non-projects) - (org-agenda-block-separator nil) - (org-tags-match-list-sublevels 'indented) - (org-agenda-sorting-strategy - '(category-keep)))) - - (tags-todo "-CANCELLED/!NEXT" - ((org-agenda-overriding-header (concat "\nāš”Project Next Tasks\n" - (if bh/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'bh/skip-projects-and-habits-and-single-tasks) - (org-tags-match-list-sublevels t) - (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-with-date bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-block-separator nil) - (org-agenda-sorting-strategy - '(todo-state-down effort-up category-keep)))) - - (tags-todo "-HOLD-CANCELLED/!" - ((org-agenda-overriding-header "\nšŸš« Stuck Projects\n") - (org-agenda-skip-function 'bh/skip-non-stuck-projects) - (org-agenda-block-separator nil) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header (concat "\nāš”Standalone Tasks\n" - (if bh/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'bh/skip-project-tasks) - (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-with-date bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-sorting-strategy - '(category-keep)))) - )) - ("A" "Daily agenda and top priority tasks" - ( - (agenda "" ( - (org-agenda-overriding-header "šŸ“Œ Today's agenda\n") - (org-agenda-span 1) - (org-deadline-warning-days 0) - (org-agenda-block-separator nil) - (org-scheduled-past-days 0) - ;; We don't need the `org-agenda-date-today' - ;; highlight because that only has a practical - ;; utility in multi-day views. - (org-agenda-day-face-function (lambda (date) 'org-agenda-date)) - (org-agenda-format-date "%A %-e %B %Y") - )) - - (agenda "" ( - (org-agenda-overriding-header "\nšŸ“š Pending scheduled tasks") - (org-agenda-time-grid nil) - (org-agenda-start-on-weekday nil) - (org-agenda-span 1) - (org-agenda-show-all-dates nil) - (org-scheduled-past-days 365) - ;; Excludes today's scheduled items - (org-scheduled-delay-days 1) - (org-agenda-block-separator nil) - (org-agenda-entry-types '(:scheduled)) - (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) - (org-agenda-day-face-function (lambda (date) 'org-agenda-date)) - (org-agenda-format-date "") - )) - - (agenda "" ( - (org-agenda-overriding-header "\nā° Next three days\n") - (org-agenda-start-on-weekday nil) - (org-agenda-start-day nil) - (org-agenda-start-day "+1d") - (org-agenda-span 3) - (org-deadline-warning-days 0) - (org-agenda-block-separator nil) - (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) - )) - - (agenda "" ( - (org-agenda-overriding-header "\nšŸ•˜ Upcoming deadlines (+14d)\n") - (org-agenda-time-grid nil) - (org-agenda-start-on-weekday nil) - ;; We don't want to replicate the previous section's - ;; three days, so we start counting from the day after. - (org-agenda-start-day "+4d") - (org-agenda-span 14) - (org-agenda-show-all-dates nil) - (org-deadline-warning-days 0) - (org-agenda-entry-types '(:deadline)) - (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) - )) - - (tags-todo "*" - ( - (org-agenda-overriding-header "\nšŸ¤” Important tasks without a date") - (org-agenda-skip-function '(org-agenda-skip-if nil '(timestamp))) - (org-agenda-skip-function - `(org-agenda-skip-entry-if - 'notregexp ,(format "\\[#%s\\]" (char-to-string org-priority-highest)))) - (org-agenda-block-separator nil) - )) - - (tags-todo "REFILE" - ((org-agenda-overriding-header "\nā›” Tasks to Refile") - (org-agenda-block-separator nil) - )) - - - (tags-todo "-HOLD-CANCELLED/!" - ((org-agenda-overriding-header "\nšŸš« Stuck Projects") - (org-agenda-skip-function 'bh/skip-non-stuck-projects) - (org-agenda-block-separator nil) - (org-agenda-sorting-strategy - '(category-keep)))) - )) - )) - -(setq org-agenda-files my-org-agenda-files) -(setq org-agenda-custom-commands my-org-agenda-custom-commands) - -;; Do not dim blocked tasks -(setq org-agenda-compact-blocks nil) -(setq org-agenda-dim-blocked-tasks nil) -(setq org-agenda-block-separator 61) - -(defun bh/is-project-p () - "Any task with a todo keyword subtask" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (forward-line 1) - (while (and (not has-subtask) - (< (point) subtree-end) - (re-search-forward "^\*+ " subtree-end t)) - (when (member (org-get-todo-state) org-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task has-subtask)))) - -(defun bh/is-project-subtree-p () - "Any task with a todo keyword that is in a project subtree. -Callers of this function already widen the buffer view." - (let ((task (save-excursion (org-back-to-heading 'invisible-ok) - (point)))) - (save-excursion - (bh/find-project-task) - (if (equal (point) task) - nil - t)))) - -(defun bh/is-task-p () - "Any task with a todo keyword and no subtask" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (forward-line 1) - (while (and (not has-subtask) - (< (point) subtree-end) - (re-search-forward "^\*+ " subtree-end t)) - (when (member (org-get-todo-state) org-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task (not has-subtask))))) - -(defun bh/is-subproject-p () - "Any task which is a subtask of another project" - (let ((is-subproject) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (while (and (not is-subproject) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq is-subproject t)))) - (and is-a-task is-subproject))) - -(defun bh/list-sublevels-for-projects-indented () - "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. - This is normally used by skipping functions where this variable is already local to the agenda." - (if (marker-buffer org-agenda-restrict-begin) - (setq org-tags-match-list-sublevels 'indented) - (setq org-tags-match-list-sublevels nil)) - nil) - -(defun bh/list-sublevels-for-projects () - "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. - This is normally used by skipping functions where this variable is already local to the agenda." - (if (marker-buffer org-agenda-restrict-begin) - (setq org-tags-match-list-sublevels t) - (setq org-tags-match-list-sublevels nil)) - nil) - -(defvar bh/hide-scheduled-and-waiting-next-tasks t) - -(defun bh/toggle-next-task-display () - (interactive) - (setq bh/hide-scheduled-and-waiting-next-tasks (not bh/hide-scheduled-and-waiting-next-tasks)) - (when (equal major-mode 'org-agenda-mode) - (org-agenda-redo)) - (message "%s WAITING and SCHEDULED NEXT Tasks" (if bh/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) - -(defun bh/skip-stuck-projects () - "Skip trees that are not stuck projects" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (bh/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - nil - next-headline)) ; a stuck project, has subtasks but no next task - nil)))) - -(defun bh/skip-non-stuck-projects () - "Skip trees that are not stuck projects" - ;; (bh/list-sublevels-for-projects-indented) - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (bh/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - next-headline - nil)) ; a stuck project, has subtasks but no next task - next-headline)))) - -(defun bh/skip-non-projects () - "Skip trees that are not projects" - ;; (bh/list-sublevels-for-projects-indented) - (if (save-excursion (bh/skip-non-stuck-projects)) - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((bh/is-project-p) - nil) - ((and (bh/is-project-subtree-p) (not (bh/is-task-p))) - nil) - (t - subtree-end)))) - (save-excursion (org-end-of-subtree t)))) - -(defun bh/skip-non-tasks () - "Show non-project tasks. -Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((bh/is-task-p) - nil) - (t - next-headline))))) - -(defun bh/skip-project-trees-and-habits () - "Skip trees that are projects" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((bh/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - (t - nil))))) - -(defun bh/skip-projects-and-habits-and-single-tasks () - "Skip trees that are projects, tasks that are habits, single non-project tasks" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((org-is-habit-p) - next-headline) - ((and bh/hide-scheduled-and-waiting-next-tasks - (member "WAITING" (org-get-tags-at))) - next-headline) - ((bh/is-project-p) - next-headline) - ((and (bh/is-task-p) (not (bh/is-project-subtree-p))) - next-headline) - (t - nil))))) - -(defun bh/skip-project-tasks-maybe () - "Show tasks related to the current restriction. -When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. -When not restricted, skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max)))) - (limit-to-project (marker-buffer org-agenda-restrict-begin))) - (cond - ((bh/is-project-p) - next-headline) - ((org-is-habit-p) - subtree-end) - ((and (not limit-to-project) - (bh/is-project-subtree-p)) - subtree-end) - ((and limit-to-project - (bh/is-project-subtree-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - (t - nil))))) - -(defun bh/skip-project-tasks () - "Show non-project tasks. -Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((bh/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - ((bh/is-project-subtree-p) - subtree-end) - (t - nil))))) - -(defun bh/skip-non-project-tasks () - "Show project tasks. -Skip project and sub-project tasks, habits, and loose non-project tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((bh/is-project-p) - next-headline) - ((org-is-habit-p) - subtree-end) - ((and (bh/is-project-subtree-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - ((not (bh/is-project-subtree-p)) - subtree-end) - (t - nil))))) - -(defun bh/skip-projects-and-habits () - "Skip trees that are projects and tasks that are habits" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((bh/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - (t - nil))))) - -(defun bh/skip-non-subprojects () - "Skip trees that are not projects" - (let ((next-headline (save-excursion (outline-next-heading)))) - (if (bh/is-subproject-p) - nil - next-headline))) - -;; CLOCKING ;; -;; Resume clocking task when emacs is restarted -(org-clock-persistence-insinuate) -;; -;; Show lot of clocking history so it's easy to pick items off the C-F11 list -(setq org-clock-history-length 23) -;; Resume clocking task on clock-in if the clock is open -(setq org-clock-in-resume t) -;; Change tasks to NEXT when clocking in -(setq org-clock-in-switch-to-state 'bh/clock-in-to-next) -;; Separate drawers for clocking and logs -(setq org-drawers (quote ("PROPERTIES" "LOGBOOK"))) -;; Save clock data and state changes and notes in the LOGBOOK drawer -(setq org-clock-into-drawer t) -;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration -(setq org-clock-out-remove-zero-time-clocks t) -;; Clock out when moving task to a done state -(setq org-clock-out-when-done t) -;; Save the running clock and all clock history when exiting Emacs, load it on startup -(setq org-clock-persist t) -;; Do not prompt to resume an active clock -(setq org-clock-persist-query-resume nil) -;; Enable auto clock resolution for finding open clocks -(setq org-clock-auto-clock-resolution (quote when-no-clock-is-running)) -;; Include current clocking task in clock reports -(setq org-clock-report-include-clocking-task t) - - -(setq bh/keep-clock-running nil) - -(defun bh/clock-in-to-next (kw) - "Switch a task from TODO to NEXT when clocking in. -Skips capture tasks, projects, and subprojects. -Switch projects and subprojects from NEXT back to TODO" - (when (not (and (boundp 'org-capture-mode) org-capture-mode)) - (cond - ((and (member (org-get-todo-state) (list "TODO")) - (bh/is-task-p)) - "NEXT") - ((and (member (org-get-todo-state) (list "NEXT")) - (bh/is-project-p)) - "TODO")))) - -(defun bh/find-project-task () - "Move point to the parent (project) task if any" - (save-restriction - (widen) - (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) - (while (org-up-heading-safe) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - (goto-char parent-task) - parent-task))) - -(defun bh/punch-in (arg) - "Start continuous clocking and set the default task to the -selected task. If no task is selected set the Organization task -as the default task." - (interactive "p") - (setq bh/keep-clock-running t) - (if (equal major-mode 'org-agenda-mode) - ;; - ;; We're in the agenda - ;; - (let* ((marker (org-get-at-bol 'org-hd-marker)) - (tags (org-with-point-at marker (org-get-tags-at)))) - (if (and (eq arg 4) tags) - (org-agenda-clock-in '(16)) - (bh/clock-in-organization-task-as-default))) - ;; - ;; We are not in the agenda - ;; - (save-restriction - (widen) - ; Find the tags on the current task - (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4)) - (org-clock-in '(16)) - (bh/clock-in-organization-task-as-default))))) - -(defun bh/punch-out () - (interactive) - (setq bh/keep-clock-running nil) - (when (org-clock-is-active) - (org-clock-out)) - (org-agenda-remove-restriction-lock)) - -(defun bh/clock-in-default-task () - (save-excursion - (org-with-point-at org-clock-default-task - (org-clock-in)))) - -(defun bh/clock-in-parent-task () - "Move point to the parent (project) task if any and clock in" - (let ((parent-task)) - (save-excursion - (save-restriction - (widen) - (while (and (not parent-task) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - (if parent-task - (org-with-point-at parent-task - (org-clock-in)) - (when bh/keep-clock-running - (bh/clock-in-default-task))))))) - -(defvar bh/organization-task-id "eb155a82-92b2-4f25-a3c6-0304591af2f9") - -(defun bh/clock-in-organization-task-as-default () - (interactive) - (org-with-point-at (org-id-find bh/organization-task-id 'marker) - (org-clock-in '(16)))) - -(defun bh/clock-out-maybe () - (when (and bh/keep-clock-running - (not org-clock-clocking-in) - (marker-buffer org-clock-default-task) - (not org-clock-resolving-clocks-due-to-idleness)) - (bh/clock-in-parent-task))) - -(add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append) - - -;; ORG REPORTS ;; -; Set default column view headings: Task Effort Clock_Summary -(setq org-columns-default-format "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM") - -(defun my-org-clocktable-indent-string (level) - (if (= level 1) - "" - (let ((str "^")) - (while (> level 2) - (setq level (1- level) - str (concat str "--"))) - (concat str "-> ")))) - -(advice-add 'org-clocktable-indent-string :override #'my-org-clocktable-indent-string) - -(setq org-clock-clocktable-default-properties '(:maxlevel 4 :scope file :formula %)) - -; global Effort estimate values -; global STYLE property values for completion -(setq org-global-properties (quote (("Effort_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00") - ("STYLE_ALL" . "habit")))) - -;; Agenda log mode items to display (closed and state changes by default) -(setq org-agenda-log-mode-items (quote (closed state))) - -;; TAGS ;; -; Tags with fast selection keys -(setq org-tag-alist (quote ((:startgroup) - ("@errand" . ?e) - ("@office" . ?o) - ("@home" . ?H) - (:endgroup) - ("WAITING" . ?w) - ("HOLD" . ?h) - ("PERSONAL" . ?P) - ("WORK" . ?W) - ("ORG" . ?O) - ("NOTE" . ?n) - ("CANCELLED" . ?c) - ("FLAGGED" . ??)))) - -(setq org-stuck-projects - '("+LEVEL=2+PROJECT/-MAYBE-DONE" ("NEXT") ("@shop") - "\\")) - -; Allow setting single tags without the menu -(setq org-fast-tag-selection-single-key (quote expert)) - -; For tag searches ignore tasks with scheduled and deadline dates -(setq org-agenda-tags-todo-honor-ignore-options t) - -;; org-modern -(add-hook 'org-mode-hook 'org-modern-mode) -(add-hook 'org-agenda-finalize-hook #'org-modern-agenda) - -;; Credits: https://200ok.ch/posts/2022-02-13_integrating_org_mode_agenda_into_other_calendar_apps.html -(defun org-agenda-export-to-ics () - (set-org-agenda-files) - ;; Run all custom agenda commands that have a file argument. - (org-batch-store-agenda-views) - - ;; Org mode correctly exports TODO keywords as VTODO events in ICS. - ;; However, some proprietary calendars do not really work with - ;; standards (looking at you Google), so VTODO is ignored and only - ;; VEVENT is read. - (with-current-buffer (find-file-noselect org-agenda-private-local-path) - (goto-char (point-min)) - (while (re-search-forward "VTODO" nil t) - (replace-match "VEVENT")) - (save-buffer)) - - ;; Copy the ICS file to a remote server (Tramp paths work). - (copy-file org-agenda-private-local-path org-agenda-private-remote-path t)) -- cgit v1.2.3