#+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.
