Set MM pair list with a script?



  • Hi!

    Is it possible to set the current MM pair list using a script?

    (Would also be curious to know if there are other parts of the MM extension - like the Preview text - that can be interacted with or set using Python?)

    Thank you!



  • This should be possible, but I don't know what the consequences could be. If you really want to do it, I can look through the code and figure it out. :)

    It should be possible to catch notifications posted when a pair is viewed in the editor. Likewise, it should be possible to set the text in the preview. So, in theory, some Python code could run and update the preview automagically.



  • Hi Tal!

    Being able to set the pair list with a script would be amazing.

    (I wrote a script that generates text for the Space Center to check kerning and I would love to have the pairs I'm reviewing pop up in the MM pair list so that I can quickly edit the kerning in MM at the same time.)

    I don't really have a need to do anything else at the moment, but it's great to know about the other options.

    Thank you so much for offering to look into it!



  • This is some really, really, really hacky stuff and I can't guarantee that it won't destroy the moon, but…

    The real trick is getting the MetricsMachine window. There is a clean way to get this from within the running extension via the MetricsMachineController object, but that's not accessible outside of the extension so we have to do the gnarly iteration in getMetricsMachinePreviewPane. After that it's pretty simple: set the text and tell the interface to notice the change.

    from AppKit import NSApp
    from mm4.interface.views.typingGroup import TypingGroup
    
    def getMetricsMachinePreviewPane(font):
        document = None
        for d in NSApp().orderedDocuments():
            if hasattr(d, "font") and d.font == font.naked():
                document = d
                break
        for w in NSApp().orderedWindows():
            if w.document() == document:
                for view in w.contentView().subviews():
                    if "VanillaSplitViewSubclass" in view.__class__.__name__:
                        for p in view.vanillaWrapper()._paneDescriptions:
                            if isinstance(p["view"], TypingGroup):
                                typingView = p["view"]
                                return typingView
    
    f = CurrentFont()
    previewPane = getMetricsMachinePreviewPane(f)
    textBox = previewPane.textEntry
    textBox.set("hello")
    previewPane.textEntryCallback(textBox)
    


  • Ah! I probably confused things by asking a few questions at once but would it be possible to set the pair list?

    Thank you for looking into this despite the hacky nature of the question - I really appreciate it!



  • Ah. Here's how you can do that (and probably destroy the moon in the process):

    def getMetricsMachineController():
        # Iterate through ALL OBJECTS IN PYTHON!
        import gc
        for obj in gc.get_objects():
            if hasattr(obj, "__class__"):
                # Does this one have a familiar name? Cool. Assume that we have what we are looking for.
                if obj.__class__.__name__ == "MetricsMachineController":
                    return obj
    
    
    # Get the current font.
    font = CurrentFont()
    
    # Get the MM main controller.
    metricsMachineController = getMetricsMachineController()
    
    # Get the document controller for the current font.
    documentController = metricsMachineController._openControllers[font.naked()] # private attribute!
    
    # Set the pair list. This can be any legal pair list structure.
    text = """
    #KPL:P: yikes
    A B
    """
    documentController._setPairList(text) # private method!
    


  • Hooray! This works perfectly. Thank you so much, Tal!