Commit be70000ccb39

Vincent Demeester <vincent@sbr.pm>
2026-02-03 13:27:43
org-manager: add --with-content flag to search command
Add optional --with-content flag to org-manager search command to return full TODO content and properties, not just basic metadata. Changes: - elisp: Update org-batch-search to accept optional include-content parameter that extracts full body content and properties - bash: Add --with-content flag parsing to cmd_search - docs: Update Org and TODOs skill documentation with search modes and usage examples Benefits: - Backward compatible (default behavior unchanged) - Performance optimized (content only extracted when requested) - More flexible (choose between quick scan vs detailed context) - Better Claude integration via skill documentation Usage: # Basic search (fast, metadata only) org-manager search todos.org 'keyword' # Search with full content org-manager search todos.org 'keyword' --with-content
1 parent 4ff5300
Changed files (4)
dots
.config
claude
emacs
dots/.config/claude/skills/Org/tools/org-manager
@@ -106,8 +106,9 @@ READ COMMANDS:
   count <file> [--state=STATE]
       Count TODO items by state
 
-  search <file> <term>
+  search <file> <term> [--with-content]
       Search for term in file
+      Use --with-content to include full TODO content and properties in results
 
   by-section <file> <section>
       Get TODOs in specific section
@@ -305,6 +306,12 @@ EXAMPLES:
   # Get today's schedule
   org-manager scheduled ~/desktop/org/todos.org
 
+  # Search for term in TODOs (basic mode - no content)
+  org-manager search ~/desktop/org/todos.org "NixOS"
+
+  # Search with full content and properties
+  org-manager search ~/desktop/org/todos.org "NixOS" --with-content
+
   # Count by state
   org-manager count ~/desktop/org/todos.org
 
@@ -428,13 +435,26 @@ cmd_count() {
 
 cmd_search() {
     local file="$1"
-    local term="$2"
+    local term="$2"; shift 2
+    local with_content="nil"
 
     [[ -f "$file" ]] || error "File not found: $file"
     [[ -n "$term" ]] || error "Search term required"
 
+    while [[ $# -gt 0 ]]; do
+        case "$1" in
+            --with-content)
+                with_content="t"
+                shift
+                ;;
+            *)
+                error "Unknown option: $1"
+                ;;
+        esac
+    done
+
     local elisp="(progn
-      (let ((result (org-batch-search \"$file\" \"$term\")))
+      (let ((result (org-batch-search \"$file\" \"$term\" $with_content)))
         (org-batch-output-json t result))
       (kill-emacs 0))"
 
dots/.config/claude/skills/Org/SKILL.md
@@ -64,9 +64,12 @@ org-manager denote-update ~/desktop/org/notes/20251205T*.org \
 
 **Org-mode Operations**:
 ```bash
-# Search for content
+# Search for content (basic mode - metadata only)
 org-manager search ~/desktop/org/notes/*.org "keyword"
 
+# Search with full content and properties
+org-manager search ~/desktop/org/notes/*.org "keyword" --with-content
+
 # Count TODOs in file
 org-manager count ~/desktop/org/todos.org
 
@@ -74,6 +77,11 @@ org-manager count ~/desktop/org/todos.org
 org-manager sections ~/desktop/org/notes/20251205T*.org
 ```
 
+**Search modes:**
+- **Basic mode** (default): Fast scan returning heading, state, priority, tags, matched-in location
+- **With content** (`--with-content`): Includes full TODO body and properties for complete context
+- Use `--with-content` when you need to see the full details of matching items
+
 **Output**: Returns JSON with operation results.
 
 ### journelly-manager
dots/.config/claude/skills/TODOs/SKILL.md
@@ -386,7 +386,7 @@ org-manager archive ~/desktop/org/todos.org
   - Other markdown syntax (bold, links, code) will NOT be converted
 - Best practice: Write content in org-mode format from the start
 
-**Statistics:**
+**Statistics and Search:**
 ```bash
 # Count by state
 org-manager count ~/desktop/org/todos.org
@@ -394,10 +394,19 @@ org-manager count ~/desktop/org/todos.org
 # Get all sections
 org-manager sections ~/desktop/org/todos.org
 
-# Search for term
+# Search for term (basic mode - metadata only)
 org-manager search ~/desktop/org/todos.org "wireguard"
+
+# Search with full content and properties
+org-manager search ~/desktop/org/todos.org "wireguard" --with-content
 ```
 
+**Search modes:**
+- **Basic mode** (default): Returns heading, state, priority, tags, scheduled, deadline, matched-in location
+- **With content** (`--with-content`): Includes full TODO body content and properties drawer
+- Use `--with-content` when you need to see the full context of matching TODOs
+- Basic mode is faster for quick scans and overview
+
 All commands return JSON for easy parsing:
 ```bash
 org-manager list ~/desktop/org/todos.org --state=NEXT | jq -r '.data[] | "[\(.todo)] \(.heading)"'
dots/.config/emacs/site-lisp/org-batch-functions.el
@@ -139,20 +139,28 @@ Returns alist with counts for each state."
                     (cl-incf (alist-get state-sym counts))))))
     counts))
 
-(defun org-batch-search (file search-term)
+(defun org-batch-search (file search-term &optional include-content)
   "Search for SEARCH-TERM in FILE content.
-Returns list of matching headlines with context."
+Returns list of matching headlines with context.
+If INCLUDE-CONTENT is non-nil, includes full TODO content and properties."
   (org-ql-select file
     `(and (todo)
           (regexp ,(regexp-quote search-term)))
     :action (lambda ()
-              (let ((alist (org-batch--element-to-alist-at-point)))
-                (cons (cons 'matched-in
-                            (if (string-match-p (regexp-quote search-term)
-                                                (alist-get 'heading alist))
-                                "heading"
-                              "content"))
-                      alist)))))
+              (let* ((alist (org-batch--element-to-alist-at-point))
+                     (matched-in (if (string-match-p (regexp-quote search-term)
+                                                     (alist-get 'heading alist))
+                                     "heading"
+                                   "content"))
+                     (result (cons (cons 'matched-in matched-in) alist)))
+                (if include-content
+                    (let* ((element (org-element-at-point))
+                           (properties (org-batch--extract-properties-at-point))
+                           (content (org-batch--extract-content-at-point element)))
+                      (append result
+                              (list (cons 'properties properties)
+                                    (cons 'content content))))
+                  result)))))
 
 (defun org-batch-get-sections (file)
   "Get list of all level-1 sections in FILE."