Files
passepartout/skills/org-skill-utils-org.org
Amr Gharbeia 21c792b019 refactor(skills): absolute XDG paths for tangling
- Updated all 23 skill org files to use absolute path
- Tangle now outputs directly to ~/.local/share/opencortex/skills/
- Removed  env var (org-babel doesn't expand it)
2026-04-30 11:09:46 -04:00

4.4 KiB

SKILL: Utils Org (org-skill-utils-org.org)

Overview

The Utils Org skill provides advanced structural manipulation for Org-mode files and their AST representation.

Implementation

Reading Files

(defun utils-org-read-file (filepath)
  "Reads an Org file into a string."
  (uiop:read-file-string filepath))

Writing Files

(defun utils-org-write-file (filepath content)
  "Writes content to an Org file."
  (uiop:with-output-file (s filepath :if-exists :supersede)
    (format s "~a" content)))

ID Generation

(defun utils-org-generate-id ()
  "Generates a new UUID for an Org node."
  (string-downcase (format nil "~a" (uuid:make-v4-uuid))))

ID Formatting

(defun utils-org-id-format (id)
  "Ensures the ID has the 'id:' prefix."
  (if (uiop:string-prefix-p "id:" id)
      id
      (format nil "id:~a" id)))

Setting Properties (Recursive)

(defun utils-org-set-property (ast target-id property value)
  "Recursively sets a property on a headline with a matching ID in the AST."
  (let ((type (getf ast :type))
        (props (getf ast :properties))
        (contents (getf ast :contents)))
    (when (and (eq type :HEADLINE) (string= (getf props :ID) target-id))
      (setf (getf (getf ast :properties) property) value)
      (return-from utils-org-set-property t))
    (dolist (child contents)
      (when (listp child)
        (when (utils-org-set-property child target-id property value)
          (return-from utils-org-set-property t)))))
  nil)

Setting TODO Status

(defun utils-org-set-todo (ast target-id status)
  "Sets the TODO status of a headline in the AST."
  (utils-org-set-property ast target-id :TODO status))

Adding Headlines

(defun utils-org-add-headline (ast parent-id title)
  "Adds a new headline as a child of the parent-id in the AST."
  (let* ((type (getf ast :type))
         (props (getf ast :properties))
         (id (getf props :ID))
         (contents (getf ast :contents)))
    (when (and (eq type :HEADLINE) (string= id parent-id))
      (let ((new-node (list :type :HEADLINE
                           :properties (list :ID (utils-org-id-format (utils-org-generate-id))
                                            :TITLE title)
                           :contents nil)))
        (setf (getf ast :contents) (append contents (list new-node)))
        (return-from utils-org-add-headline t)))
    (dolist (child contents)
      (when (listp child)
        (when (utils-org-add-headline child parent-id title)
          (return-from utils-org-add-headline t)))))
  nil)

Searching Headlines (by ID)

(defun utils-org-find-headline-by-id (ast id)
  "Finds a headline by its ID in the AST."
  (let ((props (getf ast :properties)))
    (when (string= (getf props :ID) id)
      (return-from utils-org-find-headline-by-id ast))
    (dolist (child (getf ast :contents))
      (when (listp child)
        (let ((found (utils-org-find-headline-by-id child id)))
          (when found (return-from utils-org-find-headline-by-id found)))))
    nil))

Searching Headlines (by Title)

(defun utils-org-find-headline-by-title (ast title)
  "Finds a headline by its title in the AST."
  (let ((props (getf ast :properties)))
    (when (string-equal (getf props :TITLE) title)
      (return-from utils-org-find-headline-by-title ast))
    (dolist (child (getf ast :contents))
      (when (listp child)
        (let ((found (utils-org-find-headline-by-title child title)))
          (when found (return-from utils-org-find-headline-by-title found)))))
    nil))

Placeholder for External Edits

(defun utils-org-modify (filepath id changes)
  "Placeholder for Emacs-driven modification of a specific node."
  (declare (ignore changes))
  (harness-log "UTILS-ORG: Applying changes to ~a in ~a" id filepath)
  t)

Placeholder for AST to Org conversion

(defun utils-org-ast-to-org (ast)
  "Minimal converter from AST back to Org text (Placeholder)."
  (declare (ignore ast))
  "* TITLE (Placeholder)")

Skill Registration

(defskill :skill-utils-org
  :priority 100
  :trigger (lambda (ctx) (declare (ignore ctx)) nil))