Skip to content

Programmatic Implicit Button Types

An implicit button type is defined or updated via the (defib) macro (ibtype:create is alias for this). It may be called just as (defun) is, but with a number of constraints. The parameter list should always be empty since no parameters will be used. A documentation string is required. The last required form is the at-p predicate which when non-‘nil’, must do three things:

  1. determine if there is a button at point that matches the type being defined;
  2. if so, call ibut:set-label to identify the label text of the button;
  3. if so, call hact to invoke the button’s action, typically using the label.

The call to ibut:label-set may contain just the button’s label argument or the label plus its start and end positions in the buffer, if you wnat the button to flash when pressed.

The hact call, run whenever a button of the type is activated, must be the last expression within the at-p form unless the action itself ends with a call to hact. This call will always return ‘t’ when the at-p form is tested for a boolean value since the implicit button type’s check has already evaluated true before this is called. The arguments to the call to hact are an action function and whatever arguments it takes. The action may be a Hyperbole action type created with defact or a regular Emacs Lisp function. However, the action should not return ‘nil’ since any ‘nil’ value returned is converted to ‘t’ to ensure the implicit button checker recognizes that the action has been executed.

Action invocations have the form: (hact actype &rest actype-arguments) where actype is a Hyperbole action type symbol or an Emacs Lisp function name or lambda; actype-arguments are the arguments fed to the action invocation when an implicit button of the type is activated.

It is imperative that all actions (non-predicate code) be invoked through the (hact) function or your ibtypes will not work properly. (Hyperbole first tests to see if any ibtype matches the current context before activating any type, so it ensures that (hact) calls are disabled during this testing). Any action types used in the definition of an implicit button type may be created before or after the definition, but obviously, must be defined before any implicit buttons of the given type are activated or an error will result.

If an implicit button type create is successful, the symbol that Hyperbole uses internally to reference the type is returned. On failure, ‘nil’ is returned so that you may test whether or not the operation succeeds. Implicit button type names and action type names may be the same without any conflict. In fact, such naming is encouraged when an implicit button type is the exclusive user of an action type.

When the Action Key is pressed, each implicit button type predicate is checked in priority order and the first one whose at-p form evaluates non-‘nil’ is activated (its action is run using the button label at point). The first time an implicit button type is defined, it becomes the highest priority type; repeated definitions of the same type update the type but do not change its priority order. {C-h h i t RET} (hui:htype-help 'ibtypes 'no-sort) displays the doc strings for all current implicit button types in descending priority order.

Call (ibtype:delete) to remove an implicit button type from a Hyperbole environment. It takes a single parameter which should be the same type symbol used in the type definition call (not the Hyperbole symbol returned by the call). This will not delete the action type used by the implicit button; that must be done separately.

By default, a request for help on an implicit button will display the button’s attributes in the same manner as is done for explicit buttons. For some implicit button types, other forms of help will be more appropriate. If an Emacs Lisp function is defined whose name is formed from the concatenation of the type name followed by ‘:help’, e.g. my-ibtype:help, it is used as the assist-action whenever the Assist Key is pressed, to respond to requests for help on buttons of that type. Any such function should take a single argument of an implicit button construct. (This is what (ibut:at-p) returns when point is within an implicit button context). Remember that the standard help for buttons with custom help functions is still available with {C-h A} for the Action Key and {C-u C-h A} for the Assist Key.

To programmatically query implicit buttons for their attributes, use the functions from the ‘hbut’ and ‘hattr’ classes. See the hib-kbd.el file for an example of a custom help function.