nhooks
nhooks copied to clipboard
#+TITLE: NHooks
/A hook facility for Common Lisp./
This package holds an enhanced implementation of hooks (extension points). It works similarly to Emacs hooks with crucial improvements:
-
If the compiler allows it (such as SBCL), type-checking is performed at compile-time and at run-time when adding handlers to a hook.
-
On failure, multiple restarts are offered, such as disabling the offending handler or simply continuing to the next function.
-
The hook handler execution order and combination can be customized.
-
Anonymous functions (lambdas) can be added to hooks as =handler= objects.
When inspecting hooks, readable names are thus exposed instead of lambda blackboxes.
Handlers are compared through their names (through the mandatory =name= slot). A hook can not contain multiple handlers with the same name.
-
A special provision is taken for "setters", handlers that are meant to set a given place to a given values.
Such =handler= objects can be compared and identified uniquely.
** Example
#+begin_src lisp (let ((hook (make-instance 'nhooks:hook-number->number :handlers (list #'add-1 #'multiply-by-2) :combination #'nhooks:combine-composed-hook))) (nhooks:run-hook hook 17)) ;; => 35 #+end_src
See the [[file:package.lisp][package]] documentation for a usage guide and more examples.
** Road-map
- [ ] Handlers should subclass generic functions and thus be funcallable.
- [ ] Setters could subclass handlers.
** History
This library was originally contributed by the maintainers of the [[https://nyxt-browser.com/][Nyxt]] web browser to [[https://github.com/ruricolist/serapeum][Serapeum]]. Then it got overhauled and backward compatibility broke, so a dedicated library was published instead. The Serapeum contrib is considered deprecated.
** Change log
*** 1.2.2
- Remove =NASDF= as a dependency.
*** 1.2.1
- Major refactoring (turn all the =defmethod=-defined functions into generics).
- =define-hook-type=: New optional =documentation= argument.
*** 1.2.0
- Hooks and handlers are now "funcallable", for instance with =(funcall HOOK ARGS)=.
- =find-handler=: New optional =include-disabled= argument.
- Fix bug when appending handler.
- Add =wait-on= helper.
*** 1.1.1
- Add package documentation.
- Fix bug on CLISP.
*** 1.1.0
- Add =on= and =once-on= helpers.