Action

Project to OmniFocus

Posted by Andrew Payne, Last update 2 days ago

Creates a Task Group in the inbox from tasks in the draft. It prompts for Project Name, Due Date, Defer Date, and Task names.

It will create a task group in the inbox ready to be dragged and organized in projects.

It will replace the mark down with ‘- [OF]’ to indicate that the task has been sent to Omnifocus and prevent it from being sent again.

Steps

  • script

    // Send markdown tasks to OmniFocus as a task group with name, dates, and tags
    
    const tasks = [];
    const newLines = [];
    const taskRegex = /^\s*-\s*\[\s*\]\s*(.+)/; 
    
    draft.lines.forEach(line => {
    	const match = line.match(taskRegex);
    	if (match) {
    		// match[1] is the captured task content
    		tasks.push(`- ${match[1].trim()}`);
    		// Mark task as completed and add [OF] marker
    		newLines.push(line.replace(/\[\s*\]/, '[OF]'));
    	} else {
    		newLines.push(line);
    	}
    });
    
    const taskCount = tasks.length;
    
    if (taskCount > 0) {
    	const p = Prompt.create();
    	p.title = "Create OmniFocus Project";
    	p.message = "Enter project details";
    	
    	p.addTextField("name", "Project Name", "");
    	p.addTextField("dueDate", "Due Date", "", {placeholder: "e.g., tomorrow, next week"});
    	p.addTextField("deferDate", "Defer Date", "", {placeholder: "e.g., today, next Monday"});
    	p.addTextField("tags", "Tags", "", {placeholder: "e.g., work, urgent (comma separated)"});
    	
    	p.addButton("Create Project");
    	
    	if (!p.show()) {
    		context.cancel("User cancelled.");
    	}
    	
    	const { name, dueDate, deferDate, tags } = p.fieldValues;
    	
    	if (!name || name.trim() === "") {
    		app.displayWarningMessage("Project name is required.");
    		context.cancel("Project name not provided.");
    	}
    	
    	const projectName = name.trim();
    	// Project type is now hard-coded to parallel
    	const projectType = "@parallel"; 
    	let taskpaperContent = [`${projectName}: ${projectType}`];
    
    	// Helper function to append tags
    	const appendTag = (value, tag) => {
    		if (value && value.trim() !== "") {
    			return ` @${tag}(${value.trim()})`;
    		}
    		return "";
    	};
    
    	let projectHeader = taskpaperContent[0];
    	projectHeader += appendTag(dueDate, "due");
    	projectHeader += appendTag(deferDate, "defer");
    
    	if (tags && tags.trim() !== "") {
    		const tagList = tags.split(',')
    			.map(t => t.trim())
    			.filter(t => t !== "")
    			.join(', ');
    			
    		if (tagList) {
    			projectHeader += ` @tags(${tagList})`;
    		}
    	}
    	taskpaperContent[0] = projectHeader;
    
    	const indentedTasks = tasks.map(t => `\t${t}`);
    	const taskpaper = taskpaperContent.concat(indentedTasks).join("\n");
    	
    	const cb = CallbackURL.create();
    	cb.baseURL = "omnifocus://x-callback-url/paste";
    	cb.addParameter("content", taskpaper);
    	
    	if (!cb.open()) {
    	    app.displayErrorMessage("Failed to send to OmniFocus.");
    	    context.fail("OmniFocus callback failed.");
    	}
    	
    	draft.content = newLines.join("\n");
    	draft.update();
    	
    	const pluralS = taskCount === 1 ? '' : 's';
    	app.displayInfoMessage(`Created project "${projectName}" with ${taskCount} task${pluralS} in OmniFocus`);
    
    } else {
    	app.displayInfoMessage("No uncompleted tasks found.");
    }

Options

  • After Success Default
    Notification Info
    Log Level Info
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.