How to jump to a task in `focus` fast by string

Say I have this bike document with these root nodes:

I have a macro that takes a task from Things, moves it to over to Bike. Like so:

However I want to make a change so that if there is an existing root node with the text I pass, it will just jump focus into it.

How can I query if there is a root node with this exact text, if yes, focus in on it. If not, create a new root node with a structure I pass.

Thanks.

If you are going to use AppleScript, there are two basic patterns for finding a matching row:

either the where/whose syntax:

set searchString to "omicron"

tell application "Bike"
    tell front document
        set refMatches to a reference to (rows where name = searchString)
        -- set refMatches to a reference to (rows where name contains searchString)
        
        if 0 < (count of refMatches) then
            set target to item 1 of refMatches
            
            set focused row to target
            name of target
        else
            "No row found containing string."
        end if
    end tell
end tell

or the outline path pattern:

tell application "Bike"
    tell front document
        set matches to query it outline path "//" & searchString
        
        if 0 < length of matches then
            set target to item 1 of matches
            
            set focused row to target
            name of target
        else
            "No row found matching outline path."
        end if
    end tell
end tell
1 Like

For a JavaScript version, see:

Or in Script Editor (with language selector at top left set to JavaScript):

Expand disclosure triangle to view JS source
(() => {
    "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();
})();

See: Using Scripts | Bike

1 Like