Getting a list of KM clipboard names?

Is there a KM action or scripting method which can yield a list of KM clipboard names ?

( as displayed by KM > Preferences > Clipboards )

( apart from by shameless UI kludge, that is :open_mouth: :see_no_evil: ... )

List of KM Clipboards ( by UI scripting kludge ).kmmacros (25.3 KB)

Hey Rob,

Try this:

set plistFile to ((path to application support from user domain as text) & "Keyboard Maestro:Keyboard Maestro Clipboards.plist")

tell application "System Events"
  tell property list file plistFile
    tell property list items
      set kmClipboardNames to value of its property list item 3
    end tell
  end tell
end tell

-Chris

1 Like

Perfect – thank you!

( and very helpful to know that that .plist is there )

In JavaScript for Applications, the Macros.plist file can be read quite simply and directly with $.NSDictionary, but I think that requires a dict rather than an array at the top level.

Falling back to the more general $.NSXMLDocument for this one, we could get our array of Clipboard names with something like:

(function () {
  var a = Application.currentApplication(),
    strPath = (
      a.includeStandardAdditions = true, a
    ).pathTo(
      'application support', {
        from: 'user domain'
      }
    ) + "/Keyboard Maestro/Keyboard Maestro Clipboards.plist";

  return ObjC.unwrap(
    $.NSXMLDocument.alloc.initWithXMLStringOptionsError(
      ObjC.unwrap(
        $.NSString.stringWithContentsOfFile(strPath)
      ),
      0, null
    ).rootElement.childAtIndex(0).children
  ).map(
    function (x) {
      return ObjC.unwrap(
        x.childAtIndex(3).stringValue
      );
    }
  );
})();

One of those cases where the Application("System Events") approach probably does look simpler and more sensible : - )

Scripter time vs run-time – the System Events approach is arguably clearer and faster to write, but a quick test suggests that in the JS context the XML reader executes a little faster (about 1/3 of the SE approach’s elapsed time). Unlikely to be significant : - )

Using Application("System Events):

(function () {
  function kmClipPath() {
    var a = Application.currentApplication();

    return (a.includeStandardAdditions = true, a)
      .pathTo("application support", {
        from: "user domain"
      }) + "/Keyboard Maestro/Keyboard Maestro Clipboards.plist"
  };

  return Application("System Events")
    .propertyListFiles[kmClipPath()]
    .propertyListItems().map(
      function (c) {
        return c.propertyListItems.Name.value();
      }
    );
})();

These days both HW & SW are so fast that we rarely need to optimize our code for speed, except perhaps in a large repition loop.

I always vote for the most readable code. :smile:
Else 6 months later I may not be able to understand my own code. :wink:

Trying out the two versions I see a very perceptible difference.

So it comes down to how often I'm using the code. If once in a blue moon then a little slower is okay — if often then a little slower adds up — and I'd rather spend time composing the faster code.

I write a lot of code that's good enough for now, some of it ends up being optimized — some doesn't.

Then again my perception threshold for noticing performance issues is ± 0.03 seconds.

-Chris

That's interesting – I was taking an average over 10000 calls. I wonder if there's an initialisation that spreads them out a bit more.

( I guess System Events is probably a bigger thing to load up than NSXMLDocument ... )