Copy Action(s) selected In Keyboard Maestro as JSON

Copy Selected Keyboard Maestro Action(s) as JSON.kmmacros (7.4 KB)


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

    ObjC.import("AppKit");

    // Rob Trew @2023
    // Ver 0.2

    const main = () =>
        either(
            alert("Copy KM selection as JSON")
        )(
            jso => copyText(
                JSON.stringify(jso, null, 2)
            )
        )(
            bindLR(
                clipTextLR()
            )(
                jsoFromPlistStringLR
            )
        );


    // ----------------------- 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
            );
        };


    // clipTextLR :: () -> Either String String
    const clipTextLR = () => {
        // Either a message, or the plain text
        // content of the clipboard.
        const
            mb = $.NSPasteboard.generalPasteboard
                .stringForType($.NSPasteboardTypeString);

        return mb.isNil() ? (
            Left("No utf8-plain-text found in clipboard.")
        ) : Right(ObjC.unwrap(mb));
    };


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

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


    // jsoFromPlistStringLR :: XML String -> Either String Dict
    const jsoFromPlistStringLR = xml => {
        // Either an explanatory message, or a
        // JS dictionary parsed from the plist XML
        const
            nsErrorRef = $(),
            nsObject = $.NSPropertyListSerialization
                .propertyListWithDataOptionsFormatError(
                    $(xml).dataUsingEncoding(
                        $.NSUTF8StringEncoding
                    ),
                    0, 0, nsErrorRef
                );

        return nsObject.isNil() ? {
            Left: ObjC.unwrap(
                nsErrorRef.localizedDescription
            )
        } : {
            Right: ObjC.deepUnwrap(nsObject)
        };
    };


    // --------------------- 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();
})();



1 Like

To make the most of your macro, I'm curious about its advantages compared to DanThomas' KMET: Edit KM Objects as Text (Search & Replace) Version 1.3 macro.