nhooks icon indicating copy to clipboard operation
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.