TaskPaper 3 archive @done items and log to Day One (v1 or v2)

A macro for TaskPaper 3 and Day One 2 (or 1)

TaskPaper 3 archive @done and log to Day One ver 1 or 2.kmmacros (26.5 KB)

(Contains a JavaScript for Automation translation of an earlier AppleScript by Brett Terpstra.
Brett's original script was for TaskPaper 2 and Day One 1)

This macro:

  1. Moves items tagged as @done to an Archive: project in the same TaskPaper 3 file
  2. Logs a record of the completed items to Day One version one or two (whichever is installed)
  3. Gives a notification

JavaScript for Automation Source of the main action:

// VER 0.05
// TASKPAPER 3 ARCHIVE DONE AND LOG TO DAY ONE Ver 1 or 2

// A JavaScript for Applications translation of an orginal script by Brett Terpstra
// http://brettterpstra.com/2012/02/23/log-taskpaper-archives-to-day-one/
// For TaskPaper 3, and DayOne version 1 or 2

(function (dctOptions) { // For option keys and their values, see end of script
    'use strict';

    // TASKPAPER 3 EVALUATION CONTEXT:

    function fn(editor, options) {

        // Task with some of its tags removed
        function tagsPruned(oTask, lstNoiseTags) {
            return lstNoiseTags.reduce(function (t, strTag) {
                var strAttrib = 'data-' + strTag;

                if (t.hasAttribute(strAttrib)) {
                    t.removeAttribute(strAttrib);
                }
                return t;
            }, oTask);
        }

        // Task with a @project(strProjName) tag added (if not found)
        function projectTagged(oTask) {
            if (!oTask.hasAttribute('data-project')) {
                if (oTask.getAttribute('data-type') !== 'project') {
                    var project = taskProject(oTask),
                        strProj = project ? (function () {
                            var strText = project.bodyString;

                            return strText.slice(0, strText.indexOf(':'));
                        })() : '';

                    if (strProj) oTask.setAttribute('data-project', strProj);
                }
            }
            return oTask;
        }

        // Immediately enclosing project of the task
        function taskProject(oTask) {
            var p = oTask,
                blnFound = false;
            while (!(blnFound = (p.getAttribute('data-type') === 'project'))) {
                p = p.parent;
            }
            return blnFound ? p : undefined;
        }


        // ARCHIVE AND LOG

        var outline = editor.outline,

            // EXISTING OR NEW ARCHIVE PROJECT ?
            as = editor.outline.evaluateItemPath(
                '/(Archive and @type=project)[-1]'
            ),
            archive = as.length > 0 ? as[0] : (function () {
                var newArchive = outline.createItem('Archive:');

                outline.groupUndoAndChanges(function () {
                    outline.root.appendChildren(
                        newArchive
                    );
                });
                return newArchive;
            })(),

            oFirstChild = archive.firstChild || (function () {
                outline.groupUndoAndChanges(function () {
                    archive.appendChildren(outline.createItem());
                });
                return archive.firstChild;
            })();


        // COMPLETED BUT UNARCHIVED TASKS ?
        tasks = outline.evaluateItemPath('@done except /Archive//*');


        // ARCHIVED AND LISTED
        if (tasks.length > 0) {

            // If we have a non-circular destination, make the move ...
            if (oFirstChild && (tasks.indexOf(oFirstChild) === -1)) {
                var lstNoise = options.tagsToStrip,

                    strProjectPrefix = options.projectPrefix;

                // project-tagged and noise-tag-pruned
                outline.groupUndoAndChanges(function () {
                    outline.insertItemsBefore(
                        tasks.map(function (x) {
                            return projectTagged(tagsPruned(
                                x,
                                lstNoise));
                        }),
                        oFirstChild
                    );
                });

                // loggable string
                return tasks.map(function (t) {
                        return (
                            t.getAttribute(
                                'data-type'
                            ) === 'project' ? strProjectPrefix : ''
                        ) + t.bodyString;
                    })
                    .join('\n');
            } else return [];
        } else return '';
    }

    // JS FOR APPLICATIONS EVALUATION CONTEXT:

    var ds = Application("com.hogbaysoftware.TaskPaper3")
        .documents,
        d = ds.length ? ds[0] : undefined,
        strFileName = d ? d.name() : '',

        strHeader = dctOptions.fileNameAsHeader && d ? (
            '## ' + strFileName + '\n\n'
        ) : '',

        strArchive = d ? d.evaluate({
            script: fn.toString(),
            withOptions: {
                tagsToStrip: ['na', 'next', 'priority', 'waiting'],

                projectPrefix: dctOptions.projectPrefix
            }
        }) : '';


    // Submits the string to Day One through the command line tool at:
    //      http://dayoneapp.com/faq/#commandlineinterface
    //
    // Day One Ver 1 may need:
    // Run `ln -s "/Applications/Day One/Day One.app/Contents/MacOS/dayone" /usr/local/bin/dayone` 
    // to make it available on that path

    // Day One Ver 2:
    // -- The CLI will generates an error unless we specify a default journal
    // You may need to run:
    // $ alias dayone='/usr/local/bin/dayone -j=\"~/Library/Group\ Containers/5U8NS4GX82.dayoneapp2/Data/Auto\ Import/Default\ Journal.dayone\"'

    if (strArchive) {
        var a = Application.currentApplication();

        (a.includeStandardAdditions = true, a)
        .doShellScript(
            '/usr/local/bin/dayone' + (dctOptions.dayOneVersion > 1 ? (
                ' -j="~/Library/Group\ Containers/5U8NS4GX82.dayoneapp2/Data/Auto\ Import/Default\ Journal.dayone"'
            ) : '') +
            ' new <<T3DY2_END\n' + strHeader + strArchive +
            '\nT3DY2_END'
        );

        return JSON.stringify({
            fileName: strFileName,
            logged: strArchive
        }, null, 2);

    } else return '';

    // OPTIONS
})({ // Precede each log with TaskPaper filename as header ? 
    fileNameAsHeader: true,

    projectPrefix: '### ', // Day One prefix for projects ? ( '' to skip )

    // Day One Version (auto-detects) or manually specify 1 or 2
    dayOneVersion: parseInt(
        Application("Day One")
        .version()
        .charAt(0), 10
    )
})

I’m using the latest version of Day One and have executed the alias noted in the script. It does move all of the @done items in my Taskpaper file to the bottom of the file but I’m getting an error and these items are not being put in Day One.

The script error is:

/var/folders/zr/xg8c2lcj0m7bp8l181_hzmbm0000gn/T/Keyboard-Maestro-Script-016D4F93-DC7A-428D-95BB-94B15B4405A3:34:62: execution error: Error on line 4: SyntaxError: JSON Parse error: Unrecognized token ‘/’ (-2700)

Any thoughts on what I need to do correct this?

Okay, just ignore the old guy in the corner…

I had not installed the Day One CLI. All is well now.

1 Like

UPDATE:

A refreshed version of the macro (editable time of original post seems to have elapsed).

TaskPaper 3 archive @done and log to Day One ver 1 or 2.kmmacros (26.4 KB)

If an earlier build of Day One 2 was not interacting properly with the CLI, it may be worth reinstalling the CLI from:

http://help.dayoneapp.com/day-one-tools/

http://dayoneapp.com/downloads/dayone-cli.pkg

I have re-installed the latest CLI and I am running DayOne Classic but I also have this JSON error. How could I solve this ?

I don't, unfortunately, have a copy of Day One v1 to test with, but there is some discussion of the relationships between the two versions and CLI use in this thread:

Thank you, but the CLI on itself seems to work correctly.

The error :

/var/folders/2t/z7x_mzs52n7_qmwdxpgm8_xm0000gn/T/Keyboard-Maestro-Script-D33879FD-6D56-4BE1-922E-E9676E22DC06:164:203: execution error: Error on line 9: SyntaxError: JSON Parse error: Unrecognized token ‘/’ (-2700)

Which line 9 is this ? There does not seem to be anything wrong with line 9 in the script.

What is this construct:

‘dayone ’ + …
’ new <<T3DY2_END\n’ + strHeader + strArchive +
’\nT3DY2_END’

What is T3DY2_END ?

Sorry, I am not an experience javascript programmer :wink:

The way in which the script calls the CLI is appropriate for Day One 2, but not for Day One Classic, of which, alas I have no copy.

The JSON parse error simply arises from an attempt to the unexpected output which arises from this.

The advice that you will need to get from the suppliers of Day One is, I think, more about the appropriate command line paths (shell script) for Day One v1 than about JavaScript.

I can’t guarantee, however, that the script can necessarily be adapted for Day One v 1, and as I don’t own it I am not in a position to support it. Good luck !

The following script works nicely on its own and as intended (DayOne Classic) so it does not look like the problem is in the CLI (essentials clipped from the script). I am not a programmer so I feel a bit lost with this error.

(function () {
    var a = Application.currentApplication();

    (a.includeStandardAdditions = true, a)
    .doShellScript(
        '/usr/local/bin/dayone new <<T3DY2_END\n' + 'Hello Jaap' +
        '\nT3DY2_END\n'
    );
})();