Examples — Basic

Quills

Last updated: 

The Quills API is currently very simple.  It is nevertheless possible to do some powerful things through Python in MacTerm:

Initializing MacTerm

Call Base.all_init() to initialize every C++ module in the framework.  Currently, there is no option to initialize fewer modules.

You should call this API before using Quills in your script, as not all modules can initialize just-in-time.

Beta versions of MacTerm may be somewhat “noisy” in this call (generating text to the console), but final versions write nothing by default and have an option to be verbose.

Tearing Down MacTerm

When finished with Quills (at the end of your script), call Base.all_done() to tear down the framework.  Strictly speaking this is not necessary, but it is a good idea.

IMPORTANT:  If your script actually runs the MacTerm main event loop (see Running the MacTerm Event Loop), Python will never return to the line that follows the Events.run_loop() call.  In these circumstances, the only possible way to invoke Base.all_done() is from an event termination callback that is registered beforehand.

Example:

    Base.all_init()
    
    def terminate():
        # unload all required MacTerm modules, performing necessary cleanup
        Base.all_done()
    
    Events.on_endloop_call(terminate)
    Events.run_loop()

Creating Sessions

The Session object in the Quills API represents access to resources, which is currently limited to one Unix command per terminal window.

Constructing a Session opens a new terminal window and runs its command.  (How this window behaves is currently subject to user preferences and cannot be set programmatically.)

The constructor requires an array, which contains all the command line words.  If you wish to express the command as a Python string, you can always split the string on whitespace.

Example:

    session_1 = Session(["progname", "-arg1", "-arg2", "-arg3", "val3", "-arg4", "val4"])
    session_2 = Session("progname -arg1 -arg2 -arg3 val3 -arg4 val4".split())

The returned object currently has no purpose.

If you were to place this type of statement in the MacTerm front-end script, then your Unix command would run every time you launch MacTerm.

Triggering Callbacks when Sessions Open

The Session module has the on_new_call() method for registering a callback that is told whenever any new session is created.  For example, you could do the following:

    def my_py_func():
        print "I was called by MacTerm!"
    
    Session.on_new_call(my_py_func)

Given the registration above, MacTerm calls the specified Python function every time a session is created.  If you were to run MacTerm with a console attached to standard output, you would see the print statements appear as new windows are opened.

Currently, the callback is not given arguments.

If you wish to unregister your callback, use Session.stop_new_call().

Triggering Callbacks to Handle URLs

The Session module has the on_urlopen_call() method for registering a handler for a particular schema (type) of URL.  The core MacTerm URL handlers are in fact entirely implemented in Python, and are installed using calls like this:

    Session.on_urlopen_call(pymacterm.url_open.sftp, 'sftp')

Your Python routine receives a single string argument that is a URL.  You are expected to create a new Session that properly handles the URL.

For example, if you had the text-based web browser lynx installed, you might write code like this to automatically open web pages with it:

    def run_lynx_on_url(url):
        session = Session(["/usr/local/bin/lynx", url])
    
    Session.on_urlopen_call(run_lynx_on_url, "http")
    Session.on_urlopen_call(run_lynx_on_url, "https")

Since MacTerm runs a Python interpreter, you can import standard Python libraries such as urlparse to help you implement your handler.

If you wish to unregister your callback, use Session.stop_urlopen_call().

Triggering Callbacks to Open Files

The Session module has the on_fileopen_call() method for registering a handler for a particular type of file.  The core MacTerm file handlers are in fact entirely implemented in Python, and are installed using calls like this:

    Session.on_fileopen_call(pymacterm.file_open.script, extension='bash')
    Session.on_fileopen_call(pymacterm.file_open.script, extension='ksh')
    Session.on_fileopen_call(pymacterm.file_open.script, extension='sh')
    Session.on_fileopen_call(pymacterm.file_open.script, extension='tcsh')
    Session.on_fileopen_call(pymacterm.file_open.script, extension='zsh')

Keyword arguments identify which file attribute your handler is for (indicating the meaning of the string).  Currently, the only attribute available is file extension, excluding any dot; so in the example above, "tcsh" refers to any file ending in ".tcsh"; a matching pathname would be /Users/me/Scripts/runme.tcsh.

Your Python routine receives a single string argument that is a pathname.  You are expected to create a new Session that properly handles the file.

For example, suppose you want to open all Python files with the preferred text editor of the user:

    import os
    
    def open_with_user_editor(pathname):
        editor = os.environ.get('EDITOR', '/usr/bin/vim')
        session = Session([editor, pathname])
    
    Session.on_fileopen_call(open_with_user_editor, extension='py')

Since MacTerm runs a Python interpreter, you can import standard Python libraries such as os.path to help you implement your handler.

If you wish to unregister your callback, use Session.stop_fileopen_call().

Running the MacTerm Event Loop

If your script needs to run the MacTerm graphical user interface (in order to display actual terminal windows, for example), then you must run its main event loop.

Use Events.run_loop() to start the main event loop.  This must always be the last thing that your script does, because Python will not return to execute anything that follows.

However, you may register an end-loop callback.  The default MacTerm run script uses this to invoke Base.all_done(), so that cleanup is performed as soon as the graphical user interface shuts down (typically caused by the user choosing the Quit menu command).  You can substitute your own function, which can do whatever it wants to do, although it should also call Base.all_done() at some point.

Note that there is no restriction on how complicated this function is, so you could imagine a main function that performs the “first half” of your program, launches the event loop, and then calls another function to perform the “second half” of your program after MacTerm exits.

Example:

    def terminate():
        # perform your own post-Quit actions here
        # . . .
        # unload all required MacTerm modules, performing necessary cleanup
        Base.all_done()
    
    Events.on_endloop_call(terminate)
    Events.run_loop()

Setting Environment Variables

Since the front-end script RunApplication.py is in Python, you can use the standard Python os.environ mechanism to configure environment variables.  This tends to be used only for special purposes.

For example, Apple-provided features like MallocGuardEdges and MallocScribble can be enabled when debugging, influencing the memory allocator.  The following Python statement sets MallocGuardEdges to 1:

    os.environ['MallocGuardEdges'] = '1'

These settings enter the environment of any non-log-in-shell that is spawned by MacTerm.  (A log-in shell will reset its environment to a “cleaner” state.)

Embedded settings are used no matter how MacTerm is run; for example, you could launch MacTerm from the Finder, and your custom environment would still be in effect.