-
Notifications
You must be signed in to change notification settings - Fork 6
/
interrupt.go
54 lines (49 loc) · 1.68 KB
/
interrupt.go
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
package console
// AddInterrupt registers a handler to run when the console receives
// a given interrupt error from the underlying readline shell.
//
// On most systems, the following errors will be returned with keypresses:
// - Linux/MacOS/Windows : Ctrl-C will return os.Interrupt.
//
// Many will want to use this to switch menus. Note that these interrupt errors only
// work when the console is NOT currently executing a command, only when reading input.
func (m *Menu) AddInterrupt(err error, handler func(c *Console)) {
m.mutex.RLock()
m.interruptHandlers[err] = handler
m.mutex.RUnlock()
}
// DelInterrupt removes one or more interrupt handlers from the menu registered ones.
// If no error is passed as argument, all handlers are removed.
func (m *Menu) DelInterrupt(errs ...error) {
m.mutex.RLock()
if len(errs) == 0 {
m.interruptHandlers = make(map[error]func(c *Console))
} else {
for _, err := range errs {
delete(m.interruptHandlers, err)
}
}
m.mutex.RUnlock()
}
func (m *Menu) handleInterrupt(err error) {
m.console.mutex.RLock()
m.console.isExecuting = true
m.console.mutex.RUnlock()
defer func() {
m.console.mutex.RLock()
m.console.isExecuting = false
m.console.mutex.RUnlock()
}()
// TODO: this is not a very, very safe way of comparing
// errors. I'm not sure what to right now with this, but
// from my (unreliable) expectations and usage, I see and
// use things like errors.New(os.Interrupt.String()), so
// the string itself is likely to change in the future.
//
// But if people use their own third-party errors... nothing is guaranteed.
for herr, handler := range m.interruptHandlers {
if err.Error() == herr.Error() {
handler(m.console)
}
}
}