Contents
Throughout Conkeror, hooks are provided for a variety of events. Basically, a hook is a set of functions to run when a given event occurs. Hooks promote neatness and modularity of source code because new features can be added to an existing system by hooking functions into the system at strategic points---that is, the existing system itself need not be modified.
1. Hook Components
A hook can be made of any number of components. Broadly, the three component-types of hooks used by Cokeror are global, simple-local, and local.
- Global hooks
- Global hooks have only one component, a hook in application context.
- Simple-local hooks
Simple-local hooks have two components: a local component for the specific object in question and a global hook which will be run for any object. For example, the window_* hooks are all simple-local. You can add a hook function to the global component, which will be run when the given event happens in any window, or you can add a hook function to the local component of a specific window so your function will only get run when the given event happens in that window.
- Local hooks
Local hooks have more components than simple-local (limited by current implementation to three). These components represent the levels of a hierarchy. For instance, the buffer_* hooks are local hooks with three components: you can put a hook function on the component local to a specific buffer, so that the function will run for the event only in that buffer; you can put a hook function on the component of a specific window, so that it will run when the event happens in any buffer in that window; or you can put a hook function on the global component, meaning it will run when the event happens in any buffer.
2. Hook Types
Most hooks in Conkeror are of the normal type: every hooked function gets run, and the return values of those functions are ignored. But some hooks exist for special purposes. There are two special types:
- RUN_HOOK_UNTIL_SUCCESS
- The hook functions are run until one returns a logically true value, at which point that value is returned as the overall value of the run.
- RUN_HOOK_UNTIL_FAILURE
The hook functions are run until one returns a logically false value, at which point that value is returned as the overall value of the run. If no hook functions returned a logically false value, then the overall value of the run will be true.
For multi-component hooks, local components are run in order hierarchical specificity, and the global component runs last. For example, In a buffer-local hook, the buffer component will run first, then the window component, and finally the global.
3. Adding and Removing Hook Functions
To add a function to the global component of any hook, use the following call form:
add_hook(String hook_name, Function func, Bool prepend, Bool avoid_duplicates)
To remove a function from the global component of any hook, use the following call form:
remove_hook(String hook_name, Function func)
To add a function to a local component of any hook, use the following call form:
add_hook.call(Object context, String hook_name, Function func, Bool prepend, Bool avoid_duplicates)
To remove a function from a local component of any hook, use the following call form:
remove_hook.call(Object context, String hook_name, Function func)
4. Defining Hooks
In the code below, hook_type can be one of the following constants:
- RUN_HOOK
- RUN_HOOK_UNTIL_SUCCESS
- RUN_HOOK_UNTIL_FAILURE
If hook_type is null or omitted, the type will be RUN_HOOK.
To define a global hook:
define_hook(String hook_name, &optional Const hook_type, &optional String docstring);
To define a window-local hook:
define_window_local_hook(String hook_name, &optional Const hook_type, &optional String docstring);
To define a buffer-local hook:
define_buffer_local_hook(String hook_name, &optional Const hook_type, &optional String docstring);
To define a current-buffer-local hook:
define_current_buffer_hook(String hook_name, String existing_buffer_local_hook);
To define a download-local hook:
define_download_local_hook(String hook_name, &optional Const hook_type, &optional String docstring);
4.1. Defining Coroutine Hooks
Coroutine hooks are a type of hook which can call coroutines as well as functions. These can be used to have asynchronous procedures like minibuffer prompts in a hook. They are defined by an alternative set of functions from normal hooks, but not all equivalents are provided. They will be added as they are deemed relevant.
To define a global coroutine hook:
define_coroutine_hook(String hook_name, &optional Const hook_type, &optional String docstring);
5. Running Hooks
To run a global hook:
some_hook.run(&rest args);
To run a hook with local components:
some_hook.run(Object context, &rest args)
For multiple-component hooks, the context will be the first argument passed to each hook function, followed by any additional arguments.
5.1. Running Coroutine Hooks
The way to run a coroutine hook depends on whether the calling context is already in a coroutine or not.
Run a global coroutine hook from within a coroutine:
yield some_hook.run(&rest args);
Run a global coroutine hook, starting a new coroutine:
co_call(some_hook.run(&rest args));
Run a multi-component coroutine hook from within a coroutine:
yield some_hook.run(Object context, &rest args);
Run a multi-component coroutine hook, starting a new coroutine:
co_call(some_hook.run(Object context, &rest args));
6. List of Hooks
6.1. Global
Global hooks are made by define_hook. They are only called in the global context.
- make_window_hook
- Called with one argument: the window being created. The window is not yet initialized.
- before_quit_hook
type: RUN_HOOK_UNTIL_FAILURE
coroutine hook
This hook can be used to prompt for confirmation of the quit command.
- quit_hook
Called with no arguments by the quit command, after it is determined that the program is definitely quitting.
Additionally, every global mode has a pair of global hooks, one MODE-enable-hook and one MODE-disable-hook.
6.2. Window-local
Window-local hooks are simple-local hooks, so they have two components: a local component for the window, and a global component.
- window_initialize_early_hook
noteworthy events: buffer_container and first buffer initialized.
- window_initialize_hook
noteworthy events: keyboard handling is initialized for the window.
- window_initialize_late_hook
noteworthy events: set_window_title
- window_before_close_hook
type: RUN_HOOK_UNTIL_FAILURE
coroutine hook
This hook can be used to prompt for confirmation of window closings. It does not run when windows are being closed because the application was quit with the quit command.
- window_close_hook
- mode_line_hook
- keypress_hook
type: RUN_HOOK_UNTIL_SUCCESS
6.3. Buffer-local
Buffer-local hooks are local hooks with three components: buffer, window, and global.
6.3.1. all buffers
- buffer_title_change_hook
- buffer_description_change_hook
- buffer_icon_change_hook
- select_buffer_hook
noteworthy events: set_window_title
- create_buffer_early_hook
- Run during buffer construction, after the buffer base class has finished setup, but before child classes are initialized.
noteworthy events: tab_bar_add_buffer
- create_buffer_hook
- create_buffer_late_hook
- Run by a zero timeout after buffer construction. Can be used to hide scrollbars.
- kill_buffer_hook
- buffer_scroll_hook
- buffer_dom_content_loaded_hook
- buffer_loaded_hook
- Called when the top-level document of a buffer is done loading, not counting any embedded content.
- buffer_kill_before_hook
type: RUN_HOOK_UNTIL_FAILURE
- buffer_mode_change_hook
- Run whenever a buffer-mode is enabled or disabled.
Additionally, every buffer mode has a set of buffer-local hooks: a MODE_enable_hook, a MODE_disable_hook. And every buffer mode-class has a MODECLASS_change_hook.
6.3.2. content-buffers
- content_buffer_finished_loading_hook
- content_buffer_started_loading_hook
- content_buffer_progress_change_hook
- content_buffer_location_change_hook
noteworthy events: set_window_title
- content_buffer_status_change_hook
- content_buffer_focus_change_hook
- content_buffer_dom_link_added_hook
- input_mode_change_hook
- fixme: doublecheck that this is in the right category. (do input-modes work for non-content-buffers?)
6.4. Current-buffer-local
A current-buffer hook is a buffer-local hook which only runs for those buffers which are current in their window. Every current-buffer hook is chained onto a corresponding buffer-local hook. In other words, if we have a buffer-local hook foo, then foo will in turn call current-buffer-foo when the buffer in question is current in its window.
6.4.1. all buffers
- current_buffer_title_change_hook
noteworthy events: set_window_title
- current_buffer_description_change_hook
- current_buffer_icon_change_hook
- current_buffer_scroll_hook
- current_buffer_dom_content_loaded_hook
- current_buffer_mode_change_hook
6.4.2. content-buffers
- current_content_buffer_finished_loading_hook
- current_content_buffer_progress_change_hook
- current_content_buffer_location_change_hook
- current_content_buffer_status_change_hook
- current_content_buffer_focus_change_hook
- current_buffer_input_mode_change_hook
- fixme: doublecheck that this is in the right category. (do input-modes work for non-content-buffers?)
6.5. Download-local
The download hooks are all simple-local hooks. They have a local component for the download and a global component.
- download_added_hook
noteworthy events: open_download_buffer_automatically
- download_removed_hook
- download_finished_hook
- download_progress_change_hook
- download_state_change_hook
- download_shell_command_change_hook