5
5
"fmt"
6
6
"math/big"
7
7
mrand "math/rand"
8
- "strings"
9
8
10
9
"github.com/abs-lang/abs/object"
11
10
"github.com/abs-lang/abs/util"
@@ -64,64 +63,72 @@ func NewTerminal(user string, env *object.Environment, runner Runner) *tea.Progr
64
63
}
65
64
66
65
func getInitialModel (sigs signals , user string , env * object.Environment , r Runner ) Model {
67
- in := textinput .New ()
68
- in .Prompt = getPrompt (env )
69
- in .Placeholder = exampleStatements [mrand .Intn (len (exampleStatements ))] + " # just something you can run... (tab + enter)"
70
66
historyFile , maxLines := getHistoryConfiguration (env )
71
67
history := getHistory (historyFile , maxLines )
72
- in .Focus ()
73
- messages := []string {}
74
- messages = append (messages , fmt .Sprintf ("Hello %s, welcome to the ABS (%s) programming language!" , user , env .Version ))
75
- messages = append (messages , "Type 'quit' when you're done, 'help' if you get lost!" )
76
-
77
- // check for new version about 10% of the time,
78
- // to avoid too many hangups
79
- if r , e := rand .Int (rand .Reader , big .NewInt (100 )); e == nil && r .Int64 () < 10 {
80
- if newver , update := util .UpdateAvailable (env .Version ); update {
81
- msg := fmt .Sprintf (
82
- "\n *** Update available: %s (your version is %s) ***" ,
83
- newver ,
84
- env .Version ,
85
- )
86
- messages = append (messages , lipgloss .NewStyle ().Faint (true ).Render (msg ))
87
- }
88
- }
89
68
90
- return Model {
69
+ m := Model {
91
70
signals : sigs ,
92
71
user : user ,
93
72
runner : r ,
94
- prompt : getPrompt ,
95
73
env : env ,
96
- in : in ,
97
74
history : history ,
98
75
historyPoint : len (history ),
99
76
historyFile : historyFile ,
100
77
historyMaxLInes : maxLines ,
101
78
dirty : "" ,
102
- messages : messages ,
103
- err : nil ,
104
79
}
80
+
81
+ m .prompt = func () string {
82
+ return getPrompt (m .env )
83
+ }
84
+
85
+ // Setup the input line of our terminal
86
+ in := textinput .New ()
87
+ in .Prompt = m .prompt ()
88
+ in .Placeholder = exampleStatements [mrand .Intn (len (exampleStatements ))] + " # just something you can run... (tab + enter)"
89
+ in .Focus ()
90
+
91
+ m .in = in
92
+
93
+ return m
105
94
}
106
95
107
96
type Model struct {
108
97
signals signals
109
98
user string
110
99
runner Runner
111
100
env * object.Environment
112
- prompt func (* object. Environment ) string
101
+ prompt func () string
113
102
history []string
114
103
historyPoint int
115
104
historyFile string
116
105
historyMaxLInes int
117
106
dirty string
118
- messages []string
119
107
in textinput.Model
120
- err error
121
108
}
122
109
123
110
func (m Model ) Init () tea.Cmd {
124
- return tea .Batch (tea .SetWindowTitle ("abs-repl" ), textarea .Blink )
111
+ lines := Lines {}
112
+ lines .Add (fmt .Sprintf ("Hello %s, welcome to the ABS (%s) programming language!" , m .user , m .env .Version ))
113
+ lines .Add ("Type 'quit' when you're done, 'help' if you get lost!" )
114
+
115
+ // check for new version about 10% of the time,
116
+ // to avoid too many hangups
117
+ if r , e := rand .Int (rand .Reader , big .NewInt (100 )); e == nil && r .Int64 () < 10 {
118
+ if newver , update := util .UpdateAvailable (m .env .Version ); update {
119
+ lines .Add (lipgloss .NewStyle ().Faint (true ).Render (fmt .Sprintf (
120
+ "\n *** Update available: %s (your version is %s) ***" ,
121
+ newver ,
122
+ m .env .Version ,
123
+ )))
124
+ }
125
+ }
126
+
127
+ return tea .Batch (
128
+ tea .SetWindowTitle ("abs-repl" ),
129
+ textarea .Blink ,
130
+ tea .Sequence (lines ... ),
131
+ )
125
132
}
126
133
127
134
func (m Model ) Update (msg tea.Msg ) (tea.Model , tea.Cmd ) {
@@ -144,7 +151,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
144
151
m .in .Placeholder = ""
145
152
146
153
if m .in .Value () == "" {
147
- return m . PrintNewline ( )
154
+ return m , tea . Println ( m . prompt () )
148
155
}
149
156
150
157
m .history = append (m .history , m .in .Value ())
@@ -160,7 +167,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
160
167
}
161
168
162
169
case tea .KeyTab :
163
- return m .EngagePlaceholder ()
170
+ if m .in .Placeholder != "" {
171
+ return m .EngagePlaceholder ()
172
+ }
164
173
case tea .KeyCtrlL :
165
174
return m .Clear ()
166
175
case tea .KeyUp :
@@ -199,19 +208,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
199
208
}
200
209
201
210
func (m Model ) View () string {
202
- if len (m .messages ) == 0 {
203
- return m .in .View ()
204
- }
205
-
206
- return fmt .Sprintf (
207
- "%s\n %s" ,
208
- strings .Join (m .messages , "\n " ),
209
- m .in .View (),
210
- )
211
+ return m .in .View ()
211
212
}
212
213
213
214
func (m Model ) Clear () (Model , tea.Cmd ) {
214
- m .messages = []string {}
215
215
m .in .Placeholder = ""
216
216
217
217
return m , tea .ClearScreen
@@ -223,33 +223,34 @@ func (m Model) Quit() (Model, tea.Cmd) {
223
223
return m , tea .Quit
224
224
}
225
225
226
+ func (m Model ) currentLine () string {
227
+ return m .prompt () + m .in .Value ()
228
+ }
229
+
226
230
func (m Model ) Help () (Model , tea.Cmd ) {
227
- prompt := m .prompt (m .env )
231
+ lines := Lines {}
232
+ prompt := m .prompt ()
228
233
help := func (s string ) string { return lipgloss .NewStyle ().Faint (true ).Render (s ) }
229
234
230
- m .messages = append (
231
- m .messages ,
232
- help ("\n Try typing something along the lines of:\n " ),
233
- " " + prompt + help ("current_date = `date`\n " ),
234
- help ("A command should be triggered in your system. Then try printing the result of that command with:\n " ),
235
- " " + prompt + help ("current_date\n " ),
236
- help ("Here some other valid examples of ABS code:\n " ),
237
- )
235
+ lines .Add (m .currentLine ())
236
+ lines .Add (help ("Try typing something along the lines of:\n " ))
237
+ lines .Add (" " + prompt + help ("current_date = `date`\n " ))
238
+ lines .Add (help ("A command should be triggered in your system. Then try printing the result of that command with:\n " ))
239
+ lines .Add (" " + prompt + help ("current_date\n " ))
240
+ lines .Add (help ("Here some other valid examples of ABS code:\n " ))
238
241
239
242
for i := 0 ; i < 5 ; i ++ {
240
243
ix := mrand .Intn (len (exampleStatements ))
241
- m . messages = append ( m . messages , " " + prompt + help (exampleStatements [ix ]+ "\n " ))
244
+ lines . Add ( " " + prompt + help (exampleStatements [ix ]+ "\n " ))
242
245
}
243
246
244
- m .in .SetValue ( "" )
247
+ m .in .Reset ( )
245
248
246
- return m , nil
249
+ return m , tea . Sequence ( lines ... )
247
250
}
248
251
249
252
func (m Model ) EngagePlaceholder () (Model , tea.Cmd ) {
250
- if m .in .Placeholder != "" {
251
- m .in .SetValue (m .in .Placeholder )
252
- }
253
+ m .in .SetValue (m .in .Placeholder )
253
254
254
255
return m , nil
255
256
}
@@ -276,28 +277,21 @@ func (m Model) Eval() (Model, tea.Cmd) {
276
277
}
277
278
278
279
func (m Model ) Print (msg evalCmd ) (Model , tea.Cmd ) {
279
- m . messages = append ( m . messages , m . prompt ( m . env ) + msg . code )
280
- s := msg .result
280
+ lines := Lines {}
281
+ lines . Add ( m . prompt () + msg .code )
281
282
282
- if s != "" {
283
- m . messages = append ( m . messages , s )
283
+ if msg . result != "" {
284
+ lines . Add ( msg . result )
284
285
}
285
286
286
- m .in .Prompt = m .prompt (m .env )
287
287
m .in .Reset ()
288
288
289
- return m , nil
290
- }
291
-
292
- func (m Model ) PrintNewline () (Model , tea.Cmd ) {
293
- m .messages = append (m .messages , m .prompt (m .env ))
294
-
295
- return m , nil
289
+ return m , tea .Sequence (lines ... )
296
290
}
297
291
298
292
func (m Model ) Interrupt () (Model , tea.Cmd ) {
299
- m . messages = append ( m . messages , m . prompt ( m . env ) + m . in . Value () )
293
+ l := m . currentLine ( )
300
294
m .in .Reset ()
301
295
302
- return m , nil
296
+ return m , tea . Println ( l )
303
297
}
0 commit comments