Customization Module Reference

Quills

Last updated: 

The customization module is a short-cut that allows you to write code against the Quills APIs immediately, without having to manage imports (like isolated scripts do).  You can do a number of powerful things this way, but there are limitations.  The most significant limitations are that the MacTerm startup script will call the customization module only at certain times, and it may not give you an opportunity to override every default callback that is installed.

The alternative to the customization module is a standalone script, which is harder to set up (requiring manual imports).  But, a standalone script also has virtually no limitations.

How Importing Works

When MacTerm is started, it will automatically attempt to import a Python module named customize_macterm.  Python searches its default path, which is a set of directories that depends on the Python version and therefore depends on the version of macOS.

If you run MacTerm from a shell, you should see confirmation that your module was found and imported, e.g. with a message like: MacTerm: Imported 'customize_macterm' module from ....

On macOS 10.14 and earlier using MacTerm 4.x, one of the standard search-path directories is /Library/Python/2.6/site-packages/customize_macterm.py.

On macOS 10.15 and later using MacTerm 5.x, Python 3.x is now used.  Since modern macOS no longer allows applications to link to the system Python, the Python installation path depends on how MacTerm is built.  For now, this will be some local distribution (e.g. /opt/homebrew/lib/python3.9/site-packages) but eventually some predefined search paths will be devised.

It is easier to install your customization module in a path that Python already searches than it is to redefine the search path, especially since the default path is implicitly used when MacTerm is opened from the Finder.  Of course, you can install your module anywhere you want, if you set the search path properly first.  (For more on how imports work, run pydoc import in a shell.)

The remainder of this page assumes you have installed a module as above.  Any callback function below that you wish to use should be implemented in your installed customize_macterm.py file.  All callbacks are optional.

Environment of the Customization Module

Your customize_macterm.py module may assume that quills is properly imported, including any compiled-library dependencies.  Anything else that you need should be explicitly imported however.

If the MACTERM_SKIP_CUSTOM_LIBS environment variable is set when MacTerm runs, then customize_macterm.py will be ignored even if that module exists.

Callbacks Allowed in the Customization Module

The following callbacks are allowed in customize_macterm.py.  All of them are optional.  (This API is small to start with, but more capabilities will be added in the future.  Look at the RunApplication.py file in the application bundle if you are curious about how the callbacks are used.)

IMPORTANT:  If you do implement a callback below, you must support it exactly; otherwise MacTerm may fail to start up due to Python errors.  (If you suspect this problem, run MacTerm from a shell or use the Console application to see details on any errors that may have been generated.)

app_will_finish()

Since running the main event loop prevents Python from ever returning to the startup script, anything that should happen "after" must be in a callback that is automatically executed.

One way to think of it is as if the program has two "halves"; the first half is up to the end of the event loop; the second half is everything afterward, and the second half must be in this function.

The Base.all_done() function is automatically called after your function returns.

Example in Python 2.x

    def app_will_finish():
        print "this is the 2nd half of my script"

Example in Python 3.x

    def app_will_finish():
        print("this is the 2nd half of my script")

initial_workspace() -> string

Return the UTF-8-encoded name to pass as the initial_workspace keyword parameter for Base.all_init().  Any Prefs.WORKSPACE collection name will override the Default and cause a different set of windows to be spawned.  If not defined or not found, the Default is used anyway.

If you just want to set this to a static value, you're advised to use the Preferences window, and just edit the Default to do what you want.  The only benefit to setting it here is when you want to do something dynamic; for instance, you could check to see if the computer's host name indicates a VPN connection, and spawn different startup sessions in that case.

Since the purpose of this callback is to define a parameter to the Base.all_init() API, you cannot expect Quills to be initialized when your callback is invoked.

Example in Python 2.x

    def initial_workspace():
        ws = ""
        from socket import gethostname
        host = str(gethostname())
        print "MacTerm: Current machine hostname is '%s'." % host
        if host.endswith("mycompany.com"):
            ws = "Company Servers" # or whatever you used
        return ws

Example in Python 3.x

    def initial_workspace():
        ws = ""
        from socket import gethostname
        host = str(gethostname())
        print(f"MacTerm: Current machine hostname is '{host}'.")
        if host.endswith("mycompany.com"):
            ws = "Company Servers" # or whatever you used
        return ws