MACRO: Find Macros that use Selected Sub-Macro

MACRO: Find Macros that use Selected Sub-Macro

REQUIRES: OS/X 10.10 (Yosemite) or higher

###** UPDATED 2016/06/19 v2.0 **

  • The main logic script now uses JSON to return the results.
  • Custom HTML Prompt changes:
    • New styling.
    • You can now change the width and height (see comments in the macro).
    • The HTML Table is built dynamically in JavaScript. The code is reusable, so if it interests you, feel free to use it.

Find Macros that use Selected Sub-Macro.v2.0.kmmacros (44.5 KB)

Many of us have been building up libraries of macros that can be called as "sub-macros". Reusable components, accessed through an "Execute a Macro" Action.

Sometimes you want to find all the Macros that call one of your sub-macros. Here's an easy way to do it.

  1. Select a Sub-Macro.
  2. Trigger this Macro.
  3. Get a window with the names of every Macro that uses the selected sub-macro.
  4. Click one of the listed Macros, and jump right to it.
  5. Click one of the listed Groups, and jump right to it.
  6. Leave the window open until you're done with it.

You can also do this natively in the Keyboard Maestro editor, by copying the sub-macro's UUID and pasting it into the Search field. But I prefer having the results in a separate window, like this.

One advantage of searching the native KM way is that it highlights the Actions that reference the sub-macro. My method does not do this.

So, it's up to you which you prefer.

9 Likes

Outstanding, Dan. :thumbsup:
What a great contribution to all KM users.

1 Like

An KM XREF tool that I dreamed for a long time :smiley:

Message to the kind support :wink: I get systematically in variable fmumResults:

