Combining TaskPaper with 'Tyme' (for time session tracking)?

Here is a first draft of a Tyme 2 version which simply toggles tracking for the item selected in the front document of TaskPaper 3.

Would you like to test it ?

Tyme 2 allows us to assign categories (clients etc) to projects, but the scripting interface doesn’t seem to give us access to that (yet ?) I would really like to get it to pick up a client tag from TaskPaper 3, and find/create the project in a matching Tyme2 category, but I think that may be out of reach, at least for the moment.

Seems to be working on my system OSX 10.11, TaskPaper 3.3 (211), Tyme2 (Version 1.3.2 (1850))

// Ver 0.003

// 0.002 stops tracking of any other task before starting tracking for this one
//          (rather than simply toggling tracking for the selected task only)
// 0.003 Updated to be unaffected by changes in TaskPaper app id

// Toggling Tyme2 tracking for the item selected in TaskPaper 3's front document

(function (dctOptions) {

    // TASKPAPER CONTEXT
    function TaskPaperContext(editor, options) {
        var item = editor
            .selection
            .startItem;

        var projects = editor.outline
            .evaluateItemPath('ancestor::project[-1]', item);

        return {
            project: projects.length ? (
                projects[0].bodyContentString
            ) : (options.defaultProject || 'Miscellaneous'),
            task: item ? item.bodyContentString : undefined
        }
    }

    // JAVASCRIPT FOR AUTOMATION CONTEXT

    // Found or created item in a collection exposed by an app
    // E.g. a project or a task in Tyme2

    // Object -> Object -> String -> Object -> Object
    function foundOrCreated(app, oParent, strClass, dctProps) {
        'use strict';

        // elements
        var elements = oParent[
                strClass.charAt(0)
                .toLowerCase() + strClass.substr(1) + 's'
            ],

            // dctProps -> lstTests
            lstTests = Object.keys(dctProps)
            .map(function (k) {
                var dct = {};
                return dct[k] = dctProps[k], dct;
            }, {}),

            // found or created
            found = elements.whose(
                (lstTests.length > 1 ? {
                    _and: lstTests
                } : lstTests[0])
            ),

            blnFound = found.length > 0,
            elem = (blnFound ? found()[0] : app[strClass](dctProps));

        // pushed into collection if new
        return (blnFound || elements.push(elem)), elem;
    }


    var ds = Application('TaskPaper')
        .documents,

        dctTP3Seln = ds.length ? ds[0].evaluate({
            script: TaskPaperContext.toString(),
            withOptions: dctOptions
        }) : undefined;


    if (dctTP3Seln && dctTP3Seln.task) {
        // TYME 2
        var Tyme2 = Application('de.lgerckens.Tyme2'),

            oTask = foundOrCreated(
                Tyme2,
                foundOrCreated(
                    Tyme2, Tyme2,
                    "Project", {
                        name: dctTP3Seln.project
                    }
                ),
                "Task", {
                    name: dctTP3Seln.task,
                    tasktype: 'timed'
                }
            ),
            
            // Toggle tracking
            strID = oTask.id(),
            lstTracking = Tyme2.trackedtaskids(),
            blnTracking = lstTracking.length && lstTracking
            .indexOf(strID) !== -1;

        // pause all existing tracking
        lstTracking.forEach(function (x) {
            return Tyme2.stoptrackerfortaskid(x);
        });

        // and start tracking for this item if required
        if (!blnTracking) {
            Tyme2.starttrackerfortaskid(strID)
        }
    }

})({
    defaultProject: 'Miscellaneous' // for tasks not enclosed by a TP3 project
});
2 Likes