@@ -19,10 +19,18 @@ const enum PromptInputState {
19
19
Execute ,
20
20
}
21
21
22
+ /**
23
+ * A model of the prompt input state using shell integration and analyzing the terminal buffer. This
24
+ * may not be 100% accurate but provides a best guess.
25
+ */
22
26
export interface IPromptInputModel {
23
27
readonly onDidStartInput : Event < IPromptInputModelState > ;
24
28
readonly onDidChangeInput : Event < IPromptInputModelState > ;
25
29
readonly onDidFinishInput : Event < IPromptInputModelState > ;
30
+ /**
31
+ * Fires immediately before {@link onDidFinishInput} when a SIGINT/Ctrl+C/^C is detected.
32
+ */
33
+ readonly onDidInterrupt : Event < IPromptInputModelState > ;
26
34
27
35
readonly value : string ;
28
36
readonly cursorIndex : number ;
@@ -48,6 +56,8 @@ export class PromptInputModel extends Disposable implements IPromptInputModel {
48
56
private _commandStartX : number = 0 ;
49
57
private _continuationPrompt : string | undefined ;
50
58
59
+ private _lastUserInput : string = '' ;
60
+
51
61
private _value : string = '' ;
52
62
get value ( ) { return this . _value ; }
53
63
@@ -63,6 +73,8 @@ export class PromptInputModel extends Disposable implements IPromptInputModel {
63
73
readonly onDidChangeInput = this . _onDidChangeInput . event ;
64
74
private readonly _onDidFinishInput = this . _register ( new Emitter < IPromptInputModelState > ( ) ) ;
65
75
readonly onDidFinishInput = this . _onDidFinishInput . event ;
76
+ private readonly _onDidInterrupt = this . _register ( new Emitter < IPromptInputModelState > ( ) ) ;
77
+ readonly onDidInterrupt = this . _onDidInterrupt . event ;
66
78
67
79
constructor (
68
80
private readonly _xterm : Terminal ,
@@ -72,11 +84,12 @@ export class PromptInputModel extends Disposable implements IPromptInputModel {
72
84
) {
73
85
super ( ) ;
74
86
75
- this . _register ( this . _xterm . onData ( e => this . _handleInput ( e ) ) ) ;
76
87
this . _register ( Event . any (
77
- this . _xterm . onWriteParsed ,
78
88
this . _xterm . onCursorMove ,
89
+ this . _xterm . onData ,
90
+ this . _xterm . onWriteParsed ,
79
91
) ( ( ) => this . _sync ( ) ) ) ;
92
+ this . _register ( this . _xterm . onData ( e => this . _handleUserInput ( e ) ) ) ;
80
93
81
94
this . _register ( onCommandStart ( e => this . _handleCommandStart ( e as { marker : IMarker } ) ) ) ;
82
95
this . _register ( onCommandExecuted ( ( ) => this . _handleCommandExecuted ( ) ) ) ;
@@ -121,11 +134,11 @@ export class PromptInputModel extends Disposable implements IPromptInputModel {
121
134
122
135
this . _state = PromptInputState . Execute ;
123
136
this . _cursorIndex = - 1 ;
124
- this . _onDidFinishInput . fire ( this . _createStateObject ( ) ) ;
125
- }
126
-
127
- private _handleInput ( data : string ) {
128
- this . _sync ( ) ;
137
+ const event = this . _createStateObject ( ) ;
138
+ if ( this . _lastUserInput === '\u0003' ) { // ETX end of text (ctrl+c)
139
+ this . _onDidInterrupt . fire ( event ) ;
140
+ }
141
+ this . _onDidFinishInput . fire ( event ) ;
129
142
}
130
143
131
144
@throttle ( 0 )
@@ -207,6 +220,10 @@ export class PromptInputModel extends Disposable implements IPromptInputModel {
207
220
}
208
221
}
209
222
223
+ private _handleUserInput ( e : string ) {
224
+ this . _lastUserInput = e ;
225
+ }
226
+
210
227
/**
211
228
* Detect ghost text by looking for italic or dim text in or after the cursor and
212
229
* non-italic/dim text in the cell closest non-whitespace cell before the cursor.
0 commit comments