-
Notifications
You must be signed in to change notification settings - Fork 5
/
package.lisp
108 lines (91 loc) · 3.04 KB
/
package.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
(defpackage :nhooks
(:use :common-lisp)
(:import-from :serapeum
#:*hook*
#:add-hook
#:remove-hook
#:run-hooks
#:run-hook
#:run-hook-until-failure
#:run-hook-until-success
#:with-hook-restart)
(:import-from #:alexandria
#:required-argument)
(:export
#:*hook*
#:add-hook
#:remove-hook
#:run-hooks
#:run-hook
#:run-hook-with-args-until-failure
#:run-hook-with-args-until-success
#:with-disable-handler-restart
#:default-combine-hook
#:combine-hook-until-failure
#:combine-hook-until-success
#:combine-composed-hook
#:find-handler
#:disable-hook
#:enable-hook
#:define-hook
#:find-hook
#:define-hook-type
;; Handler class:
#:handler
#:name
#:fn
#:description
#:place
#:value
;; Hook class:
#:hook
#:handler-type
#:handlers-alist
#:handlers
#:disabled-handlers
#:combination
;; Pre-generated types:
#:hook-void
#:hook-string->string
#:hook-number->number
#:hook-any
;; Short hook helpers
#:on
#:once-on
#:wait-on)
(:documentation "A hook is an instance of the `nhooks:hook' class.
You can define new hook types with the `nhooks:define-hook-type' helper.
Examples:
(nhooks:define-hook-type string->string (function (string) string))
defines the `hook-string->string' hook class.
This is equivalent to using `defclass' and overriding the `nhooks:handler-type'
slot.
You can then instantiate it:
(defvar test-hook (make-instance 'nhooks:hook-void))
And add handlers to it:
(nhooks:add-hook test-hook #'my-function)
To run the hook:
(nhooks:run-hook test-hook)
Hook handlers can be automatically derived from named functions when calling
`hooks:add-hook'. If you want to add an anonymous function, you'll have to
instantiate the handler manually:
(nhooks:add-hook test-hook
(make-instance 'nhooks:handler
:fn (lambda () (format t \"Hello!~%\"))
:name 'my-anonymous-function))
You can customize the way handlers are composed by a hook:
(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
Handlers can be enabled and disabled with `nhooks:enable-hook' and
`nhooks:disable-hook' respectively.
If the handler is meant to be a setter, the `nhooks:place' and `nhooks:value'
slots can be specified; this helps `nhooks:add-hook' to compare handlers and, in
particular, avoid duplicates in hooks.
Hooks can be defined globally and attached to arbitrary symbols or objects:
(nhooks:define-hook 'nhooks:hook-number->number 'foo
:object my-object
There are also the convenience macros `nhooks:on' and `nhooks:once-on' to attach
a form to a hook and, for once-on, to ensure it's run only once."))