Export Names of all Macros in the Selected Group to CSV or Excel

Is it possible to export all macro names in a group to a CSV file. I have many macros I am trying to sort and keep track of and move around. Is there anyway export just their names in a group so I can sort theses. Ideally it would be great if the key commands also were in a column but not mandatory.

If this is not possible maybe I could parse the /Users/~/Library/Application Support/Keyboard Maestro/Keyboard Maestro Macros.plist myself after making a copy of it. It would likely be quicker than copy and paste back and forth.

You may find that you can use, or get some ideas from:

( You can get a JSON version of the selected macro folder(s) or macro(s) with it )

( then if you paste the resulting JSON array string into Script Editor, and assign its value to a variable name like lstJSON, you could copy a simple list of names by executing something like:

var a = Application.currentApplication(),
  sa = (a.includeStandardAdditions = true, a);

var strClip = lstJSON.map(
  function (x) {
    return x.Name;
  }
).sort().join('\n');

sa.setTheClipboardTo(strClip);

strClip

This draft copies names and any hotkey trigger key codes.

(As a tab delimited list which you should be able to paste into Excel)

(Translating the key codes to human – intelligible key combination names would be another project)

Copy list of selected Macro names with any trigger keycodes.kmmacros (21.7 KB)

Source:

// COPY NAMES AND KEYS OF SELECTED KEYBOARD MAESTROS AS TEXT LISTING

// Rob Trew Twitter: @ComplexPoint  MIT license 2015
// Ver 0.5
(function () {
  // () --> JXA standard library 
  var a = Application.currentApplication(),
    sa = (a.includeStandardAdditions = true && a),

    // KM selection --> [UID]
    kmSelnUIDs = function () {
      var kme = Application("Keyboard Maestro");

      return kme.selectedmacros();
    },

    // () --> default path to Keyboard Maestro Macros.plist
    kmPlistPath = function () {
      return sa.pathTo(
        'application support', {
          from: 'user domain'
        }
      ) + "/Keyboard Maestro/Keyboard Maestro Macros.plist";
    },

    // ($NSDictionary --> ) strPlistPath --> kmMacroPlistParse;
    nsDictPlistParse = function (strPlistPath) {
      return ObjC.deepUnwrap(
        $.NSDictionary.dictionaryWithContentsOfFile(strPlistPath)
      );
    },

    // macro xml strings for set of UUIDs
    // [UUID] --> kmMacroPlistParse --> [macroXML]
    kmMacrosByUID = function (lstUID, oParse) {

      lstUID = (lstUID instanceof Array) ? lstUID : (lstUID ? [lstUID] : []);

      var lstGroups = oParse.MacroGroups,
        lng = lstGroups.length,
        lstFound = [],
        oGroup, lstMacros, lngMacros, oMacro, iIndex,
        blnGroup, i, j;

      for (i = 0; i < lng; i++) {
        oGroup = lstGroups[i];
        lstMacros = oGroup.Macros;

        if (lstMacros instanceof Array) {
          lngMacros = lstMacros.length;

          iIndex = lstUID.indexOf(oGroup.UID);
          if (iIndex !== -1) { // Group UID
            for (j = 0; j < lngMacros; j++) {
              lstFound.push(lstMacros[j]);
            }
            if (lstUID.length > 1) {
              lstUID.splice(iIndex, 1)
            } else break;
          } else { // Macro UID(s)
            for (j = 0; j < lngMacros; j++) {
              oMacro = lstMacros[j];
              iIndex = lstUID.indexOf(oMacro.UID);
              if (iIndex !== -1) {
                lstFound.push(oMacro);
                if (lstUID.length > 1) {
                  lstUID.splice(iIndex, 1);
                } else break;
              }

            }
          }
        }
      }
      return lstFound;
    },

    lstMacros = kmMacrosByUID(
      kmSelnUIDs(),
      nsDictPlistParse(
        kmPlistPath()
      )
    );


    // Tab delimited lines: Name of macro, followed by any trigger key codes
    // [{}] --> s
    return lstMacros.map(
      function (x) {
        return x.Name + '\t' + x.Triggers.filter( // trigger(s) with keycode ?
          function (dct) {
            return dct.KeyCode;
          }
        ).map(function (dctTrigger) {
          return dctTrigger.KeyCode;  // The keycode itself
        }).join('\t');
      }
    ).sort().join('\n');

})();

That is awesome, thanks for posting this ComplexPoint, Rob Trew has so many AppleScripts that I use with OmniFocus.

1 Like

Looking for a way to copy macros names and hotkeys to text or a create a list, but this script doesn’t seem to be working for me. Any alternative approaches to produce such a list? Thanks

I notice that a change in JXA has introduced an error in one line of the orginal draft. Might be worth trying this amended version, which seems to be working here:

// COPY NAMES AND KEYS OF SELECTED KEYBOARD MAESTROS AS TEXT LISTING

// Rob Trew Twitter: @ComplexPoint  MIT license 2015, 2017
// Ver 0.6
(function () {
  // () --> JXA standard library 
  var a = Application.currentApplication(),
    sa = (a.includeStandardAdditions = true, a),

    // KM selection --> [UID]
kmSelnUIDs = function () {
  var kme = Application("Keyboard Maestro");

  return kme.selectedmacros();
},

// () --> default path to Keyboard Maestro Macros.plist
kmPlistPath = function () {
  return sa.pathTo(
    'application support', {
      from: 'user domain'
    }
  ) + "/Keyboard Maestro/Keyboard Maestro Macros.plist";
},

// ($NSDictionary --> ) strPlistPath --> kmMacroPlistParse;
nsDictPlistParse = function (strPlistPath) {
  return ObjC.deepUnwrap(
    $.NSDictionary.dictionaryWithContentsOfFile(strPlistPath)
  );
},

// macro xml strings for set of UUIDs
// [UUID] --> kmMacroPlistParse --> [macroXML]
kmMacrosByUID = function (lstUID, oParse) {

  lstUID = (lstUID instanceof Array) ? lstUID : (lstUID ? [lstUID] : []);

  var lstGroups = oParse.MacroGroups,
    lng = lstGroups.length,
    lstFound = [],
    oGroup, lstMacros, lngMacros, oMacro, iIndex,
    blnGroup, i, j;

  for (i = 0; i < lng; i++) {
    oGroup = lstGroups[i];
    lstMacros = oGroup.Macros;

    if (lstMacros instanceof Array) {
      lngMacros = lstMacros.length;

      iIndex = lstUID.indexOf(oGroup.UID);
      if (iIndex !== -1) { // Group UID
        for (j = 0; j < lngMacros; j++) {
          lstFound.push(lstMacros[j]);
        }
        if (lstUID.length > 1) {
          lstUID.splice(iIndex, 1)
        } else break;
      } else { // Macro UID(s)
        for (j = 0; j < lngMacros; j++) {
          oMacro = lstMacros[j];
          iIndex = lstUID.indexOf(oMacro.UID);
          if (iIndex !== -1) {
            lstFound.push(oMacro);
            if (lstUID.length > 1) {
              lstUID.splice(iIndex, 1);
            } else break;
          }

        }
      }
    }
  }
  return lstFound;
},

lstMacros = kmMacrosByUID(
  kmSelnUIDs(),
  nsDictPlistParse(
    kmPlistPath()
  )
);


// Tab delimited lines: Name of macro, followed by any trigger key codes
// [{}] --> s
return lstMacros.map(
  function (x) {
    return x.Name + '\t' + x.Triggers.filter( // trigger(s) with keycode ?
      function (dct) {
        return dct.KeyCode;
      }
    ).map(function (dctTrigger) {
      return dctTrigger.KeyCode;  // The keycode itself
    }).join('\t');
  }
).sort().join('\n');
})();
1 Like

Got it - thanks so much!

Trying this macro/script with KME 8.2.4 without success. If I understand right, I should select the macros I'd like to export as a list and trigger this macro. I DID use the updated script. Instead of a list I get this:

image

What am I doing wrong? I find I can copy/paste from the "Macro" column selection to Google Sheets, but it is missing the triggers (which I'd like to have).

Hey Ray,

It's impossible to say, since you didn't post your macro...

In any case try this:

Export Name and Trigger Key-Code of Seleted Groups OR Macros.kmmacros (4.7 KB)

Although I suspect the trigger format isn't what you expect.

-Chris

Thank you, that worked. Although, since the trigger shortcuts are cryptic, I think copy/paste works a little better.

Hey Ray,

You can do something like this to produce better copy:

Display Names and Triggers of Selected Keyboard Maestro Macros in BBEdit v1.00.kmmacros (6.3 KB)

It requires tweaking to better present non-hotkey triggers and multiple triggers, but the result can be turned into a fairly neat table.

-Chris

1 Like