Copying Text Statistics

Not sure if there is another way of doing this at the moment, but here, FWIW (for use in Bike Preview 1.9 (109)) is a script to copy a tab-delimited set of any text statistics strings displayed at bottom left of the screen.

To test in Script Editor, set the language selector at top left to JavaScript (rather than AppleScript).

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

    // ---- COPYING TEXT STATISTICS STRINGS FROM BIKE ----

    // (Copies a tab-delimited string)
    // For Bike Preview 1.9 (109+)

    // Rob Trew @2023
    // Ver 0.02

    //     Filters out non-stat strings if the
    //     Edit > Checking > Show Checking...
    //     dialog is showing.

    ObjC.import("AppKit");

    // main :: IO ()
    const main = () =>
        either(
            alert("Copy Bike Text Statistics")
        )(
            copyText
        )(
            bindLR(
                bikeFrontWindowLR()
            )(
                window => bindLR(
                    window.exists() ? (
                        Right(window.splitterGroups.at(0))
                    ) : Left("No standard window open in Bike.")
                )(
                    splitter => splitter.exists() ? (
                        splitterStatsLR(splitter)
                    ) : Left("No text statistics displayed.")
                )
            )
        );


    // bikeFrontWindowLR :: () -> Either String Window
    const bikeFrontWindowLR = () => {
        const
            bikeProcess = Application("System Events")
            .applicationProcesses.where({name: "Bike"})
            .at(0);

        return bikeProcess.exists() ? (
            Right(
                bikeProcess.windows.where({
                    subrole: "AXStandardWindow"
                }).at(0)
            )
        ) : Left("Bike not running");
    };


    // splitterStatsLR :: Splitter -> Either String String
    const splitterStatsLR = splitter => {
        const
            digit = /^[0-9]+/u,
            report = splitter.buttons.name()
            .filter(s => digit.test(s))
            .join("\t");

        return 0 < report.length ? (
            Right(report)
        ) : Left("No text statistics displayed.");
    };


    // ----------------------- JXA -----------------------

    // alert :: String => String -> IO String
    const alert = title =>
        s => {
            const sa = Object.assign(
                Application("System Events"), {
                    includeStandardAdditions: true
                });

            return (
                sa.activate(),
                sa.displayDialog(s, {
                    withTitle: title,
                    buttons: ["OK"],
                    defaultButton: "OK"
                }),
                s
            );
        };

    // copyText :: String -> IO String
    const copyText = s => {
        const pb = $.NSPasteboard.generalPasteboard;

        return (
            pb.clearContents,
            pb.setStringForType(
                $(s),
                $.NSPasteboardTypeString
            ),
            s
        );
    };

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

    // Left :: a -> Either a b
    const Left = x => ({
        type: "Either",
        Left: x
    });


    // Right :: b -> Either a b
    const Right = x => ({
        type: "Either",
        Right: x
    });


    // bindLR (>>=) :: Either a ->
    // (a -> Either b) -> Either b
    const bindLR = m =>
        mf => m.Left ? (
            m
        ) : mf(m.Right);


    // either :: (a -> c) -> (b -> c) -> Either a b -> c
    const either = fl =>
        // Application of the function fl to the
        // contents of any Left value in e, or
        // the application of fr to its Right value.
        fr => e => e.Left ? (
            fl(e.Left)
        ) : fr(e.Right);

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

See: Using Scripts - Bike

1 Like

Updated (above) to ignore non-stat strings when the

Edit > Checking > Show Checking...

dialog is showing.

1 Like

In latest release I also make this text fields selectable. Probably script is still more useful.

1 Like