diff --git a/README.md b/README.md index f474497..4fcadd6 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ of task create "Name" [options] --note # Add note of task update [options] - --complete # Mark completed + --complete / --incomplete # Mark completed/incomplete + --drop / --undrop # Mark dropped/restore to active --flag / --unflag # Toggle flag --name # Rename --project/--tag/--due/--defer # Same as create diff --git a/src/commands/task.ts b/src/commands/task.ts index fa39205..659a22d 100644 --- a/src/commands/task.ts +++ b/src/commands/task.ts @@ -71,6 +71,8 @@ export function createTaskCommand(): Command { .option('-F, --unflag', 'Unflag the task') .option('-c, --complete', 'Mark as completed') .option('-C, --incomplete', 'Mark as incomplete') + .option('--drop', 'Mark as dropped') + .option('--undrop', 'Restore a dropped task to active') .option('-e, --estimate ', 'Estimated time in minutes', parseInt) .action( withErrorHandling(async (idOrName, options) => { @@ -90,6 +92,8 @@ export function createTaskCommand(): Command { ...(options.unflag && { flagged: false }), ...(options.complete && { completed: true }), ...(options.incomplete && { completed: false }), + ...(options.drop && { dropped: true }), + ...(options.undrop && { dropped: false }), ...(options.estimate !== undefined && { estimatedMinutes: options.estimate }), }; const task = await of.updateTask(idOrName, updates); diff --git a/src/lib/omnifocus.ts b/src/lib/omnifocus.ts index 0eea0c7..88539ef 100644 --- a/src/lib/omnifocus.ts +++ b/src/lib/omnifocus.ts @@ -43,7 +43,7 @@ export class OmniFocus { name: task.name, note: task.note || null, completed: task.completed, - dropped: task.dropped, + dropped: task.dropDate !== null, effectivelyActive: task.effectiveActive, flagged: task.flagged, project: containingProject ? containingProject.name : null, @@ -354,6 +354,16 @@ export class OmniFocus { if (options.completed !== undefined) { updates.push(options.completed ? 'task.markComplete();' : 'task.markIncomplete();'); } + if (options.dropped !== undefined) { + updates.push( + options.dropped + ? 'task.drop(false, null);' + // Guard against reactivating a completed task: `active` isn't + // specific to "dropped", so undrop is a no-op on a task that's + // completed rather than dropped. + : 'if (!task.completed) { task.active = true; }' + ); + } if (options.estimatedMinutes !== undefined) { updates.push(`task.estimatedMinutes = ${options.estimatedMinutes};`); } diff --git a/src/mcp/server.ts b/src/mcp/server.ts index 56f6720..ab93388 100644 --- a/src/mcp/server.ts +++ b/src/mcp/server.ts @@ -92,6 +92,7 @@ server.tool( flagged: z.boolean().optional().describe('Flag/unflag the task'), estimatedMinutes: z.number().optional().describe('New estimated duration'), completed: z.boolean().optional().describe('Mark complete/incomplete'), + dropped: z.boolean().optional().describe('Mark dropped/undropped'), }, async ({ idOrName, ...options }) => jsonResponse(await of.updateTask(idOrName, options)) ); diff --git a/src/types.ts b/src/types.ts index c058dd8..af376f8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -63,6 +63,7 @@ export interface UpdateTaskOptions { flagged?: boolean; estimatedMinutes?: number; completed?: boolean; + dropped?: boolean; } export interface CreateProjectOptions {