-
Notifications
You must be signed in to change notification settings - Fork 1
/
context.go
82 lines (74 loc) · 1.94 KB
/
context.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
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
package anansi
// Context provides a piece of terminal context setup and teardown logic.
//
// See Term.RunWith and Term.RunWithout for more detail.
type Context interface {
// Enter is called to (re)establish terminal context at the start of the
// first Term.RunWith and at the end of every Term.RunWithout.
Enter(term *Term) error
// Exit is called to restore original terminal context at the end of the
// first Term.RunWith and at the start of Term.RunWithout.
Exit(term *Term) error
// Close is an optional method that is called only at the end of the first
// Term.RunWith, but NOT at the start of term.RunWithout.
// Close() error
}
// Contexts returns a Context that: calls all given context Enter()s in order,
// stopping on first failure; and calls all given context Exit()s in reverse
// order, returning the first error, but proceeding to all all remaining
// Exit() even under error.
func Contexts(cs ...Context) Context {
if len(cs) == 0 {
return nil
}
a := cs[0]
for i := 1; i < len(cs); i++ {
b := cs[i]
if b == nil || b == Context(nil) {
continue
}
if a == nil || a == Context(nil) {
a = b
continue
}
as, haveAs := a.(contexts)
bs, haveBs := b.(contexts)
if haveAs && haveBs {
a = append(as, bs...)
} else if haveAs {
a = append(as, b)
} else if haveBs {
a = append(contexts{a}, bs...)
} else {
a = contexts{a, b}
}
}
return a
}
type contexts []Context
func (tcs contexts) Enter(term *Term) error {
for i := 0; i < len(tcs); i++ {
if err := tcs[i].Enter(term); err != nil {
return err
}
}
return nil
}
func (tcs contexts) Exit(term *Term) (rerr error) {
for i := len(tcs) - 1; i >= 0; i-- {
if err := tcs[i].Exit(term); rerr == nil {
rerr = err
}
}
return rerr
}
func (tcs contexts) Close() (rerr error) {
for i := len(tcs) - 1; i >= 0; i-- {
if cl, ok := tcs[i].(interface{ Close() error }); ok {
if err := cl.Close(); rerr == nil {
rerr = err
}
}
}
return rerr
}