2016-06-16 09:48:05.839 osascript[19996:6813589] warning: failed to get scripting definition from /usr/bin/osascript; it may not be scriptable.
/var/folders/0d/dj43zrpj3kg85hdt91_cjwy00000gp/T/Keyboard-Maestro-Script-C3CD02A7-1CD0-4BE9-A4C7-52892202A9F0:1560:1594: execution error: Error on line 55: TypeError: undefined is not a function (evaluating 'convertPlistPartToString(macro.Actions)
.includes(_targetMacroUUID)') (0)

NB:

  • Hope I don't misused this great KM tool.
  • Cannot help in JXA, sorry :wink:
  • Perhaps a tagging this topic as "tool" can be welcome

--Alain

Uh oh. What version of OS/X are you on? Better yet, what version of KM are you on?

  • OSX 10.10.5 Yosemite
  • Last version of KM: 7.1.1
    Ultra speed support :smiley:

I aim to please. Also, couldn't sleep tonight. :slight_smile:

In my macro, find this action :

Just to be safe:

  1. Duplicate it (cmd+d).
  2. Disable one of them (right-click, "Disable")

Now replace the text in the non-disabled action with this:

(function() {
    'use strict';

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

    function readPlistBinaryFile(filePath) {
        var data = $.NSData.dataWithContentsOfFile(filePath);
        return ObjC.deepUnwrap(
            $.NSPropertyListSerialization
            .propertyListWithDataOptionsFormatError(
                data, $.NSPropertyListBinaryFormat_v1_0, 0, null));
    }

    function convertPlistPartToString(plistPart) {
        var _data = $.NSPropertyListSerialization
            .dataWithPropertyListFormatOptionsError(
                $(plistPart), $.NSPropertyListXMLFormat_v1_0, 0, null);
        var _nsstring = $.NSString.alloc.initWithDataEncoding(
            _data, $.NSUTF8StringEncoding);
        return $(_nsstring).js;
    }

    var _kme = Application("Keyboard Maestro Engine");
    var _targetMacroUUID = _kme.getvariable('fmumTargetMacroUUID');
    var _targetMacroName = "Unknown";

    var _plist = readPlistBinaryFile(getKMMacrosSourceFileName());

    var _result = [];
    _plist.MacroGroups.forEach(function(group) {
        var macros = group.Macros;

        // If this is a smart group, it won't have any macros
        if (!macros) {
            return;
        }

        var groupName = group.Name;
        var groupUUID = group.UID;

        macros.forEach(function(macro) {
            var macroName = macro.Name;
            var macroUUID = macro.UID;
            if (macroUUID === _targetMacroUUID) {
                _targetMacroName = macroName;
            } else {
                var _parts = convertPlistPartToString(macro.Actions);
                if (_parts && _parts.includes(_targetMacroUUID)) {
                    _result.push(groupName + "\t" + groupUUID +
                        "\t" + macroName + "\t" + macroUUID);
                }
            }
        })
    });
    return _targetMacroName + "\n" + _result.sort().join("\n");
})()

Let me know if this fixes the problem.

fmumResults =>

2016-06-16 10:39:50.079 osascript[20268:6953186] warning: failed to get scripting definition from /usr/bin/osascript; it may not be scriptable.
/var/folders/0d/dj43zrpj3kg85hdt91_cjwy00000gp/T/Keyboard-Maestro-Script-3413FE14-0409-4C4D-BA20-35F0EBAF900B:1870:1936: execution error: Error on line 56: TypeError: undefined is not a function (evaluating '_parts.includes(_targetMacroUUID)') (0)

Dan perhaps better to sleep and support when you awake :wink: Thanks
--Alain

I’ll go to sleep now, but try this instead. It’ll solve the problem.

Same as before, paste this into the action:

(function() {
    'use strict';

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

    function readPlistBinaryFile(filePath) {
        var data = $.NSData.dataWithContentsOfFile(filePath);
        return ObjC.deepUnwrap(
            $.NSPropertyListSerialization
            .propertyListWithDataOptionsFormatError(
                data, $.NSPropertyListBinaryFormat_v1_0, 0, null));
    }

    function convertPlistPartToString(plistPart) {
        var _data = $.NSPropertyListSerialization
            .dataWithPropertyListFormatOptionsError(
                $(plistPart), $.NSPropertyListXMLFormat_v1_0, 0, null);
        var _nsstring = $.NSString.alloc.initWithDataEncoding(
            _data, $.NSUTF8StringEncoding);
        return $(_nsstring).js;
    }

    var _kme = Application("Keyboard Maestro Engine");
    var _targetMacroUUID = _kme.getvariable('fmumTargetMacroUUID');
    var _targetMacroName = "Unknown";

    var _plist = readPlistBinaryFile(getKMMacrosSourceFileName());

    var _result = [];
    _plist.MacroGroups.forEach(function(group) {
        var macros = group.Macros;

        // If this is a smart group, it won't have any macros
        if (!macros) {
            return;
        }

        var groupName = group.Name;
        var groupUUID = group.UID;

        macros.forEach(function(macro) {
            var macroName = macro.Name;
            var macroUUID = macro.UID;
            if (macroUUID === _targetMacroUUID) {
                _targetMacroName = macroName;
            } else {
                var _parts = convertPlistPartToString(macro.Actions);
                if (_parts && _parts.indexOf(_targetMacroUUID) >= 0) {
                    _result.push(groupName + "\t" + groupUUID +
                        "\t" + macroName + "\t" + macroUUID);
                }
            }
        })
    });
    return _targetMacroName + "\n" + _result.sort().join("\n");
})()

NOTE:

The above changes have been released in updated version 1.1, which allows this macro to work on OS/X 10.10 (Yosemite).

Download link in first post.

Nevertheless, I see some improvement :wink: Not totally joking Dan :smile:

updated version 1.1

fmumResults =>

2016-06-16 12:20:58.181 osascript[20528:7047331] warning: failed to get scripting definition from /usr/bin/osascript; it may not be scriptable.
_date_set_file_fr
Palette MyGest 7B943D53-3743-42FE-B41B-A10548F78D5C 01)XXXX: 4xxx: QA v1.5 A444EB87-E86A-4558-B44B-4F5B2AF08CFC
Palette MyGest 7B943D53-3743-42FE-B41B-A10548F78D5C 02)XXXX: Synthèse v1.0 14D78F60-40C9-4608-B6A5-FF85BA138BEF

fmumTargetMacroName =>

2016-06-16 12:20:58.181 osascript[20528:7047331] warning: failed to get scripting definition from /usr/bin/osascript; it may not be scriptable.

--Alain

Can you use Keyboard Maestro->Preferences->Actions and tell me what “fmumLine” and “fmumResults” contain?

Dan,

Do you mean Keyboard Maestro->Preferences->Variables?

If your answer is “yes”:

fmumLine =>
_date_set_file_fr

For fmumResults just see my previous post (I have overwritten sparse private info).

Duh. Sorry.

OK, I know what's happening. According to this post:

So I need to strip that line out, if it exists. Can you verify that the error message in fmumResults is just one line? What I mean is, this part:

is all one one line, with no line breaks in the middle or anything, right?

If so try this:

Find Macros that use Selected Sub-Macro.v1.11.kmmacros (43.5 KB)

:clap::thumbsup:
Dan, done, you can sleep the sleep of the Just (of course even without the above macro ;-))

Thanks a lot,
–Alain

Awesome! Thanks for helping figure this one out.

Update version 2.0. See the first post.

2 Likes

Excellent update Dan! :thumbsup:

1 Like

Dan this is awesome, I downloaded this a few weeks ago but didn’t quite realize what a gem this is, you are blowing my mind lately! I love how active you guys are on the forum and absolutely love using Keyboard Maestro with stuff like this.

1 Like

Awesome! Glad I’m helping.