Toggling Multiple Tags with Single Command

and if you wanted to edit the cycle of tags a little more easily, you could experiment with variants like this:

/* eslint-disable max-lines-per-function */
(() => {
    "use strict";

    // Ver 0.02
    // A bit of tidying

    // - TOGGLING SELECTED ITEMS THROUGH A CYCLE OF TAGS -

    // main :: IO ()
    const main = () =>
        Application("TaskPaper").documents.at(0)
        .evaluate({
            script: `${TaskPaperContextScript}`,
            withOptions: {
                tagCycle: [
                    "important",
                    "next",
                    "today",
                    "incubate",
                    "waiting",
                    "declined"
                ]
            }
        });

    // -------------------- TASKPAPER --------------------

    const TaskPaperContextScript = (editor, options) => {

        const tpMain = () => {
            const
                outline = editor.outline,
                selection = editor.selection,
                tagCycle = options.tagCycle;

            outline.groupUndoAndChanges(() =>
                selection.selectedItems.forEach(
                    item => bimap(
                        k => k && item.removeAttribute(
                            `data-${k}`
                        )
                    )(
                        k => k && item.setAttribute(
                            `data-${k}`, ""
                        )
                    )(
                        foundAndNext(tagCycle)(item)
                    )
                )
            );

            editor.moveSelectionToItems(selection);
        };

        // foundAndNext :: [String] ->
        // Item -> (String, String)
        const foundAndNext = tagNames =>
            // A Tuple of the first found tag in the cycle,
            // if any, and the next tag in the cycle, if any.
            item => {
                const
                    iLast = tagNames.length - 1,
                    mbi = tagNames.findIndex(
                        k => item.hasAttribute(`data-${k}`)
                    );

                return 0 <= iLast ? (
                    -1 !== mbi ? (
                        iLast !== mbi ? [
                            tagNames[mbi],
                            tagNames[1 + mbi]
                        ] : [tagNames[iLast], ""]
                    ) : ["", tagNames[0]]
                ) : ["", ""];
            };


        // bimap :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)
        const bimap = f =>
            // Tuple instance of bimap.
            // A tuple of the application of f and g to the
            // first and second values respectively.
            g => ab => [f(ab[0]), g(ab[1])];


        // TaskPaper context main function called.
        return tpMain();
    };

    // Script main function called.
    return main();
})();
2 Likes