@stephendolan/omnifocus-cli 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # OmniFocus CLI
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@stephendolan/omnifocus-cli.svg)](https://www.npmjs.com/package/@stephendolan/omnifocus-cli)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@stephendolan/omnifocus-cli.svg)](https://www.npmjs.com/package/@stephendolan/omnifocus-cli)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Node.js Version](https://img.shields.io/node/v/@stephendolan/omnifocus-cli.svg)](https://nodejs.org)
7
+ [![Platform](https://img.shields.io/badge/platform-macOS-lightgrey.svg)](https://www.apple.com/macos/)
8
+
3
9
  A powerful command-line interface for OmniFocus on macOS, inspired by the GitHub CLI (`gh`).
4
10
 
5
11
  ## Features
@@ -7,6 +13,7 @@ A powerful command-line interface for OmniFocus on macOS, inspired by the GitHub
7
13
  - 📝 **Task Management** - Create, list, update, and delete tasks
8
14
  - 📂 **Project Management** - Manage projects and their organization
9
15
  - 📥 **Inbox Management** - View and count inbox items
16
+ - 🏷️ **Tag Analysis** - View tag usage statistics and identify stale tags
10
17
  - 🔍 **Search** - Full-text search across tasks
11
18
  - 🎨 **Beautiful Output** - Color-coded, formatted output with icons
12
19
  - ⚡ **Fast** - Direct OmniFocus integration using JXA
@@ -14,9 +21,20 @@ A powerful command-line interface for OmniFocus on macOS, inspired by the GitHub
14
21
  ## Installation
15
22
 
16
23
  ```bash
24
+ # Install globally
25
+ npm install -g @stephendolan/omnifocus-cli
26
+
27
+ # Or run directly without installing
28
+ npx @stephendolan/omnifocus-cli task list
29
+ ```
30
+
31
+ ### From Source
32
+
33
+ ```bash
34
+ git clone https://github.com/stephendolan/omnifocus-cli.git
35
+ cd omnifocus-cli
17
36
  npm install
18
- npm run build
19
- npm link
37
+ npm run link # Build and link globally
20
38
  ```
21
39
 
22
40
  Now you can use the `of` command anywhere in your terminal.
@@ -168,6 +186,102 @@ of search "documentation"
168
186
  of search "meeting" -v
169
187
  ```
170
188
 
189
+ ### Tag Commands
190
+
191
+ #### List Tags
192
+
193
+ ```bash
194
+ # List all tags with usage counts
195
+ of tag list
196
+
197
+ # Show tags unused for 30+ days
198
+ of tag list --unused-days 30
199
+
200
+ # Sort by usage (most used first)
201
+ of tag list --sort usage
202
+
203
+ # Sort by activity (most recent first)
204
+ of tag list --sort activity
205
+
206
+ # Only count active (incomplete) tasks
207
+ of tag list --active-only
208
+
209
+ # Show verbose details (IDs, creation/modification dates)
210
+ of tag list -v
211
+ ```
212
+
213
+ #### Tag Statistics
214
+
215
+ ```bash
216
+ # Show comprehensive tag usage statistics
217
+ of tag stats
218
+ ```
219
+
220
+ The `tag stats` command displays:
221
+ - Total tag counts (total, active, with tasks, unused)
222
+ - Average tasks per tag
223
+ - Most used tags (top 5)
224
+ - Least used tags (bottom 5)
225
+ - Stale tags (no activity in 30+ days)
226
+
227
+ #### Create Tag
228
+
229
+ ```bash
230
+ # Create a new tag
231
+ of tag create "New Tag"
232
+
233
+ # Create a nested tag (child of existing tag)
234
+ of tag create "Child Tag" --parent "Parent Tag"
235
+ ```
236
+
237
+ #### View Tag
238
+
239
+ ```bash
240
+ # View tag details by name
241
+ of tag view "Tag Name"
242
+
243
+ # View tag by ID (always unique)
244
+ of tag view "kXu3B-LZfFH"
245
+
246
+ # View nested tag using path syntax
247
+ of tag view "Parent/Child"
248
+ ```
249
+
250
+ **Note:** If multiple tags share the same name in different hierarchies (e.g., "Work/Meetings" and "Personal/Meetings"), you must use either:
251
+ - The full hierarchical path: `of tag view "Work/Meetings"`
252
+ - The tag ID: `of tag view "kXu3B-LZfFH"`
253
+
254
+ The command will show an error with available paths and IDs if the name is ambiguous.
255
+
256
+ #### Update Tag
257
+
258
+ ```bash
259
+ # Rename a tag
260
+ of tag update "Old Name" --name "New Name"
261
+
262
+ # Deactivate a tag
263
+ of tag update "Tag Name" --inactive
264
+
265
+ # Reactivate a tag
266
+ of tag update "Tag Name" --active
267
+
268
+ # Update nested tag using path
269
+ of tag update "Parent/Child" --name "New Name"
270
+ ```
271
+
272
+ #### Delete Tag
273
+
274
+ ```bash
275
+ # Delete a tag by name
276
+ of tag delete "Tag Name"
277
+
278
+ # Delete using alias
279
+ of tag rm "Tag Name"
280
+
281
+ # Delete nested tag using path
282
+ of tag delete "Parent/Child"
283
+ ```
284
+
171
285
  ## Command Reference
172
286
 
173
287
  ### Global Options
@@ -201,6 +315,20 @@ of search "meeting" -v
201
315
  - `--sequential` - Make it a sequential project
202
316
  - `--status <status>` - Set status (active, on hold, dropped)
203
317
 
318
+ ### Tag Options
319
+
320
+ **List options:**
321
+ - `-u, --unused-days <days>` - Show tags unused for N days
322
+ - `-s, --sort <field>` - Sort by: name, usage, activity (default: name)
323
+ - `-a, --active-only` - Only count active (incomplete) tasks
324
+ - `-v, --verbose` - Show detailed information (IDs, dates)
325
+
326
+ **Create/Update options:**
327
+ - `-p, --parent <name>` - Create as child of parent tag (create only)
328
+ - `-n, --name <name>` - Rename tag (update only)
329
+ - `-a, --active` - Set tag as active (update only)
330
+ - `-i, --inactive` - Set tag as inactive (update only)
331
+
204
332
  ## Output Legend
205
333
 
206
334
  ### Task List
@@ -222,6 +350,13 @@ of search "meeting" -v
222
350
  - `[Folder]` - Folder name (cyan)
223
351
  - `#tag` - Tags (magenta)
224
352
 
353
+ ### Tag List
354
+
355
+ - `#tag` - Tag name (cyan if active, gray if inactive)
356
+ - `(X/Y)` - Remaining/Total tasks
357
+ - `active X ago` - Last activity timestamp (cyan)
358
+ - `never used` - Tag has no tasks (gray)
359
+
225
360
  ## Examples
226
361
 
227
362
  ### Daily Workflow
@@ -271,6 +406,44 @@ of task update "Draft quarterly report" --complete
271
406
  of task update "Team meeting prep" --due "2024-01-22"
272
407
  ```
273
408
 
409
+ ### Tag Management
410
+
411
+ ```bash
412
+ # View all tags with usage stats
413
+ of tag list
414
+
415
+ # Find stale tags not used in 60+ days
416
+ of tag list --unused-days 60
417
+
418
+ # See most used tags
419
+ of tag list --sort usage
420
+
421
+ # View recently active tags
422
+ of tag list --sort activity
423
+
424
+ # Get comprehensive tag statistics
425
+ of tag stats
426
+
427
+ # Create a new tag
428
+ of tag create "Urgent"
429
+
430
+ # Create nested tags for organization
431
+ of tag create "Work Meetings" --parent "Work"
432
+ of tag create "Personal Meetings" --parent "Personal"
433
+
434
+ # View a specific tag (with hierarchical path if needed)
435
+ of tag view "Work/Work Meetings"
436
+
437
+ # Rename a stale tag
438
+ of tag update "Old Project" --name "Archived Project"
439
+
440
+ # Deactivate unused tags
441
+ of tag update "Archived Project" --inactive
442
+
443
+ # Delete completely unused tags
444
+ of tag delete "Obsolete Tag"
445
+ ```
446
+
274
447
  ## Requirements
275
448
 
276
449
  - macOS (OmniFocus is Mac-only)
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/commands/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,oBAAoB,IAAI,OAAO,CA+E9C"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/commands/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,oBAAoB,IAAI,OAAO,CA0H9C"}
@@ -1,5 +1,5 @@
1
1
  import { Command } from 'commander';
2
- import { displayProjectList, displayProjectDetails, displayWithSuccessMessage, displaySuccessMessage } from '../lib/display.js';
2
+ import { displayProjectList, displayProjectDetails, displayWithSuccessMessage, displaySuccessMessage, displayProjectStats } from '../lib/display.js';
3
3
  import { executeOmniFocusCommand } from '../lib/command-utils.js';
4
4
  export function createProjectCommand() {
5
5
  const command = new Command('project');
@@ -40,6 +40,30 @@ export function createProjectCommand() {
40
40
  status: options.status,
41
41
  }), (project) => displayWithSuccessMessage('Project created successfully', project, displayProjectDetails), 'Failed to create project');
42
42
  });
43
+ command
44
+ .command('update <idOrName>')
45
+ .description('Update an existing project')
46
+ .option('-n, --name <name>', 'Rename project')
47
+ .option('--note <text>', 'New note')
48
+ .option('-f, --folder <name>', 'Move to folder')
49
+ .option('-t, --tag <tags...>', 'Replace tags')
50
+ .option('-s, --sequential', 'Make it sequential')
51
+ .option('-p, --parallel', 'Make it parallel')
52
+ .option('--status <status>', 'Set status (active, on hold, dropped)')
53
+ .action(async (idOrName, options) => {
54
+ await executeOmniFocusCommand('Updating project...', (of) => {
55
+ const updates = {
56
+ ...(options.name && { name: options.name }),
57
+ ...(options.note !== undefined && { note: options.note }),
58
+ ...(options.folder && { folder: options.folder }),
59
+ ...(options.tag && { tags: options.tag }),
60
+ ...(options.sequential && { sequential: true }),
61
+ ...(options.parallel && { sequential: false }),
62
+ ...(options.status && { status: options.status }),
63
+ };
64
+ return of.updateProject(idOrName, updates);
65
+ }, (project) => displayWithSuccessMessage('Project updated successfully', project, displayProjectDetails), 'Failed to update project');
66
+ });
43
67
  command
44
68
  .command('delete <idOrName>')
45
69
  .alias('rm')
@@ -53,6 +77,12 @@ export function createProjectCommand() {
53
77
  .action(async (idOrName) => {
54
78
  await executeOmniFocusCommand('Loading project...', (of) => of.getProject(idOrName), (project) => displayProjectDetails(project), 'Failed to load project');
55
79
  });
80
+ command
81
+ .command('stats')
82
+ .description('Show project statistics')
83
+ .action(async () => {
84
+ await executeOmniFocusCommand('Analyzing projects...', (of) => of.getProjectStats(), (stats) => displayProjectStats(stats), 'Failed to analyze projects');
85
+ });
56
86
  return command;
57
87
  }
58
88
  //# sourceMappingURL=project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/commands/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/commands/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createTagCommand(): Command;
3
+ //# sourceMappingURL=tag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/commands/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,gBAAgB,IAAI,OAAO,CAqG1C"}
@@ -0,0 +1,69 @@
1
+ import { Command } from 'commander';
2
+ import { displayTagList, displayTagStats, displayTagDetails, displayWithSuccessMessage, displaySuccessMessage } from '../lib/display.js';
3
+ import { executeOmniFocusCommand } from '../lib/command-utils.js';
4
+ export function createTagCommand() {
5
+ const command = new Command('tag');
6
+ command.description('Manage and analyze OmniFocus tags');
7
+ command
8
+ .command('list')
9
+ .alias('ls')
10
+ .description('List tags with usage information')
11
+ .option('-u, --unused-days <days>', 'Show tags unused for N days', parseInt)
12
+ .option('-s, --sort <field>', 'Sort by: name, usage, activity (default: name)', 'name')
13
+ .option('-a, --active-only', 'Only count active (incomplete) tasks')
14
+ .option('-v, --verbose', 'Show detailed information')
15
+ .action(async (options) => {
16
+ await executeOmniFocusCommand('Loading tags...', (of) => of.listTags({
17
+ unusedDays: options.unusedDays,
18
+ sortBy: options.sort,
19
+ activeOnly: options.activeOnly,
20
+ }), (tags) => displayTagList(tags, options.verbose), 'Failed to load tags');
21
+ });
22
+ command
23
+ .command('create <name>')
24
+ .description('Create a new tag')
25
+ .option('-p, --parent <name>', 'Create as child of parent tag')
26
+ .option('-s, --status <status>', 'Set status (active, on hold, dropped)')
27
+ .action(async (name, options) => {
28
+ await executeOmniFocusCommand('Creating tag...', (of) => of.createTag({
29
+ name,
30
+ parent: options.parent,
31
+ status: options.status,
32
+ }), (tag) => displayWithSuccessMessage('Tag created successfully', tag, displayTagDetails), 'Failed to create tag');
33
+ });
34
+ command
35
+ .command('view <idOrName>')
36
+ .description('View tag details')
37
+ .action(async (idOrName) => {
38
+ await executeOmniFocusCommand('Loading tag...', (of) => of.getTag(idOrName), (tag) => displayTagDetails(tag), 'Failed to load tag');
39
+ });
40
+ command
41
+ .command('update <idOrName>')
42
+ .description('Update an existing tag')
43
+ .option('-n, --name <name>', 'Rename tag')
44
+ .option('-s, --status <status>', 'Set status (active, on hold, dropped)')
45
+ .action(async (idOrName, options) => {
46
+ await executeOmniFocusCommand('Updating tag...', (of) => {
47
+ const updates = {
48
+ ...(options.name && { name: options.name }),
49
+ ...(options.status && { status: options.status }),
50
+ };
51
+ return of.updateTag(idOrName, updates);
52
+ }, (tag) => displayWithSuccessMessage('Tag updated successfully', tag, displayTagDetails), 'Failed to update tag');
53
+ });
54
+ command
55
+ .command('delete <idOrName>')
56
+ .alias('rm')
57
+ .description('Delete a tag')
58
+ .action(async (idOrName) => {
59
+ await executeOmniFocusCommand('Deleting tag...', (of) => of.deleteTag(idOrName), () => displaySuccessMessage('Tag deleted successfully'), 'Failed to delete tag');
60
+ });
61
+ command
62
+ .command('stats')
63
+ .description('Show tag usage statistics')
64
+ .action(async () => {
65
+ await executeOmniFocusCommand('Analyzing tags...', (of) => of.getTagStats(), (stats) => displayTagStats(stats), 'Failed to analyze tags');
66
+ });
67
+ return command;
68
+ }
69
+ //# sourceMappingURL=tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/commands/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACzI,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,CAAC,WAAW,CAAC,mCAAmC,CAAC,CAAC;IAEzD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,KAAK,CAAC,IAAI,CAAC;SACX,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,0BAA0B,EAAE,6BAA6B,EAAE,QAAQ,CAAC;SAC3E,MAAM,CAAC,oBAAoB,EAAE,gDAAgD,EAAE,MAAM,CAAC;SACtF,MAAM,CAAC,mBAAmB,EAAE,sCAAsC,CAAC;SACnE,MAAM,CAAC,eAAe,EAAE,2BAA2B,CAAC;SACpD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,MAAM,uBAAuB,CAC3B,iBAAiB,EACjB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC;YAClB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,MAAM,EAAE,OAAO,CAAC,IAAI;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,EACF,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EAC/C,qBAAqB,CACtB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,kBAAkB,CAAC;SAC/B,MAAM,CAAC,qBAAqB,EAAE,+BAA+B,CAAC;SAC9D,MAAM,CAAC,uBAAuB,EAAE,uCAAuC,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,uBAAuB,CAC3B,iBAAiB,EACjB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;YACnB,IAAI;YACJ,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,EACF,CAAC,GAAG,EAAE,EAAE,CAAC,yBAAyB,CAAC,0BAA0B,EAAE,GAAG,EAAE,iBAAiB,CAAC,EACtF,sBAAsB,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,kBAAkB,CAAC;SAC/B,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QACzB,MAAM,uBAAuB,CAC3B,gBAAgB,EAChB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAC3B,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAC/B,oBAAoB,CACrB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,wBAAwB,CAAC;SACrC,MAAM,CAAC,mBAAmB,EAAE,YAAY,CAAC;SACzC,MAAM,CAAC,uBAAuB,EAAE,uCAAuC,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;QAClC,MAAM,uBAAuB,CAC3B,iBAAiB,EACjB,CAAC,EAAE,EAAE,EAAE;YACL,MAAM,OAAO,GAAqB;gBAChC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC3C,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;aAClD,CAAC;YACF,OAAO,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,yBAAyB,CAAC,0BAA0B,EAAE,GAAG,EAAE,iBAAiB,CAAC,EACtF,sBAAsB,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,KAAK,CAAC,IAAI,CAAC;SACX,WAAW,CAAC,cAAc,CAAC;SAC3B,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QACzB,MAAM,uBAAuB,CAC3B,iBAAiB,EACjB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAC9B,GAAG,EAAE,CAAC,qBAAqB,CAAC,0BAA0B,CAAC,EACvD,sBAAsB,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,2BAA2B,CAAC;SACxC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,uBAAuB,CAC3B,mBAAmB,EACnB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,EACxB,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,EACjC,wBAAwB,CACzB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,iBAAiB,IAAI,OAAO,CA4H3C"}
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,iBAAiB,IAAI,OAAO,CAwI3C"}
@@ -1,5 +1,5 @@
1
1
  import { Command } from 'commander';
2
- import { displayTaskList, displayTaskDetails, displayWithSuccessMessage, displaySuccessMessage } from '../lib/display.js';
2
+ import { displayTaskList, displayTaskDetails, displayWithSuccessMessage, displaySuccessMessage, displayTaskStats } from '../lib/display.js';
3
3
  import { executeOmniFocusCommand } from '../lib/command-utils.js';
4
4
  export function createTaskCommand() {
5
5
  const command = new Command('task');
@@ -91,6 +91,12 @@ export function createTaskCommand() {
91
91
  .action(async (idOrName) => {
92
92
  await executeOmniFocusCommand('Loading task...', (of) => of.getTask(idOrName), (task) => displayTaskDetails(task), 'Failed to load task');
93
93
  });
94
+ command
95
+ .command('stats')
96
+ .description('Show task statistics')
97
+ .action(async () => {
98
+ await executeOmniFocusCommand('Analyzing tasks...', (of) => of.getTaskStats(), (stats) => displayTaskStats(stats), 'Failed to analyze tasks');
99
+ });
94
100
  return command;
95
101
  }
96
102
  //# sourceMappingURL=task.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC5I,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAC;IAE9C,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,KAAK,CAAC,IAAI,CAAC;SACX,WAAW,CAAC,YAAY,CAAC;SACzB,MAAM,CAAC,eAAe,EAAE,yBAAyB,CAAC;SAClD,MAAM,CAAC,sBAAsB,EAAE,mBAAmB,CAAC;SACnD,MAAM,CAAC,kBAAkB,EAAE,eAAe,CAAC;SAC3C,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;SACpD,MAAM,CAAC,eAAe,EAAE,2BAA2B,CAAC;SACpD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,MAAM,uBAAuB,CAC3B,kBAAkB,EAClB,CAAC,EAAE,EAAE,EAAE;YACL,MAAM,OAAO,GAAgB;gBAC3B,gBAAgB,EAAE,OAAO,CAAC,SAAS;gBACnC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBACzC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpD,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;aACzC,CAAC;YAEF,OAAO,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,EAClD,sBAAsB,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,mBAAmB,CAAC;SAChC,MAAM,CAAC,sBAAsB,EAAE,mBAAmB,CAAC;SACnD,MAAM,CAAC,mBAAmB,EAAE,UAAU,CAAC;SACvC,MAAM,CAAC,qBAAqB,EAAE,UAAU,CAAC;SACzC,MAAM,CAAC,kBAAkB,EAAE,2BAA2B,CAAC;SACvD,MAAM,CAAC,oBAAoB,EAAE,6BAA6B,CAAC;SAC3D,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC;SACxC,MAAM,CAAC,0BAA0B,EAAE,2BAA2B,EAAE,QAAQ,CAAC;SACzE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,uBAAuB,CAC3B,kBAAkB,EAClB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC;YACpB,IAAI;YACJ,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,OAAO,CAAC,GAAG;YACjB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,gBAAgB,EAAE,OAAO,CAAC,QAAQ;SACnC,CAAC,EACF,CAAC,IAAI,EAAE,EAAE,CAAC,yBAAyB,CAAC,2BAA2B,EAAE,IAAI,EAAE,kBAAkB,CAAC,EAC1F,uBAAuB,CACxB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,mBAAmB,EAAE,UAAU,CAAC;SACvC,MAAM,CAAC,eAAe,EAAE,UAAU,CAAC;SACnC,MAAM,CAAC,sBAAsB,EAAE,iBAAiB,CAAC;SACjD,MAAM,CAAC,qBAAqB,EAAE,cAAc,CAAC;SAC7C,MAAM,CAAC,kBAAkB,EAAE,2BAA2B,CAAC;SACvD,MAAM,CAAC,oBAAoB,EAAE,6BAA6B,CAAC;SAC3D,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC;SACrC,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC;SACzC,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC;SAC7C,MAAM,CAAC,kBAAkB,EAAE,oBAAoB,CAAC;SAChD,MAAM,CAAC,0BAA0B,EAAE,2BAA2B,EAAE,QAAQ,CAAC;SACzE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;QAClC,MAAM,uBAAuB,CAC3B,kBAAkB,EAClB,CAAC,EAAE,EAAE,EAAE;YACL,MAAM,OAAO,GAAsB;gBACjC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC3C,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;gBACzD,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpD,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;gBACzC,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;gBACtD,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC5D,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBACtC,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;gBACzC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;gBAC5C,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;gBAC/C,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;aAC9E,CAAC;YAEF,OAAO,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1C,CAAC,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,yBAAyB,CAAC,2BAA2B,EAAE,IAAI,EAAE,kBAAkB,CAAC,EAC1F,uBAAuB,CACxB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,KAAK,CAAC,IAAI,CAAC;SACX,WAAW,CAAC,eAAe,CAAC;SAC5B,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QACzB,MAAM,uBAAuB,CAC3B,kBAAkB,EAClB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAC/B,GAAG,EAAE,CAAC,qBAAqB,CAAC,2BAA2B,CAAC,EACxD,uBAAuB,CACxB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,mBAAmB,CAAC;SAChC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QACzB,MAAM,uBAAuB,CAC3B,iBAAiB,EACjB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAC5B,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAClC,qBAAqB,CACtB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,sBAAsB,CAAC;SACnC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,uBAAuB,CAC3B,oBAAoB,EACpB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EACzB,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAClC,yBAAyB,CAC1B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { createProjectCommand } from './commands/project.js';
5
5
  import { createInboxCommand } from './commands/inbox.js';
6
6
  import { createSearchCommand } from './commands/search.js';
7
7
  import { createPerspectiveCommand } from './commands/perspective.js';
8
+ import { createTagCommand } from './commands/tag.js';
8
9
  const program = new Command();
9
10
  program
10
11
  .name('of')
@@ -15,5 +16,6 @@ program.addCommand(createProjectCommand());
15
16
  program.addCommand(createInboxCommand());
16
17
  program.addCommand(createSearchCommand());
17
18
  program.addCommand(createPerspectiveCommand());
19
+ program.addCommand(createTagCommand());
18
20
  program.parse();
19
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,IAAI,CAAC;KACV,WAAW,CAAC,iDAAiD,CAAC;KAC9D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,CAAC;AAE/C,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,IAAI,CAAC;KACV,WAAW,CAAC,iDAAiD,CAAC;KAC9D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,CAAC;AAC/C,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;AAEvC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
- import type { Task, Project, Perspective } from '../types.js';
1
+ import type { Task, Project, Perspective, Tag, TagStats, TaskStats, ProjectStats } from '../types.js';
2
2
  export declare function displaySuccessMessage(message: string): void;
3
- export declare function displayWithSuccessMessage<T extends Task | Project>(message: string, entity: T, displayFn: (entity: T) => void): void;
3
+ export declare function displayWithSuccessMessage<T extends Task | Project | Tag>(message: string, entity: T, displayFn: (entity: T) => void): void;
4
4
  export declare function displayPerspectiveList(perspectives: Perspective[]): void;
5
5
  export declare function pluralize(count: number, singular: string, plural?: string): string;
6
6
  export declare function displayTask(task: Task, verbose?: boolean): void;
@@ -9,4 +9,10 @@ export declare function displayProject(project: Project, verbose?: boolean): voi
9
9
  export declare function displayProjectList(projects: Project[], verbose?: boolean): void;
10
10
  export declare function displayTaskDetails(task: Task): void;
11
11
  export declare function displayProjectDetails(project: Project): void;
12
+ export declare function displayTag(tag: Tag, verbose?: boolean): void;
13
+ export declare function displayTagList(tags: Tag[], verbose?: boolean): void;
14
+ export declare function displayTagStats(stats: TagStats): void;
15
+ export declare function displayTaskStats(stats: TaskStats): void;
16
+ export declare function displayProjectStats(stats: ProjectStats): void;
17
+ export declare function displayTagDetails(tag: Tag): void;
12
18
  //# sourceMappingURL=display.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/lib/display.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAQ9D,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,IAAI,GAAG,OAAO,EAChE,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,EACT,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,GAC7B,IAAI,CAIN;AAMD,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,IAAI,CAKxE;AAiBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAiB,GAAG,MAAM,CAE1F;AAiBD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,UAAQ,GAAG,IAAI,CAuC7D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,OAAO,UAAQ,GAAG,IAAI,CAEpE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,UAAQ,GAAG,IAAI,CA8BtE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,UAAQ,GAAG,IAAI,CAE7E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CA0CnD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2B5D"}
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/lib/display.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQtG,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,IAAI,GAAG,OAAO,GAAG,GAAG,EACtE,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,EACT,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,GAC7B,IAAI,CAIN;AAMD,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,IAAI,CAKxE;AAiBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAiB,GAAG,MAAM,CAE1F;AAgCD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,UAAQ,GAAG,IAAI,CAuC7D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,OAAO,UAAQ,GAAG,IAAI,CAEpE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,UAAQ,GAAG,IAAI,CA8BtE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,UAAQ,GAAG,IAAI,CAE7E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CA0CnD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2B5D;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,UAAQ,GAAG,IAAI,CA0B1D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,OAAO,UAAQ,GAAG,IAAI,CAEjE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CA0BrD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAoBvD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAmB7D;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAoChD"}
@@ -38,6 +38,19 @@ function formatTags(tags, separator = ' ') {
38
38
  export function pluralize(count, singular, plural = `${singular}s`) {
39
39
  return `${count} ${count === 1 ? singular : plural}`;
40
40
  }
41
+ function displayMetric(label, value, valueColor) {
42
+ const formattedValue = valueColor ? valueColor(value.toString()) : value.toString();
43
+ console.log(chalk.gray(label.padEnd(25)) + formattedValue);
44
+ }
45
+ function displayTopList(title, items, countKey, color = chalk.cyan) {
46
+ if (items.length === 0)
47
+ return;
48
+ console.log();
49
+ console.log(chalk.bold(title));
50
+ items.forEach(item => {
51
+ console.log(` ${color(item.name)} ${chalk.gray(`(${item[countKey]} ${countKey})`)}`);
52
+ });
53
+ }
41
54
  function displayList(items, itemName, displayFn, verbose = false) {
42
55
  if (items.length === 0) {
43
56
  console.log(chalk.gray(`No ${itemName}s found`));
@@ -165,4 +178,117 @@ export function displayProjectDetails(project) {
165
178
  }
166
179
  console.log();
167
180
  }
181
+ export function displayTag(tag, verbose = false) {
182
+ const parts = [];
183
+ parts.push(tag.active ? chalk.green('●') : chalk.gray('○'));
184
+ parts.push(chalk.bold(tag.name));
185
+ parts.push(chalk.gray(`(${tag.taskCount} tasks, ${tag.remainingTaskCount} remaining)`));
186
+ if (tag.lastActivity) {
187
+ const activityDate = new Date(tag.lastActivity);
188
+ const dateStr = formatDistanceToNow(activityDate, { addSuffix: true });
189
+ parts.push(chalk.cyan(`active ${dateStr}`));
190
+ }
191
+ else {
192
+ parts.push(chalk.gray('never used'));
193
+ }
194
+ console.log(parts.join(' '));
195
+ if (verbose) {
196
+ console.log(chalk.gray(` ID: ${tag.id}`));
197
+ if (tag.added) {
198
+ console.log(chalk.gray(` Created: ${format(new Date(tag.added), 'PPP')}`));
199
+ }
200
+ if (tag.modified) {
201
+ console.log(chalk.gray(` Modified: ${format(new Date(tag.modified), 'PPP')}`));
202
+ }
203
+ }
204
+ }
205
+ export function displayTagList(tags, verbose = false) {
206
+ displayList(tags, 'tag', displayTag, verbose);
207
+ }
208
+ export function displayTagStats(stats) {
209
+ console.log();
210
+ console.log(chalk.bold.underline('Tag Usage Statistics'));
211
+ console.log();
212
+ displayMetric('Total Tags:', stats.totalTags, chalk.bold);
213
+ displayMetric('Active Tags:', stats.activeTags, chalk.green);
214
+ displayMetric('Tags with Tasks:', stats.tagsWithTasks, chalk.cyan);
215
+ displayMetric('Unused Tags:', stats.unusedTags, chalk.yellow);
216
+ displayMetric('Avg Tasks per Tag:', stats.avgTasksPerTag.toFixed(1));
217
+ displayTopList('Most Used Tags:', stats.mostUsedTags, 'taskCount', chalk.cyan);
218
+ displayTopList('Least Used Tags:', stats.leastUsedTags, 'taskCount', chalk.magenta);
219
+ if (stats.staleTags.length > 0) {
220
+ console.log();
221
+ console.log(chalk.bold('Stale Tags (no activity in 30+ days):'));
222
+ stats.staleTags.slice(0, 10).forEach(t => {
223
+ console.log(` ${chalk.red(t.name)} ${chalk.gray(`(${t.daysSinceActivity} days)`)}`);
224
+ });
225
+ if (stats.staleTags.length > 10) {
226
+ console.log(chalk.gray(` ... and ${stats.staleTags.length - 10} more`));
227
+ }
228
+ }
229
+ console.log();
230
+ }
231
+ export function displayTaskStats(stats) {
232
+ console.log();
233
+ console.log(chalk.bold.underline('Task Statistics'));
234
+ console.log();
235
+ displayMetric('Total Tasks:', stats.totalTasks, chalk.bold);
236
+ displayMetric('Active Tasks:', stats.activeTasks, chalk.yellow);
237
+ displayMetric('Completed Tasks:', stats.completedTasks, chalk.green);
238
+ displayMetric('Flagged Tasks:', stats.flaggedTasks, chalk.cyan);
239
+ displayMetric('Overdue Tasks:', stats.overdueActiveTasks, chalk.red);
240
+ displayMetric('Completion Rate:', `${stats.completionRate}%`);
241
+ if (stats.avgEstimatedMinutes !== null) {
242
+ displayMetric('Avg Estimate:', `${formatEstimate(stats.avgEstimatedMinutes)} (${stats.tasksWithEstimates} tasks)`);
243
+ }
244
+ displayTopList('Top Projects by Task Count:', stats.tasksByProject, 'taskCount', chalk.cyan);
245
+ displayTopList('Top Tags by Task Count:', stats.tasksByTag, 'taskCount', chalk.magenta);
246
+ console.log();
247
+ }
248
+ export function displayProjectStats(stats) {
249
+ console.log();
250
+ console.log(chalk.bold.underline('Project Statistics'));
251
+ console.log();
252
+ displayMetric('Total Projects:', stats.totalProjects, chalk.bold);
253
+ displayMetric('Active Projects:', stats.activeProjects, chalk.green);
254
+ displayMetric('On Hold Projects:', stats.onHoldProjects, chalk.yellow);
255
+ displayMetric('Dropped Projects:', stats.droppedProjects, chalk.red);
256
+ displayMetric('Sequential Projects:', stats.sequentialProjects, chalk.blue);
257
+ displayMetric('Parallel Projects:', stats.parallelProjects);
258
+ displayMetric('Avg Tasks per Project:', stats.avgTasksPerProject.toFixed(1));
259
+ displayMetric('Avg Remaining per Proj:', stats.avgRemainingPerProject.toFixed(1));
260
+ displayMetric('Avg Completion Rate:', `${stats.avgCompletionRate}%`);
261
+ displayTopList('Projects with Most Tasks:', stats.projectsWithMostTasks, 'taskCount', chalk.cyan);
262
+ displayTopList('Projects with Most Remaining Work:', stats.projectsWithMostRemaining, 'remainingCount', chalk.yellow);
263
+ console.log();
264
+ }
265
+ export function displayTagDetails(tag) {
266
+ console.log();
267
+ console.log(chalk.bold.underline(tag.name));
268
+ console.log();
269
+ const statusColor = tag.status === 'active' ? chalk.green :
270
+ tag.status === 'on hold' ? chalk.yellow : chalk.red;
271
+ console.log(chalk.gray('ID: ') + tag.id);
272
+ console.log(chalk.gray('Status: ') + statusColor(tag.status));
273
+ console.log(chalk.gray('Tasks: ') + `${tag.remainingTaskCount} remaining / ${tag.taskCount} total`);
274
+ console.log(chalk.gray('Allows Next Action:') + (tag.allowsNextAction ? 'Yes' : 'No'));
275
+ if (tag.parent) {
276
+ console.log(chalk.gray('Parent: ') + chalk.cyan(tag.parent));
277
+ }
278
+ if (tag.children.length > 0) {
279
+ console.log(chalk.gray('Children: ') + chalk.cyan(tag.children.join(', ')));
280
+ }
281
+ if (tag.added) {
282
+ console.log(chalk.gray('Created: ') + format(new Date(tag.added), 'PPP p'));
283
+ }
284
+ if (tag.modified) {
285
+ console.log(chalk.gray('Modified: ') + format(new Date(tag.modified), 'PPP p'));
286
+ }
287
+ if (tag.lastActivity) {
288
+ const activityDate = new Date(tag.lastActivity);
289
+ const dateStr = formatDistanceToNow(activityDate, { addSuffix: true });
290
+ console.log(chalk.gray('Last Activity: ') + `${format(activityDate, 'PPP p')} (${dateStr})`);
291
+ }
292
+ console.log();
293
+ }
168
294
  //# sourceMappingURL=display.js.map