Skip to content

Local Hooks

David Brainard edited this page Aug 19, 2019 · 3 revisions

Some toolboxes will require machine-specific configuration in order to run correctly. For example, they may need to know the location where local input data are stored, or where output data should be written.

To help users set up local configuration, ToolboxToolbox provides a "local hook" mechanism allowing user-defined code to be executed during toolbox deployment.

Finding and Running Local Hooks

When you install ToolboxToolbox, you can use startup.m to specify a folder where ToolboxToolbox should store local hook scripts.

During deployments, ToolboxToolbox will check this folder for scripts that have the same name as the toolboxes being deployed. If found, these scripts will be executed as part of the deployment.

For a toolbox named "Foo", ToolboxToolbox will look for a local hook script with either of two names:

  • FooLocalHook.m
  • Foo.m

You can create a local hook for any toolbox, and put arbitrary code in it.

Hook Isolation

ToolboxToolbox executes each hook in an isolated environment. This is to prevent hard-to-debug errors that depend on the order of hook execution or other stateful things like variables in Matlab's base workspace or the value of pwd().

Specifically:

  • Hooks are evaluated within a local function workspace, not in the base workspace.
  • After each hook finishes executing, ToolboxToolbox changes back to the directory where it started.

Any command window output produced when a local hook is run is captured by default and placed in the message field of the corresponding toolbox record. If instead you want to have the output go to the command window, set key 'printLocalHookOutput' to true. In this case, the message field of the record is set to the empty string.

Local Hook Templates

Toolbox authors can write templates for local hooks, to make it easy for users to set up their toolboxes. THis is a good way for authors to communicate to users what exactly they need to configure locally.

When ToolboxToolbox finds a template as part of a toolbox, it will automatically copy the template to the configured local hooks folder and run it during deployments. This may be sufficient for some toolboxes. For others, the user may need customize the hook with local information and re-deploy in order for the toolbox to work.

Local hook templates should be located inside their respective toolbox repositories.

Toolbox records should use the localHookTemplate field to point to the local hook template file. This must be a relative path from the repository root to the template file.

For example, a project Foo might have a code subfolder and a configuration subfolder:

  • Foo/
    • code/
      • lots of stuff...
    • configuration/
      • localHookTemplate.m
      • other stuff...

The toolbox record for Foo should declare its local hook template like this in Matlab:

tbToolboxRecord('localHookTemplate', 'configuration/localHookTemplate.m', ...)

Or like this in JSON:

...
"localHookTemplate": "configuration/localHookTemplate.m"
...

Writing Local Hook Templates

Local hook templates should make a best effort to choose reasonable default values so that they can run without modification, and work reasonably well for most users. They should require customization only in special situations.

Here are some guidelines for writing local hook templates that can run without modification.

Reasonable Defaults

Don't write hard-coded paths in local hooks, and don't expect users to fill in hard-coded paths before they can successfully deploy. Instead, try to choose reasonable paths dynamically, based on local configurations. The following utilities should help with choosing local paths dynamically:

The same idea should apply to all configurable values, not just file paths. For example, if a toolbox requires credentials for a web service, it should start with some reasonable "guest" credentials suitable for casual users. Only power users should have to worry about special credentials.

Use Prefs

When using utilities like the ones listed above, local hooks should use tbCurrentPrefs() to obtain the current working deployment preferences. This allows the local hook to respond to details of the current deployment, instead of always using default values.

For example, a user might deploy a toolbox Foo to the usual toolboxes folder, or a snapshot of Foo to some other folder. The local hook can detect which folder by obtaining the current working prefs struct and passing it to tbLocateToolbox().

% where is Foo being deployed?
prefs = tbCurrentPrefs();
fooFolder = tbLocateToolbox('Foo', prefs);

The value of fooFolder would then be correct, whether Foo was being deployed to the usual toolbox folder, or some other folder.

Without the prefs struct, tbLocateToolbox() would only be able to return the usual, default toolbox folder.