-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtea.go
89 lines (77 loc) · 1.48 KB
/
tea.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
83
84
85
86
87
88
89
package tea
import (
"context"
"errors"
"fmt"
"reflect"
)
type Msg interface{}
type Model interface{}
type Cmd []func() Msg
func Tag(cmd Cmd, tag func(Msg) Msg) Cmd {
for i, fn := range cmd {
if fn == nil {
continue
}
cmd[i] = func() Msg {
return tag(fn())
}
}
return cmd
}
type Init func() (Model, Cmd)
type Update func(Msg, Model) (Model, Cmd)
type View func(Model) string
type Program struct {
init Init
update Update
view View
context context.Context
cancel func()
}
func NewProgram(init Init, update Update, view View) (*Program, error) {
if init == nil || update == nil || view == nil {
return nil, errors.New("init or update or view cannot be nill")
}
ctx, cancel := context.WithCancel(context.Background())
program := &Program{
init: init,
update: update,
view: view,
context: ctx,
cancel: cancel,
}
return program, nil
}
func execCmd(ch chan Msg, cmd Cmd) {
for _, fn := range cmd {
if fn != nil {
ch <- fn()
}
}
}
func (program *Program) Start() chan Msg {
ch := make(chan Msg)
go func() {
model, cmd := program.init()
fmt.Println(program.view(model))
go execCmd(ch, cmd)
for {
select {
case msg := <-ch:
newModel, cmd := program.update(msg, model)
if !reflect.DeepEqual(newModel, model) {
model = newModel
fmt.Println(program.view(model))
}
go execCmd(ch, cmd)
case <-program.context.Done():
return
}
}
}()
return ch
}
func (program *Program) Stop() {
program.cancel()
}