Script to move @today items to top of project

Hi all,

I’m trying to create a script that moves all @today items to the top of their project and @waiting items to the bottom. I used to have on for TP2, but making one for TP3 / jxa is proving a bit more difficult to start with. Would anyone happen to have some pointers / boilerplate code to start with? I’m somewhat able to code myself, but would appreciate some ideas how to build this!

thanks!
Maarten

2 Likes

Can post your old TP2 script ?

(That would simplify getting the details so that we can sketch a TP3 version for you)

Very crude, but see below. I can’t really see how to include code like this nicely so I’ve included it as preformatted text:

tell application "TaskPaper" tell front document set p to «class STcp» of «class STsy» set move_entry_ids to {} set done_entry_ids to {} repeat with each in every «class TPer» of p if exists («class TPtg» named "waiting" of each) then set done_entry_ids to done_entry_ids & id of each else set move_entry_ids to move_entry_ids & done_entry_ids set done_entry_ids to {} end if end repeat repeat with each in move_entry_ids move «class TPer» id each to end of every «class TPer» of p end repeat end tell end tell

A rough indication – only for testing with dummy data:

(function () {
    'use strict';

    // TASKPAPER CONTEXT

    function TaskPaperContext(editor, options) {

        var outline = editor.outline,
            projects = outline.evaluateItemPath(
                '//@waiting or @today/ancestor::project'
            );

        outline.groupUndoAndChanges(function () {
            projects.forEach(function (p) {
                // THREE TYPES OF ITEM IN THE PROJECT
                // Where ! means (not ...)
                var lstChildren = p.children,

                    // @waiting (unless also @today)
                    lstWaiting = lstChildren.filter(function (x) {
                        return x.hasAttribute('data-waiting') &&
                            !x.hasAttribute('data-today');
                    }),

                    // anything tagged @today
                    lstToday = lstChildren.filter(function (x) {
                        return x.hasAttribute('data-today');
                    }),

                    // anything with neither @today nor @waiting
                    lstOther = lstChildren.filter(function (x) {
                        return !x.hasAttribute('data-today') &&
                            !x.hasAttribute('data-waiting');
                    });

                // Remove from existing position
                lstChildren.forEach(function (x) {
                    x.removeFromParent();
                });
                // and reinsert in order
                p.appendChildren(lstToday.concat(lstOther, lstWaiting));
            })
        });
    }

    // JAVASCRIPT FOR AUTOMATION CONTEXT

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

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

})();
1 Like

This is absolutely terrific! Exactly what I was looking for and a nice way to up my own coding skills a bit by adapting this. Thanks so much! Small dummy question: how do you embed Javascript code in a post, I seem to overlook that option in the forum editor

See under ‘Github fenced code blocks’

```javascript
  
     4 space indented code goes here

```

If you want to experiment with a slightly different approach – possibly quicker to fine-tune – you could try doing it all with paths:

(function () {
    'use strict';

    // TASKPAPER CONTEXT

    function TaskPaperContext(editor, options) {

        // concatMap :: (a -> [b]) -> [a] -> [b]
        var concatMap = function (f, xs) {
            return [].concat.apply([], xs.map(f));
        };

        var outline = editor.outline,
            projects = outline.evaluateItemPath(
                '//@waiting or @today/ancestor::project'
            );

        outline.groupUndoAndChanges(function () {
            projects.forEach(function (p) {
                // THREE TYPES OF ITEM IN THE PROJECT
               
                var filter = function (strPath) {
                        return outline.evaluateItemPath(strPath, p);
                    },

                    lstOrdered = concatMap(filter, [
                        '@today',
                        'not (@waiting or @today)',
                        '@waiting and not @today'
                    ]);

                // Remove from existing position
                p.children.forEach(function (x) {
                    x.removeFromParent();
                });
                // and reinsert in order
                p.appendChildren(lstOrdered);
            });
        });
    }

    // JAVASCRIPT FOR AUTOMATION CONTEXT

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

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

})();