@@ -46,6 +46,23 @@ var ErrInterrupted = errors.New("program was interrupted")
46
46
// function and, henceforth, the UI.
47
47
type Msg interface {}
48
48
49
+ // Model contains the program's state as well as its core functions.
50
+ type Model [T any ] interface {
51
+ // Init is the first function that will be called. It returns an optional
52
+ // initial command. To not perform an initial command return nil.
53
+ Init () (T , Cmd )
54
+
55
+ // Update is called when a message is received. Use it to inspect messages
56
+ // and, in response, update the model and/or send a command.
57
+ Update (Msg ) (T , Cmd )
58
+
59
+ // View renders the program's UI, which is just a [fmt.Stringer]. The view
60
+ // is rendered after every Update.
61
+ // The main model can return a [Frame] to set the cursor position and
62
+ // style.
63
+ View () fmt.Stringer
64
+ }
65
+
49
66
// Cmd is an IO operation that returns a message when it's complete. If it's
50
67
// nil it's considered a no-op. Use it for things like HTTP requests, timers,
51
68
// saving and loading from disk, and so on.
@@ -142,7 +159,7 @@ type Program[T any] struct {
142
159
// To have more control over the cursor position and style, you can use
143
160
// [Frame.Cursor] and [NewCursor] to position the cursor and define its
144
161
// style.
145
- View func (T ) Frame
162
+ View func (T ) fmt. Stringer
146
163
147
164
// Model contains the last state of the program. If the program hasn't
148
165
// started yet, it will be nil. After the program finish executing, it will
@@ -275,6 +292,15 @@ func Interrupt() Msg {
275
292
return InterruptMsg {}
276
293
}
277
294
295
+ // NewProgram creates a new Program.
296
+ func NewProgram [T any ](model Model [T ]) * Program [T ] {
297
+ p := new (Program [T ])
298
+ p .Init = model .Init
299
+ p .Update = func (t T , msg Msg ) (T , Cmd ) { return any (t ).(Model [T ]).Update (msg ) }
300
+ p .View = func (t T ) fmt.Stringer { return any (t ).(Model [T ]).View () }
301
+ return p
302
+ }
303
+
278
304
func (p * Program [T ]) init () {
279
305
if atomic .LoadInt32 (& p .initialized ) == 1 {
280
306
return
0 commit comments