Copy Text Line in any App for use as Bike Focal Row (found or created)

Where several lines are copied in the current Application, only the first is used.

If the copied line is found in the front Bike document, then
Bike outline focus is applied to that existing line and its outline subtree.

If the line is not found, it is created at the end of the Bike document,
and made focal.

Copy Text Line in any App for use as Bike Focal Row (found or created).kmmacros (7.2 KB)


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

    // First line of clipboard text used as Bike focal row
    // (either found in front document or created at its end)
    const main = () => {
        const
            bike = Object.assign(
                Application("Bike"),
                { includeStandardAdditions: true }
            ),
            doc = bike.documents.at(0);

        return doc.exists()
            ? (() => {
                const clip = bike.theClipboard();

                return "string" === typeof clip
                    ? firstLineAsBikeFocalRow(bike)(doc)(
                        clip
                    )
                    : "No text found in clipboard."
            })()
            : "No document open in Bike.";
    };


    // ---------------------- BIKE -----------------------

    // firstLineAsBikeFocus :: Application -> 
    // Document -> String -> IO String
    const firstLineAsBikeFocalRow = bike =>
        doc => s => {
            const firstLine = lines(s)[0].trim();

            return 0 < firstLine.length
                ? (
                    bike.activate(),
                    doc.focusedRow = bikeRowFoundOrCreated(
                        bike
                    )(doc)(firstLine),
                    doc.focusedRow.name()
                )
                : "No text found in clipboard";
        };


    // bikeRowFoundOrCreated :: Application ->
    // Document -> String -> IO Row
    const bikeRowFoundOrCreated = bike =>
        // Either the first row in the document matching
        // the name, or a new row with that name, 
        // at the end of the document.
        doc => name => {
            const matches = doc.rows.where({ name });

            return 0 < matches.length
                ? matches.at(0)
                : (() => {
                    const newRow = new bike.Row({ name });

                    return (
                        doc.rows.push(newRow),
                        newRow
                    );
                })();
        };

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

    // lines :: String -> [String]
    const lines = s =>
        // A list of strings derived from a single string
        // which is delimited by \n or by \r\n or \r.
        0 < s.length
            ? s.split(/\r\n|\n|\r/u)
            : [];

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