@@ -14,16 +14,10 @@ import { Terminal } from '@xterm/headless';
14
14
import { strictEqual } from 'assert' ;
15
15
import { timeout } from 'vs/base/common/async' ;
16
16
17
- class TestPromptInputModel extends PromptInputModel {
18
- forceSync ( ) {
19
- this . _syncNow ( ) ;
20
- }
21
- }
22
-
23
17
suite ( 'PromptInputModel' , ( ) => {
24
18
const store = ensureNoDisposablesAreLeakedInTestSuite ( ) ;
25
19
26
- let promptInputModel : TestPromptInputModel ;
20
+ let promptInputModel : PromptInputModel ;
27
21
let xterm : Terminal ;
28
22
let onCommandStart : Emitter < ITerminalCommand > ;
29
23
let onCommandExecuted : Emitter < ITerminalCommand > ;
@@ -40,13 +34,13 @@ suite('PromptInputModel', () => {
40
34
onCommandExecuted . fire ( null ! ) ;
41
35
}
42
36
43
- function assertPromptInput ( valueWithCursor : string ) {
44
- if ( ! valueWithCursor . includes ( '|' ) ) {
37
+ async function assertPromptInput ( valueWithCursor : string ) {
38
+ await timeout ( 0 ) ;
39
+
40
+ if ( promptInputModel . cursorIndex !== - 1 && ! valueWithCursor . includes ( '|' ) ) {
45
41
throw new Error ( 'assertPromptInput must contain | character' ) ;
46
42
}
47
43
48
- promptInputModel . forceSync ( ) ;
49
-
50
44
const actualValueWithCursor = promptInputModel . getCombinedString ( ) ;
51
45
strictEqual (
52
46
actualValueWithCursor ,
@@ -64,123 +58,123 @@ suite('PromptInputModel', () => {
64
58
xterm = store . add ( new Terminal ( { allowProposedApi : true } ) ) ;
65
59
onCommandStart = store . add ( new Emitter ( ) ) ;
66
60
onCommandExecuted = store . add ( new Emitter ( ) ) ;
67
- promptInputModel = store . add ( new TestPromptInputModel ( xterm , onCommandStart . event , onCommandExecuted . event , new NullLogService ) ) ;
61
+ promptInputModel = store . add ( new PromptInputModel ( xterm , onCommandStart . event , onCommandExecuted . event , new NullLogService ) ) ;
68
62
} ) ;
69
63
70
64
test ( 'basic input and execute' , async ( ) => {
71
65
await writePromise ( '$ ' ) ;
72
66
fireCommandStart ( ) ;
73
- assertPromptInput ( '|' ) ;
67
+ await assertPromptInput ( '|' ) ;
74
68
75
69
await writePromise ( 'foo bar' ) ;
76
- assertPromptInput ( 'foo bar|' ) ;
70
+ await assertPromptInput ( 'foo bar|' ) ;
77
71
78
72
await writePromise ( '\r\n' ) ;
79
73
fireCommandExecuted ( ) ;
80
- assertPromptInput ( 'foo bar| ' ) ;
74
+ await assertPromptInput ( 'foo bar' ) ;
81
75
82
76
await writePromise ( '(command output)\r\n$ ' ) ;
83
77
fireCommandStart ( ) ;
84
- assertPromptInput ( '|' ) ;
78
+ await assertPromptInput ( '|' ) ;
85
79
} ) ;
86
80
87
81
test ( 'cursor navigation' , async ( ) => {
88
82
await writePromise ( '$ ' ) ;
89
83
fireCommandStart ( ) ;
90
- assertPromptInput ( '|' ) ;
84
+ await assertPromptInput ( '|' ) ;
91
85
92
86
await writePromise ( 'foo bar' ) ;
93
- assertPromptInput ( 'foo bar|' ) ;
87
+ await assertPromptInput ( 'foo bar|' ) ;
94
88
95
89
await writePromise ( '\x1b[3D' ) ;
96
- assertPromptInput ( 'foo |bar' ) ;
90
+ await assertPromptInput ( 'foo |bar' ) ;
97
91
98
92
await writePromise ( '\x1b[4D' ) ;
99
- assertPromptInput ( '|foo bar' ) ;
93
+ await assertPromptInput ( '|foo bar' ) ;
100
94
101
95
await writePromise ( '\x1b[3C' ) ;
102
- assertPromptInput ( 'foo| bar' ) ;
96
+ await assertPromptInput ( 'foo| bar' ) ;
103
97
104
98
await writePromise ( '\x1b[4C' ) ;
105
- assertPromptInput ( 'foo bar|' ) ;
99
+ await assertPromptInput ( 'foo bar|' ) ;
106
100
107
101
await writePromise ( '\x1b[D' ) ;
108
- assertPromptInput ( 'foo ba|r' ) ;
102
+ await assertPromptInput ( 'foo ba|r' ) ;
109
103
110
104
await writePromise ( '\x1b[C' ) ;
111
- assertPromptInput ( 'foo bar|' ) ;
105
+ await assertPromptInput ( 'foo bar|' ) ;
112
106
} ) ;
113
107
114
108
test ( 'ghost text' , async ( ) => {
115
109
await writePromise ( '$ ' ) ;
116
110
fireCommandStart ( ) ;
117
- assertPromptInput ( '|' ) ;
111
+ await assertPromptInput ( '|' ) ;
118
112
119
113
await writePromise ( 'foo\x1b[2m bar\x1b[0m\x1b[4D' ) ;
120
- assertPromptInput ( 'foo|[ bar]' ) ;
114
+ await assertPromptInput ( 'foo|[ bar]' ) ;
121
115
122
116
await writePromise ( '\x1b[2D' ) ;
123
- assertPromptInput ( 'f|oo[ bar]' ) ;
117
+ await assertPromptInput ( 'f|oo[ bar]' ) ;
124
118
} ) ;
125
119
126
120
test ( 'wide input (Korean)' , async ( ) => {
127
121
await writePromise ( '$ ' ) ;
128
122
fireCommandStart ( ) ;
129
- assertPromptInput ( '|' ) ;
123
+ await assertPromptInput ( '|' ) ;
130
124
131
125
await writePromise ( '안영' ) ;
132
- assertPromptInput ( '안영|' ) ;
126
+ await assertPromptInput ( '안영|' ) ;
133
127
134
128
await writePromise ( '\r\n컴퓨터' ) ;
135
- assertPromptInput ( '안영\n컴퓨터|' ) ;
129
+ await assertPromptInput ( '안영\n컴퓨터|' ) ;
136
130
137
131
await writePromise ( '\r\n사람' ) ;
138
- assertPromptInput ( '안영\n컴퓨터\n사람|' ) ;
132
+ await assertPromptInput ( '안영\n컴퓨터\n사람|' ) ;
139
133
140
134
await writePromise ( '\x1b[G' ) ;
141
- assertPromptInput ( '안영\n컴퓨터\n|사람' ) ;
135
+ await assertPromptInput ( '안영\n컴퓨터\n|사람' ) ;
142
136
143
137
await writePromise ( '\x1b[A' ) ;
144
- assertPromptInput ( '안영\n|컴퓨터\n사람' ) ;
138
+ await assertPromptInput ( '안영\n|컴퓨터\n사람' ) ;
145
139
146
140
await writePromise ( '\x1b[4C' ) ;
147
- assertPromptInput ( '안영\n컴퓨|터\n사람' ) ;
141
+ await assertPromptInput ( '안영\n컴퓨|터\n사람' ) ;
148
142
149
143
await writePromise ( '\x1b[1;4H' ) ;
150
- assertPromptInput ( '안|영\n컴퓨터\n사람' ) ;
144
+ await assertPromptInput ( '안|영\n컴퓨터\n사람' ) ;
151
145
152
146
await writePromise ( '\x1b[D' ) ;
153
- assertPromptInput ( '|안영\n컴퓨터\n사람' ) ;
147
+ await assertPromptInput ( '|안영\n컴퓨터\n사람' ) ;
154
148
} ) ;
155
149
156
150
test ( 'emoji input' , async ( ) => {
157
151
await writePromise ( '$ ' ) ;
158
152
fireCommandStart ( ) ;
159
- assertPromptInput ( '|' ) ;
153
+ await assertPromptInput ( '|' ) ;
160
154
161
155
await writePromise ( '✌️👍' ) ;
162
- assertPromptInput ( '✌️👍|' ) ;
156
+ await assertPromptInput ( '✌️👍|' ) ;
163
157
164
158
await writePromise ( '\r\n😎😕😅' ) ;
165
- assertPromptInput ( '✌️👍\n😎😕😅|' ) ;
159
+ await assertPromptInput ( '✌️👍\n😎😕😅|' ) ;
166
160
167
161
await writePromise ( '\r\n🤔🤷😩' ) ;
168
- assertPromptInput ( '✌️👍\n😎😕😅\n🤔🤷😩|' ) ;
162
+ await assertPromptInput ( '✌️👍\n😎😕😅\n🤔🤷😩|' ) ;
169
163
170
164
await writePromise ( '\x1b[G' ) ;
171
- assertPromptInput ( '✌️👍\n😎😕😅\n|🤔🤷😩' ) ;
165
+ await assertPromptInput ( '✌️👍\n😎😕😅\n|🤔🤷😩' ) ;
172
166
173
167
await writePromise ( '\x1b[A' ) ;
174
- assertPromptInput ( '✌️👍\n|😎😕😅\n🤔🤷😩' ) ;
168
+ await assertPromptInput ( '✌️👍\n|😎😕😅\n🤔🤷😩' ) ;
175
169
176
170
await writePromise ( '\x1b[2C' ) ;
177
- assertPromptInput ( '✌️👍\n😎😕|😅\n🤔🤷😩' ) ;
171
+ await assertPromptInput ( '✌️👍\n😎😕|😅\n🤔🤷😩' ) ;
178
172
179
173
await writePromise ( '\x1b[1;4H' ) ;
180
- assertPromptInput ( '✌️|👍\n😎😕😅\n🤔🤷😩' ) ;
174
+ await assertPromptInput ( '✌️|👍\n😎😕😅\n🤔🤷😩' ) ;
181
175
182
176
await writePromise ( '\x1b[D' ) ;
183
- assertPromptInput ( '|✌️👍\n😎😕😅\n🤔🤷😩' ) ;
177
+ await assertPromptInput ( '|✌️👍\n😎😕😅\n🤔🤷😩' ) ;
184
178
} ) ;
185
179
186
180
// To "record a session" for these tests:
@@ -206,7 +200,7 @@ suite('PromptInputModel', () => {
206
200
'[34m\r\n[38;2;17;17;17m[44m03:13:47 [34m[41m [38;2;17;17;17mvscode [31m[43m [38;2;17;17;17m tyriar/prompt_input_model [33m[46m [38;2;17;17;17m$⇡ [36m[49m [mvia [32m[1m v18.18.2 \r\n❯[m ' ,
207
201
] ) ;
208
202
fireCommandStart ( ) ;
209
- assertPromptInput ( '|' ) ;
203
+ await assertPromptInput ( '|' ) ;
210
204
211
205
await replayEvents ( [
212
206
'[?25l[93mf[97m[2m[3makecommand[3;4H[?25h' ,
@@ -216,7 +210,7 @@ suite('PromptInputModel', () => {
216
210
'[?25l[93m[3;3Hfoo[?25h' ,
217
211
'[m' ,
218
212
] ) ;
219
- assertPromptInput ( 'foo|' ) ;
213
+ await assertPromptInput ( 'foo|' ) ;
220
214
} ) ;
221
215
test ( 'input with accepted and run ghost text' , async ( ) => {
222
216
await replayEvents ( [
@@ -229,62 +223,62 @@ suite('PromptInputModel', () => {
229
223
] ) ;
230
224
promptInputModel . setContinuationPrompt ( '∙ ' ) ;
231
225
fireCommandStart ( ) ;
232
- assertPromptInput ( '|' ) ;
226
+ await assertPromptInput ( '|' ) ;
233
227
234
228
await replayEvents ( [
235
229
'[?25l[93me[97m[2m[3mcho "hello world"[3;4H[?25h' ,
236
230
'[m' ,
237
231
] ) ;
238
- assertPromptInput ( 'e|[cho "hello world"]' ) ;
232
+ await assertPromptInput ( 'e|[cho "hello world"]' ) ;
239
233
240
234
await replayEvents ( [
241
235
'[?25l[93mec[97m[2m[3mho "hello world"[3;5H[?25h' ,
242
236
'[m' ,
243
237
] ) ;
244
- assertPromptInput ( 'ec|[ho "hello world"]' ) ;
238
+ await assertPromptInput ( 'ec|[ho "hello world"]' ) ;
245
239
246
240
await replayEvents ( [
247
241
'[?25l[93m[3;3Hech[97m[2m[3mo "hello world"[3;6H[?25h' ,
248
242
'[m' ,
249
243
] ) ;
250
- assertPromptInput ( 'ech|[o "hello world"]' ) ;
244
+ await assertPromptInput ( 'ech|[o "hello world"]' ) ;
251
245
252
246
await replayEvents ( [
253
247
'[?25l[93m[3;3Hecho[97m[2m[3m "hello world"[3;7H[?25h' ,
254
248
'[m' ,
255
249
] ) ;
256
- assertPromptInput ( 'echo|[ "hello world"]' ) ;
250
+ await assertPromptInput ( 'echo|[ "hello world"]' ) ;
257
251
258
252
await replayEvents ( [
259
253
'[?25l[93m[3;3Hecho [97m[2m[3m"hello world"[3;8H[?25h' ,
260
254
'[m' ,
261
255
] ) ;
262
- assertPromptInput ( 'echo |["hello world"]' ) ;
256
+ await assertPromptInput ( 'echo |["hello world"]' ) ;
263
257
264
258
await replayEvents ( [
265
259
'[?25l[93m[3;3Hecho [36m"hello world"[?25h' ,
266
260
'[m' ,
267
261
] ) ;
268
- assertPromptInput ( 'echo "hello world"|' ) ;
262
+ await assertPromptInput ( 'echo "hello world"|' ) ;
269
263
270
264
await replayEvents ( [
271
265
']633;E;echo "hello world";ff464d39-bc80-4bae-9ead-b1cafc4adf6f]633;C' ,
272
266
] ) ;
273
267
fireCommandExecuted ( ) ;
274
- assertPromptInput ( 'echo "hello world"| ' ) ;
268
+ await assertPromptInput ( 'echo "hello world"' ) ;
275
269
276
270
await replayEvents ( [
277
271
'\r\n' ,
278
272
'hello world\r\n' ,
279
273
] ) ;
280
- assertPromptInput ( 'echo "hello world"| ' ) ;
274
+ await assertPromptInput ( 'echo "hello world"' ) ;
281
275
282
276
await replayEvents ( [
283
277
']633;D;0]633;A]633;P;Cwd=C:\x5cGithub\x5cmicrosoft\x5cvscode]633;B' ,
284
278
'[34m\r\n[38;2;17;17;17m[44m03:41:42 [34m[41m [38;2;17;17;17mvscode [31m[43m [38;2;17;17;17m tyriar/prompt_input_model [33m[46m [38;2;17;17;17m$ [36m[49m [mvia [32m[1m v18.18.2 \r\n❯[m ' ,
285
279
] ) ;
286
280
fireCommandStart ( ) ;
287
- assertPromptInput ( '|' ) ;
281
+ await assertPromptInput ( '|' ) ;
288
282
} ) ;
289
283
290
284
test ( 'input, go to start (ctrl+home), delete word in front (ctrl+delete)' , async ( ) => {
@@ -297,7 +291,7 @@ suite('PromptInputModel', () => {
297
291
'[34m\r\n[38;2;17;17;17m[44m16:07:06 [34m[41m [38;2;17;17;17mvscode [31m[43m [38;2;17;17;17m tyriar/210662 [33m[46m [38;2;17;17;17m$! [36m[49m [mvia [32m[1m v18.18.2 \r\n❯[m ' ,
298
292
] ) ;
299
293
fireCommandStart ( ) ;
300
- assertPromptInput ( '|' ) ;
294
+ await assertPromptInput ( '|' ) ;
301
295
302
296
await replayEvents ( [
303
297
'[?25l[93mG[97m[2m[3mit push[3;4H[?25h' ,
@@ -306,7 +300,7 @@ suite('PromptInputModel', () => {
306
300
'[m' ,
307
301
'[?25l[93m[3;3HGet[97m[2m[3m-ChildItem -Path a[3;6H[?25h' ,
308
302
] ) ;
309
- assertPromptInput ( 'Get|[-ChildItem -Path a]' ) ;
303
+ await assertPromptInput ( 'Get|[-ChildItem -Path a]' ) ;
310
304
311
305
await replayEvents ( [
312
306
'[m' ,
0 commit comments