diff --git a/config.el b/config.el index e71a170..031d823 100644 --- a/config.el +++ b/config.el @@ -43,134 +43,99 @@ ;; (remove-hook 'doom-switch-buffer-hook #'+org--restart-mode-h ;; 'local))) +;; If you use `org' and don't want your org files in the default location below, +;; change `org-directory'. It must be set before org loads! (setq org-directory "~/Nextcloud/org/") -(after! org - (setq org-return-follows-link t - org-agenda-files `(,(expand-file-name "gtd/inbox.org" org-directory) - ,(expand-file-name "gtd/projects.org" org-directory))) - (setq org-capture-templates - `(("i" "Inbox" entry (file ,(expand-file-name "gtd/inbox.org" org-directory)) - "* TODO %?\nEntered on %U\n" :prepend t) - ("x" "Org Protocol" entry (file ,(expand-file-name "gtd/inbox.org" org-directory)) - "* TODO %:annotation\nEntered on %U\n" :prepend t :immediate-finish t))) +;; (defun max/org-gtd--incubate () +;; "Process GTD inbox item by incubating it. +;; Allow the user apply user-defined tags from +;; `org-tag-persistent-alist', `org-tag-alist' or file-local tags in +;; the inbox. Refile to any org-gtd incubate target (see manual)." +;; (interactive) +;; (org-gtd--decorate-item) +;; (org-gtd--refile org-gtd-incubated) +;; (org-gtd-process-inbox)) - (setq org-log-done 'time - org-log-into-drawer t) +;; (defun max/org-gtd--quick-action () +;; "Process GTD inbox item by doing it now. +;; Allow the user apply user-defined tags from +;; `org-tag-persistent-alist', `org-tag-alist' or file-local tags in +;; the inbox. Mark it as done and archive." +;; (interactive) +;; (org-back-to-heading) +;; (org-gtd--decorate-item) +;; (org-clock-in) +;; (org-gtd--refile org-gtd-actions) +;; (org-gtd-process-inbox)) - (setq org-tag-alist '(("@errand" . ?e) - ("@office" . ?o) - ("@home" . ?h))) +;; (use-package! org-gtd +;; :after org +;; :config +;; (setq org-gtd-directory (concat org-directory "newgtd/") +;; org-edna-use-inheritance t +;; org-gtd-update-ack "2.1.0" +;; org-gtd-refile-to-any-target t) +;; (advice-add #'org-gtd--incubate :override #'max/org-gtd--incubate) +;; (advice-add #'org-gtd--quick-action :override #'max/org-gtd--quick-action) +;; (map! :leader +;; (:prefix ("d" . "org-gtd") +;; :desc "Capture" "c" #'org-gtd-capture +;; :desc "Engage" "e" #'org-gtd-engage +;; :desc "Process inbox" "p" #'org-gtd-process-inbox +;; :desc "Show all next" "n" #'org-gtd-show-all-next +;; :desc "Stuck projects" "s" #'org-gtd-show-stuck-projects)) +;; (set-popup-rule! "^\\*ivy-occur" :size 0.35 :ttl 0 :quit nil) +;; (map! :map org-gtd-process-map +;; :desc "Choose" "C-c c" #'org-gtd-choose)) - (setq org-refile-allow-creating-parent-nodes 'confirm - org-refile-targets `(("projects.org" . (:level . 1)) - (,(expand-file-name "gtd/someday.org" org-directory) . (:level . 0)))) +;; (set-popup-rule! "^\\*helpful" :ignore t) - ;; https://christiantietze.de/posts/2019/03/sync-emacs-org-files/ - (add-hook 'auto-save-hook #'org-save-all-org-buffers) - (add-hook 'kill-emacs-hook #'org-save-all-org-buffers) - (advice-add #'org-save-all-org-buffers :around #'doom-shut-up-a) - - (add-to-list 'org-modules 'org-habit t) - - (setq org-todo-keywords - '((sequence "TODO(t)" "NEXT(n)" "HOLD(h)" "WAIT(w)" "|" "DONE(d)" "KILL(k)")))) - -(after! org-clock - (setq org-clock-persist t - org-clock-persist-query-resume nil - ;; org-clock-out-remove-zero-time-clocks t - org-clock-in-switch-to-state "NEXT")) ;;; Autoload this function for the org-pomodoro polybar module -(autoload #'org-pomodoro-active-p "org-pomodoro" nil t) +;; (autoload #'org-pomodoro-active-p "org-pomodoro" nil t) -(after! org-pomodoro - (defvar +org-pomodoro-length-file "/tmp/org-pomodoro-length" - "Location of the lock file which stores the PID of the process currenty running mu4e") - (defun +org-pomodoro/set-length () - "Sets the length of pomodoros and breaks. The lengths are stored in a file - so that they may persist between sessions." - (interactive) - (let ((pomodoro-length (read-number "org-pomodoro-length: " org-pomodoro-length)) - (pomodoro-short-break-length (read-number "org-pomodoro-short-break-length: " org-pomodoro-short-break-length)) - (pomodoro-long-break-length (read-number "org-pomodoro-long-break-length: " org-pomodoro-long-break-length))) - (write-region (format "%d\n%d\n%d\n" pomodoro-length pomodoro-short-break-length pomodoro-long-break-length) - nil - +org-pomodoro-length-file) - (+org-pomodoro/update-length))) + (map! :map evil-org-agenda-mode-map + :m "c p" #'org-agenda-set-property) - (defun +org-pomodoro/update-length () - "Update the length of pomodoros and breaks from `+org-pomodoro-length-file'. - If the file does not exist, just return nil." - (when (file-exists-p +org-pomodoro-length-file) - (let ((lengths (mapcar 'string-to-number - (split-string (with-temp-buffer - (setq coding-system-for-read 'utf-8) - (insert-file-contents +org-pomodoro-length-file) - (buffer-string)) "\n" t)))) - (setq org-pomodoro-length (nth 0 lengths) - org-pomodoro-short-break-length (nth 1 lengths) - org-pomodoro-long-break-length (nth 2 lengths))))) + ;; (defun max/skip-habits () + ;; "Skip trees that are habits." + ;; (save-restriction + ;; (widen) + ;; (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + ;; (cond + ;; ((org-is-habit-p) + ;; next-headline) + ;; (t + ;; nil))))) - (+org-pomodoro/update-length) - - (defun +org-pomodoro/restart-last-pomodoro () - "Starts a new pomodoro on the last clocked-in task. Resets the pomodoro count without prompt when necessary. - This is useful for external scripts as the org-pomodoro function has y-or-n prompts" - (when (and org-pomodoro-last-clock-in - org-pomodoro-expiry-time - (org-pomodoro-expires-p)) - (setq org-pomodoro-count 0)) - (setq org-pomodoro-last-clock-in (current-time)) - - (call-interactively 'org-clock-in-last) - (org-pomodoro-start :pomodoro)) - - (defun +org-pomodoro/start-pomodoro-on-capture () - "Starts org-pomodoro upon capture if the pomodoro capture template was used" - - (when (and (not org-note-abort) - (equal (org-capture-get :pomodoro) t)) - (when (and org-pomodoro-last-clock-in - org-pomodoro-expiry-time - (org-pomodoro-expires-p)) - (setq org-pomodoro-count 0)) - (set-buffer (org-capture-get :buffer)) - (goto-char (org-capture-get :insertion-point)) - (org-clock-in) - (org-pomodoro-start :pomodoro))) - - (add-hook 'org-capture-after-finalize-hook #'+org-pomodoro/start-pomodoro-on-capture)) - -(defun max/org-gtd--incubate () - "Process GTD inbox item by incubating it. -Allow the user apply user-defined tags from -`org-tag-persistent-alist', `org-tag-alist' or file-local tags in -the inbox. Refile to any org-gtd incubate target (see manual)." - (interactive) - (org-gtd--decorate-item) - (org-gtd--refile org-gtd-incubated) - (org-gtd-process-inbox)) - -(use-package! org-gtd - :after org - :config - (org-edna-mode) - (setq org-gtd-directory (concat org-directory "newgtd/") - org-edna-use-inheritance t - org-gtd-refile-to-any-target t ) - (advice-add #'org-gtd--incubate :override #'max/org-gtd--incubate) - (map! :leader - (:prefix ("d" . "org-gtd") - :desc "Capture" "c" #'org-gtd-capture - :desc "Engage" "e" #'org-gtd-engage - :desc "Process inbox" "p" #'org-gtd-process-inbox - :desc "Show all next" "n" #'org-gtd-show-all-next - :desc "Stuck projects" "s" #'org-gtd-show-stuck-projects)) - (map! :map org-gtd-process-map - :desc "Choose" "C-c c" #'org-gtd-choose)) + ;; (setq org-columns-default-format "%40ITEM(Task) %Effort(EE){:} %CLOCKSUM(Time Spent) %SCHEDULED(Scheduled) %DEADLINE(Deadline)") + ;; (setq org-agenda-custom-commands `((" " "Agenda" + ;; ((alltodo "" + ;; ((org-agenda-overriding-header "Inbox") + ;; (org-agenda-files '(,(expand-file-name "gtd/inbox.org" org-directory))))) + ;; (agenda "" + ;; ((org-agenda-span 'week) + ;; (org-deadline-warning-days 365))) + ;; (todo "NEXT" + ;; ((org-agenda-overriding-header "In Progress") + ;; (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))))) + ;; (todo "TODO" + ;; ((org-agenda-overriding-header "Active Projects") + ;; (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))) + ;; (org-agenda-skip-function #'max/skip-habits))))) + ;; ("W" "Weekly Review" + ;; ((agenda "" + ;; ((org-agenda-span 'week) + ;; (org-agenda-start-day "-6d"))) + ;; (todo "NEXT" + ;; ((org-agenda-overriding-header "In Progress") + ;; (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))))) + ;; (todo "TODO" + ;; ((org-agenda-overriding-header "Active Projects") + ;; (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))) + ;; (org-agenda-skip-function #'max/skip-habits)))))))) (defun max/org-agenda-bulk-mark-inbox-items () "Bulk mark all inbox items in the org-agenda." @@ -236,57 +201,6 @@ the inbox. Refile to any org-gtd incubate target (see manual)." :map evil-org-agenda-mode-map :m "P" #'max/org-agenda-process-inbox) -(after! org-agenda - (setq org-agenda-window-setup 'current-window - org-agenda-restore-windows-after-quit t - org-agenda-block-separator nil - org-agenda-compact-blocks t - org-agenda-start-with-log-mode t) - - (defun max/switch-to-agenda () - (interactive) - (org-agenda nil " ")) - - (map! :map 'override - "" #'max/switch-to-agenda) - - (defun max/skip-habits () - "Skip trees that are habits." - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((org-is-habit-p) - next-headline) - (t - nil))))) - - ;; (setq org-columns-default-format "%40ITEM(Task) %Effort(EE){:} %CLOCKSUM(Time Spent) %SCHEDULED(Scheduled) %DEADLINE(Deadline)") - (setq org-agenda-custom-commands `((" " "Agenda" - ((alltodo "" - ((org-agenda-overriding-header "Inbox") - (org-agenda-files '(,(expand-file-name "gtd/inbox.org" org-directory))))) - (agenda "" - ((org-agenda-span 'week) - (org-deadline-warning-days 365))) - (todo "NEXT" - ((org-agenda-overriding-header "In Progress") - (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))))) - (todo "TODO" - ((org-agenda-overriding-header "Active Projects") - (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))) - (org-agenda-skip-function #'max/skip-habits))))) - ("W" "Weekly Review" - ((agenda "" - ((org-agenda-span 'week) - (org-agenda-start-day "-6d"))) - (todo "NEXT" - ((org-agenda-overriding-header "In Progress") - (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))))) - (todo "TODO" - ((org-agenda-overriding-header "Active Projects") - (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))) - (org-agenda-skip-function #'max/skip-habits)))))))) ;; org-agenda-custom-commands ;; '((" " "Agenda" ;; ((agenda "" @@ -324,87 +238,81 @@ the inbox. Refile to any org-gtd incubate target (see manual)." "I" #'indium-launch) ) -(use-package! org-clock-convenience - :after org-agenda - :config - ;; Fix for macos: https://github.com/dfeich/org-clock-convenience/issues/9#issuecomment-646842338 - (when IS-MAC (load "org-clock-convenience")) - (map! :after org-agenda - :map org-agenda-mode-map - "" #'org-clock-convenience-timestamp-up - "" #'org-clock-convenience-timestamp-down - "o" #'org-clock-convenience-fill-gap - "e" #'org-clock-convenience-fill-gap-both)) +;; (use-package! ox-mm +;; :after org) + + + ;; khalel-import-time-delta "30d" (after! info (map! :map Info-mode-map :n "g n" #'Info-goto-node)) -(setq max/org-calendar-directory (concat org-directory "calendar/")) -(setq max/org-calendar-file (concat max/org-calendar-directory "calendar.org")) +;; (setq max/org-calendar-directory (concat org-directory "calendar/")) +;; (setq max/org-calendar-file (concat max/org-calendar-directory "calendar.org")) ;;; https://www.reddit.com/r/orgmode/comments/8rl8ep/making_orgcaldav_useable/ -(use-package! org-caldav - :after org - :init - ;; (defun org-caldav-sync-at-close () - ;; (org-caldav-sync) - ;; (save-some-buffers)) +;; (use-package! org-caldav +;; :after org +;; :init +;; ;; (defun org-caldav-sync-at-close () +;; ;; (org-caldav-sync) +;; ;; (save-some-buffers)) - ;; (defvar org-caldav-sync-timer nil - ;; "Timer that `org-caldav-push-timer' used to reschedule itself, or nil.") - ;; (defun org-caldav-sync-with-delay (secs) - ;; (when org-caldav-sync-timer - ;; (cancel-timer org-caldav-sync-timer)) - ;; (setq org-caldav-sync-timer - ;; (run-with-idle-timer - ;; (* 1 secs) nil 'org-caldav-sync))) +;; ;; (defvar org-caldav-sync-timer nil +;; ;; "Timer that `org-caldav-push-timer' used to reschedule itself, or nil.") +;; ;; (defun org-caldav-sync-with-delay (secs) +;; ;; (when org-caldav-sync-timer +;; ;; (cancel-timer org-caldav-sync-timer)) +;; ;; (setq org-caldav-sync-timer +;; ;; (run-with-idle-timer +;; ;; (* 1 secs) nil 'org-caldav-sync))) - (setq org-icalendar-alarm-time 1) - :config - (setq org-caldav-resume-aborted 'always - org-caldav-save-directory max/org-calendar-directory - org-caldav-backup-file (concat max/org-calendar-directory "org-caldav-backup.org") - org-caldav-url "https://nextcloud.maxschlueter.com/remote.php/dav/calendars/max" - org-caldav-calendar-id "calendar" - org-caldav-files `(,max/org-calendar-file) - org-caldav-inbox max/org-calendar-file) +;; (setq org-icalendar-alarm-time 1) +;; :config +;; (setq org-caldav-resume-aborted 'always +;; org-caldav-save-directory max/org-calendar-directory +;; org-caldav-backup-file (concat max/org-calendar-directory "org-caldav-backup.org") +;; org-caldav-url "https://nextcloud.maxschlueter.com/remote.php/dav/calendars/max" +;; org-caldav-calendar-id "calendar" +;; org-caldav-files `(,max/org-calendar-file) +;; org-caldav-inbox max/org-calendar-file) - (after! org-agenda - (add-to-list 'org-agenda-files max/org-calendar-file t) - (setq org-agenda-include-diary t - org-agenda-insert-diary-strategy 'top-level - org-agenda-insert-diary-extract-time t - org-agenda-diary-file max/org-calendar-file)) +;; (after! org-agenda +;; (add-to-list 'org-agenda-files max/org-calendar-file t) +;; (setq org-agenda-include-diary t +;; org-agenda-insert-diary-strategy 'top-level +;; org-agenda-insert-diary-extract-time t +;; org-agenda-diary-file max/org-calendar-file)) - ;; (setq org-caldav-calendars - ;; `((:calendar-id "personal" - ;; :files (,(concat max/org-calendar-directory "personal.org")) - ;; :inbox ,(concat max/org-calendar-directory "personal.org")) - ;; (:calendar-id "work" - ;; :files (,(concat max/org-calendar-directory "work.org")) - ;; :inbox ,(concat max/org-calendar-directory "work.org")) - ;; )) +;; ;; (setq org-caldav-calendars +;; ;; `((:calendar-id "personal" +;; ;; :files (,(concat max/org-calendar-directory "personal.org")) +;; ;; :inbox ,(concat max/org-calendar-directory "personal.org")) +;; ;; (:calendar-id "work" +;; ;; :files (,(concat max/org-calendar-directory "work.org")) +;; ;; :inbox ,(concat max/org-calendar-directory "work.org")) +;; ;; )) - (defun max/org-caldav-get-inbox () - (let* ((calid (completing-read "Calendar: " - (cl-loop for cal in org-caldav-calendars - collect (plist-get cal :calendar-id)) - nil t)) - (calinbox (cl-loop for cal in org-caldav-calendars - when (string= (plist-get cal :calendar-id) calid) - return (plist-get cal :inbox)))) - calinbox)) - ;; (add-hook 'after-save-hook - ;; (lambda () - ;; (when (eq major-mode 'org-mode) - ;; (org-caldav-sync-with-delay 300)))) - ;; (add-hook 'kill-emacs-hook 'org-caldav-sync-at-close) - ) +;; (defun max/org-caldav-get-inbox () +;; (let* ((calid (completing-read "Calendar: " +;; (cl-loop for cal in org-caldav-calendars +;; collect (plist-get cal :calendar-id)) +;; nil t)) +;; (calinbox (cl-loop for cal in org-caldav-calendars +;; when (string= (plist-get cal :calendar-id) calid) +;; return (plist-get cal :inbox)))) +;; calinbox)) +;; ;; (add-hook 'after-save-hook +;; ;; (lambda () +;; ;; (when (eq major-mode 'org-mode) +;; ;; (org-caldav-sync-with-delay 300)))) +;; ;; (add-hook 'kill-emacs-hook 'org-caldav-sync-at-close) +;; ) (setq +org-roam-open-buffer-on-find-file nil) -(after! org-roam +(after! org-roam (setq org-roam-dailies-capture-templates '(("d" "default" entry "* %?" @@ -625,8 +533,6 @@ the inbox. Refile to any org-gtd incubate target (see manual)." ;; (load! nix-docbook-mode) - - ;;; (after! calfw-org ;;; (autoload (function cfw:org-create-file-source) "cfw:org-create-file-source" nil t)) @@ -636,3 +542,4 @@ the inbox. Refile to any org-gtd incubate target (see manual)." ;; load personal modules (load! "email") +(load! "gtd") diff --git a/gtd.el b/gtd.el new file mode 100644 index 0000000..9c47661 --- /dev/null +++ b/gtd.el @@ -0,0 +1,197 @@ +;;; gtd.el -*- lexical-binding: t; -*- + +(require 'org) + +(setq org-return-follows-link t + org-complete-tags-always-offer-all-agenda-tags t + org-agenda-files (append (mapcar 'file-truename + (file-expand-wildcards (concat org-directory "gtd/*.org"))) + (list (expand-file-name (funcall #'gtd-get-current-journal) org-directory)))) + +(setq org-capture-templates +`(("i" "Inbox" entry (file "gtd/inbox.org") + ,(concat "* %?\n" + ":PROPERTIES:\n:CREATED: %U\n:END:") :prepend t) + ("j" "Journal" entry (file+datetree ,(gtd-get-current-journal)) + ,(concat "* %?\n" + ":PROPERTIES:\n:CREATED: %U\n:END:")) + ("@" "Inbox [mu4e]" entry (file "gtd/inbox.org") + ;; "* Process [[mu4e:msgid:%:message-id][%:fromname - %:subject]] :email:\n%U\n")) + ,(concat "* Process %a %?\n" + ":PROPERTIES:\n:CREATED: %U\n:END:") :prepend t))) + +(setq org-refile-allow-creating-parent-nodes 'confirm + org-refile-target-verify-function (lambda (&rest _) (null (org-get-todo-state))) + ;; org-refile-target-verify-function nil + ;; org-refile-targets '(("tasks.org" . (:maxlevel . 2)))) + org-refile-targets '(("tasks.org" . (:maxlevel . 2)) + ("someday.org" . (:level . 0)))) + +(defun gtd-capture-inbox () + (interactive) + (org-capture nil "i")) + +(map! "C-c i" #'gtd-capture-inbox) + +(defun gtd-capture-journal () + (interactive) + (org-capture nil "j")) + +(map! "C-c j" #'gtd-capture-journal) + +(defun gtd-capture-email () + (interactive) + (call-interactively 'org-store-link) + (org-capture nil "@")) + +(map! :after mu4e + :map (mu4e-headers-mode-map mu4e-view-mode-map) + :vne "C-c i" #'gtd-capture-email) + +;; Insert CREATED property timestamps for non-captured headlines +(use-package! org-expiry + :config + (map! :map org-mode-map + "C-c c" #'org-expiry-insert-created) + (setq org-expiry-inactive-timestamps t)) + +;; Automatically trigger state changes in projects +(use-package! org-edna + :config + (setq org-edna-use-inheritance t) + (org-edna-mode)) + +(setq org-agenda-window-setup 'current-window + org-agenda-restore-windows-after-quit t + org-agenda-block-separator nil + org-agenda-compact-blocks t + org-agenda-start-with-log-mode t + org-agenda-hide-tags-regexp "." + org-agenda-custom-commands + '(("g" "Get Things Done (GTD)" + ((agenda "" + ((org-agenda-skip-function + '(org-agenda-skip-entry-if 'deadline)) + (org-deadline-warning-days 0))) + (tags "inbox" + ((org-agenda-prefix-format " %?-14t% s") + (org-agenda-overriding-header "\nInbox\n"))) + (todo "NEXT" + ( + ;; (org-agenda-skip-function + ;; '(org-agenda-skip-entry-if 'deadline)) + ;; (org-agenda-prefix-format " %i %-12:c [%e] ") + (org-agenda-prefix-format " %i %-14:c ") + (org-agenda-sorting-strategy '(category-up)) + (org-agenda-overriding-header "\nTasks\n"))) + (todo "WAIT" + ((org-agenda-todo-ignore-with-date t) + (org-agenda-prefix-format " %i %-14:c ") + (org-agenda-overriding-header "\nBlocked/Delegated\n"))) + ;; (agenda nil + ;; ((org-agenda-entry-types '(:deadline)) + ;; (org-agenda-format-date "") + ;; (org-deadline-warning-days 7) + ;; (org-agenda-skip-function + ;; '(org-agenda-skip-entry-if 'notregexp "\\* NEXT")) + ;; (org-agenda-overriding-header "\nDeadlines"))) + (tags "CLOSED>=\"\"" + ((org-agenda-prefix-format " %i %-14:c ") + (org-agenda-overriding-header "\nCompleted today\n"))))))) + +;; Automatically save gtd files after some actions on them +;; Taken from: https://www.labri.fr/perso/nrougier/GTD/index.html +(defun gtd-save-org-buffers () + "Save `org-agenda-files' buffers without user confirmation. +See also `org-save-all-org-buffers'" + (interactive) + (message "Saving org-agenda-files buffers...") + (save-some-buffers t (lambda () + (when (member (buffer-file-name) org-agenda-files) + t))) + (message "Saving org-agenda-files buffers... done")) + +(advice-add 'org-refile :after (lambda (&rest _) (gtd-save-org-buffers))) +(advice-add 'org-todo :after (lambda (&rest _) (gtd-save-org-buffers))) +(advice-add 'org-add-note :after (lambda (&rest _) (gtd-save-org-buffers))) +(advice-add 'org-clock-in :after (lambda (&rest _) (gtd-save-org-buffers))) + +(map! :map 'override + "" #'gtd-agenda) + +(defun gtd-agenda () + (interactive) + (org-agenda nil "g")) + +;; (defun gtd-archive-subtree () +;; "Archive the current subtree to a yearly journal." +;; (when (not (equal "DONE" (org-get-todo-state))) +;; (org-todo "DONE")) + +;; Archiving + +(defun gtd-get-current-journal () + "Returns journal file as a string for the current year." + (let ((year (number-to-string (caddr (calendar-current-date))))) + (concat "journal/" year ".org"))) + +(setq org-archive-location (concat (funcall #'gtd-get-current-journal) "::datetree/")) + +(defun max/khalel--insert-import-file-header (sdate edate) + "Insert imported events file header information into current buffer. +SDATE and EDATE denote the start and end dates, respectively, of +the current import date range." + (when khalel-import-org-file-read-only + (insert "# -*- buffer-read-only: 1; -*-\n")) + (insert khalel-import-org-file-header) + (insert (format "*Events scheduled between %s and %s*:\n" sdate edate))) + +(use-package! khalel + :commands (khalel-export-org-subtree-to-calendar + khalel-import-events + khalel-edit-calender-event + khalel-add-capture-template) + :init + (khalel-add-capture-template) + :config + (advice-add #'khalel--insert-import-file-header :override #'max/khalel--insert-import-file-header) + (advice-add #'khalel-import-events :around #'doom-shut-up-a) + (setq khalel-default-calendar "personal" + khalel-import-org-file-confirm-overwrite nil + khalel-import-start-date "-15d" + khalel-import-end-date "+30d" + khalel-import-org-file (expand-file-name "gtd/calendar.org" org-directory) + khalel-import-org-file-header "#+TITLE: Calendar\n\n\ +*NOTE*: this file has been generated by \ +[[elisp:(khalel-import-events)][khalel-import-events]] \ +and /any changes to this document will be lost on the next import/! +Instead, use =khalel-edit-calendar-event= or =khal edit= to edit the \ +underlying calendar entries, then re-import them here. + +You can use [[elisp:(khalel-run-vdirsyncer)][khalel-run-vdirsyncer]] \ +to synchronize with remote calendars. + +Consider adding this file to your list of agenda files so that events \ +show up there.\n\n")) + +(setq org-clock-persist t + ;; Useful when clocking in on a waiting task + org-clock-in-switch-to-state "NEXT" + org-clock-out-when-done '("DONE" "CNCL" "WAIT") + org-clock-persist-query-resume nil) + +(use-package! org-clock-convenience + :after org + :config + ;; Fix for macos: https://github.com/dfeich/org-clock-convenience/issues/9#issuecomment-646842338 + (when IS-MAC (load "org-clock-convenience")) + (map! :map org-agenda-mode-map + "" #'org-clock-convenience-timestamp-up + "" #'org-clock-convenience-timestamp-down + "o" #'org-clock-convenience-fill-gap + "e" #'org-clock-convenience-fill-gap-both)) + +(after! org-pomodoro + (setq org-pomodoro-length 25 + org-pomodoro-short-break-length 5 + org-pomodoro-long-break-length 20)) diff --git a/packages.el b/packages.el index 5c4dd35..da2642c 100644 --- a/packages.el +++ b/packages.el @@ -69,4 +69,5 @@ :recipe (:host github :repo "emacs-citar/citar-org-roam")) (package! pdf-tools :built-in 'prefer) (package! org-gtd) +(package! khalel) ;; (package! weblorg)