From 1a486bf45f215a6e583bbbce3622809f31cb9242 Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Thu, 9 Apr 2026 20:31:29 -0400 Subject: [PATCH] PREP: Baseline for PSF mandate consolidation --- org-skill-org-gtd-archive-roam-daily.org | 71 ++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/org-skill-org-gtd-archive-roam-daily.org b/org-skill-org-gtd-archive-roam-daily.org index 744382b..d265f9f 100644 --- a/org-skill-org-gtd-archive-roam-daily.org +++ b/org-skill-org-gtd-archive-roam-daily.org @@ -87,3 +87,74 @@ The system will utilize Emacs Lisp to extract the `:CREATED:` property from a GT - *Return Value:* `nil` - *Side Effects:* Displays a message. + +* Implementation + +** Emacs Lisp Logic (org-gtd-archive-roam-daily.el) +#+begin_src elisp :tangle projects/org-gtd-archive-roam-daily/org-gtd-archive-roam-daily.el +(require 'org-roam-dailies) +(require 'org-element) +(require 'org-time) + +(defun amero-get-org-heading-created-property () + "Extract the :CREATED: property from the current Org heading. + Returns a time string or nil if not found." + (interactive) + (save-excursion + (org-back-to-heading t) + (org-entry-get (point) "CREATED"))) + +(defun amero-parse-created-timestamp (timestamp-string) + "Parse an Org-mode timestamp string like '[2026-03-16 Mon 14:05]' + into an Emacs internal time object. + Returns nil if parsing fails." + (ignore-errors + (org-time-string-to-time timestamp-string))) + +(defun amero-get-daily-note-file (time-object) + "Get the Org-roam daily note file for a given Emacs TIME-OBJECT. + Creates the file if it doesn't exist. Returns the file path." + (let* ((date-string (format-time-string org-roam-dailies-capture-templates-date-format time-object)) + (file-path (expand-file-name (concat date-string ".org") + (expand-file-name org-roam-dailies-directory org-roam-directory)))) + ;; Ensure the directory exists + (unless (file-exists-p (file-name-directory file-path)) + (make-directory (file-name-directory file-path) t)) + ;; Create file if it doesn't exist + (unless (file-exists-p file-path) + (with-temp-buffer + (insert (format "#+title: %s\n" date-string)) + (write-file file-path))) + file-path)) + +(defun org-gtd-archive-roam-daily () + "Archive the current Org heading to an Org-roam daily file + based on its :CREATED: property." + (interactive) + (unless (org-before-first-heading-p (point)) + (user-error "Point is not on an Org heading or within an Org file.")) + + (let* ((created-timestamp-string (amero-get-org-heading-created-property)) + (created-time-object (and created-timestamp-string + (amero-parse-created-timestamp created-timestamp-string))) + (heading-start (save-excursion (org-back-to-heading t) (point))) + (heading-end (save-excursion (org-end-of-subtree t) (point))) + (heading-content (buffer-substring-no-properties heading-start heading-end)) + daily-file-path) + + (unless created-time-object + (user-error "No date error: Heading is missing a valid :CREATED: property.")) + + (setq daily-file-path (amero-get-daily-note-file created-time-object)) + + (with-current-buffer (find-file-noselect daily-file-path) + (goto-char (point-max)) + (insert "\n\n" heading-content) + (save-buffer)) + + ;; Remove the original heading + (delete-region heading-start heading-end) + (message "Archived heading to %s" daily-file-path))) + +(provide 'org-gtd-archive-roam-daily) +#+end_src