BIKE Outliner – Sort Children of Selected Row (AZ Ascending and ZA Descending)

A pair of macros for Jesse Grosjean's Bike Outliner.

AZ ascending (or ZA descending) sort of the children of the selected row.


BikeSortingPairOfMacros.kmmacros (50.2 KB)


Expand disclosure triangle to view JS source
(() => {
    "use strict";

    // First draft of a `Sort children of selected line`
    // for Bike.

    // RobTrew @2022
    // Ver 0.02

    // --------------------- OPTION ----------------------

    // Edit the option value below to `true` if you need a
    // descending sort, or to `false` for ascending.

    const orderZA = false;

    // -------------- SORTED BIKE SIBLINGS ---------------
    // main :: IO ()
    const main = () => {
        const doc = Application("Bike").documents.at(0);

        return doc.exists() ? (() => {
            const
                rows = doc.rows,
                parentRow = rows.where({
                    _and: [
                        {selected: true},
                        {_not: [{
                            name: ""
                        }]}
                    ]
                }).at(0);

            return parentRow.exists() && (
                0 < parentRow.rows.length
            ) ? (() => {
                    const
                        children = parentRow.rows.where(
                            {_not: [{
                                name: ""
                            }]}
                        ),
                        sortOrder = orderZA ? (
                            flip(comparing(fst))
                        ) : comparing(fst);

                    return sortBy(sortOrder)(
                        zip(
                            children.name()
                        )(
                            children.id()
                        )
                    )
                    .map(
                        nameID => (
                            rows.byId(nameID[1]).move({
                                to: parentRow
                            }),
                            nameID[0]
                        )
                    )
                    .join("\n");
                })() : "No row with children selected.";
        })() : "No documents open in Bike";
    };

    // --------------------- GENERIC ---------------------

    // comparing :: Ord a => (b -> a) -> b -> b -> Ordering
    const comparing = f =>
    // The ordering of f(x) and f(y) as a value
    // drawn from {-1, 0, 1}, representing {LT, EQ, GT}.
        x => y => {
            const
                a = f(x),
                b = f(y);

            return a < b ? -1 : (a > b ? 1 : 0);
        };


    // flip :: (a -> b -> c) -> b -> a -> c
    const flip = op =>
    // The binary function op with
    // its arguments reversed.
        1 !== op.length ? (
            (a, b) => op(b, a)
        ) : (a => b => op(b)(a));


    // fst :: (a, b) -> a
    const fst = tpl =>
    // First member of a pair.
        tpl[0];


    // sortBy :: (a -> a -> Ordering) -> [a] -> [a]
    const sortBy = f =>
    // A copy of xs sorted by the comparator function f.
        xs => xs.slice()
        .sort((a, b) => f(a)(b));


    // zip :: [a] -> [b] -> [(a, b)]
    const zip = xs =>
    // The paired members of xs and ys, up to
    // the length of the shorter of the two lists.
        ys => Array.from({
            length: Math.min(xs.length, ys.length)
        }, (_, i) => [xs[i], ys[i]]);

    // MAIN ---
    return main();
})();

Other Keyboard Maestro macros for BIKE Outliner

4 Likes