@@ -946,29 +946,37 @@ export class PredictionTimeline {
946946 return buffer . type === 'normal' ? buffer : undefined ;
947947 }
948948}
949+
949950/**
950- * Gets the escape sequence to restore state/appearence in the cell.
951+ * Gets the escape sequence args to restore state/appearence in the cell.
951952 */
952- const attributesToSeq = ( cell : XTermAttributes ) => cell . isAttributeDefault ( )
953- ? `${ CSI } 0m`
954- : [
955- cell . isBold ( ) && `${ CSI } 1m` ,
956- cell . isDim ( ) && `${ CSI } 2m` ,
957- cell . isItalic ( ) && `${ CSI } 3m` ,
958- cell . isUnderline ( ) && `${ CSI } 4m` ,
959- cell . isBlink ( ) && `${ CSI } 5m` ,
960- cell . isInverse ( ) && `${ CSI } 7m` ,
961- cell . isInvisible ( ) && `${ CSI } 8m` ,
962-
963- cell . isFgRGB ( ) && `${ CSI } 38;2;${ cell . getFgColor ( ) >>> 24 } ;${ ( cell . getFgColor ( ) >>> 16 ) & 0xFF } ;${ cell . getFgColor ( ) & 0xFF } m` ,
964- cell . isFgPalette ( ) && `${ CSI } 38;5;${ cell . getFgColor ( ) } m` ,
965- cell . isFgDefault ( ) && `${ CSI } 39m` ,
966-
967- cell . isBgRGB ( ) && `${ CSI } 48;2;${ cell . getBgColor ( ) >>> 24 } ;${ ( cell . getBgColor ( ) >>> 16 ) & 0xFF } ;${ cell . getBgColor ( ) & 0xFF } m` ,
968- cell . isBgPalette ( ) && `${ CSI } 48;5;${ cell . getBgColor ( ) } m` ,
969- cell . isBgDefault ( ) && `${ CSI } 49m` ,
970- ] . filter ( seq => ! ! seq ) . join ( '' ) ;
953+ const attributesToArgs = ( cell : XTermAttributes ) => {
954+ if ( cell . isAttributeDefault ( ) ) { return [ 0 ] ; }
955+
956+ const args = [ ] ;
957+ if ( cell . isBold ( ) ) { args . push ( 1 ) ; }
958+ if ( cell . isDim ( ) ) { args . push ( 2 ) ; }
959+ if ( cell . isItalic ( ) ) { args . push ( 3 ) ; }
960+ if ( cell . isUnderline ( ) ) { args . push ( 4 ) ; }
961+ if ( cell . isBlink ( ) ) { args . push ( 5 ) ; }
962+ if ( cell . isInverse ( ) ) { args . push ( 7 ) ; }
963+ if ( cell . isInvisible ( ) ) { args . push ( 8 ) ; }
964+
965+ if ( cell . isFgRGB ( ) ) { args . push ( 38 , 2 , cell . getFgColor ( ) >>> 24 , ( cell . getFgColor ( ) >>> 16 ) & 0xFF , cell . getFgColor ( ) & 0xFF ) ; }
966+ if ( cell . isFgPalette ( ) ) { args . push ( 38 , 5 , cell . getFgColor ( ) ) ; }
967+ if ( cell . isFgDefault ( ) ) { args . push ( 39 ) ; }
968+
969+ if ( cell . isBgRGB ( ) ) { args . push ( 48 , 2 , cell . getBgColor ( ) >>> 24 , ( cell . getBgColor ( ) >>> 16 ) & 0xFF , cell . getBgColor ( ) & 0xFF ) ; }
970+ if ( cell . isBgPalette ( ) ) { args . push ( 48 , 5 , cell . getBgColor ( ) ) ; }
971+ if ( cell . isBgDefault ( ) ) { args . push ( 49 ) ; }
972+
973+ return args ;
974+ } ;
971975
976+ /**
977+ * Gets the escape sequence to restore state/appearence in the cell.
978+ */
979+ const attributesToSeq = ( cell : XTermAttributes ) => `${ CSI } ${ attributesToArgs ( cell ) . join ( ';' ) } m` ;
972980
973981const arrayHasPrefixAt = < T > ( a : ReadonlyArray < T > , ai : number , b : ReadonlyArray < T > ) => {
974982 if ( a . length - ai > b . length ) {
@@ -1019,7 +1027,7 @@ const getColorWidth = (params: (number | number[])[], pos: number) => {
10191027 return advance ;
10201028} ;
10211029
1022- class TypeAheadStyle {
1030+ class TypeAheadStyle implements IDisposable {
10231031 private static compileArgs ( args : ReadonlyArray < number > ) {
10241032 return `${ CSI } ${ args . join ( ';' ) } m` ;
10251033 }
@@ -1035,8 +1043,9 @@ class TypeAheadStyle {
10351043
10361044 public apply ! : string ;
10371045 public undo ! : string ;
1046+ private csiHandler ?: IDisposable ;
10381047
1039- constructor ( value : ITerminalConfiguration [ 'localEchoStyle' ] ) {
1048+ constructor ( value : ITerminalConfiguration [ 'localEchoStyle' ] , private readonly terminal : Terminal ) {
10401049 this . onUpdate ( value ) ;
10411050 }
10421051
@@ -1049,9 +1058,38 @@ class TypeAheadStyle {
10491058 }
10501059
10511060 /**
1052- * Should be called when an attribut eupdate happens in the terminal.
1061+ * Starts tracking for CSI changes in the terminal.
1062+ */
1063+ public startTracking ( ) {
1064+ this . expectedIncomingStyles = 0 ;
1065+ this . onDidWriteSGR ( attributesToArgs ( core ( this . terminal ) . _inputHandler . _curAttrData ) ) ;
1066+ this . csiHandler = this . terminal . parser . registerCsiHandler ( { final : 'm' } , args => {
1067+ this . onDidWriteSGR ( args ) ;
1068+ return false ;
1069+ } ) ;
1070+ }
1071+
1072+ /**
1073+ * Stops tracking terminal CSI changes.
10531074 */
1054- public onDidWriteSGR ( args : ( number | number [ ] ) [ ] ) {
1075+ @debounce ( 2000 )
1076+ public debounceStopTracking ( ) {
1077+ this . stopTracking ( ) ;
1078+ }
1079+
1080+ /**
1081+ * @inheritdoc
1082+ */
1083+ public dispose ( ) {
1084+ this . stopTracking ( ) ;
1085+ }
1086+
1087+ private stopTracking ( ) {
1088+ this . csiHandler ?. dispose ( ) ;
1089+ this . csiHandler = undefined ;
1090+ }
1091+
1092+ private onDidWriteSGR ( args : ( number | number [ ] ) [ ] ) {
10551093 const originalUndo = this . undoArgs ;
10561094 for ( let i = 0 ; i < args . length ; ) {
10571095 const px = args [ i ] ;
@@ -1141,7 +1179,7 @@ class TypeAheadStyle {
11411179}
11421180
11431181export class TypeAheadAddon extends Disposable implements ITerminalAddon {
1144- private typeaheadStyle = new TypeAheadStyle ( this . config . config . localEchoStyle ) ;
1182+ private typeaheadStyle ?: TypeAheadStyle ;
11451183 private typeaheadThreshold = this . config . config . localEchoLatencyThreshold ;
11461184 protected lastRow ?: { y : number ; startingX : number } ;
11471185 private timeline ?: PredictionTimeline ;
@@ -1162,22 +1200,19 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon {
11621200 }
11631201
11641202 public activate ( terminal : Terminal ) : void {
1203+ const style = this . typeaheadStyle = this . _register ( new TypeAheadStyle ( this . config . config . localEchoStyle , terminal ) ) ;
11651204 const timeline = this . timeline = new PredictionTimeline ( terminal , this . typeaheadStyle ) ;
11661205 const stats = this . stats = this . _register ( new PredictionStats ( this . timeline ) ) ;
11671206
11681207 timeline . setShowPredictions ( this . typeaheadThreshold === 0 ) ;
1169- this . _register ( terminal . parser . registerCsiHandler ( { final : 'm' } , args => {
1170- this . typeaheadStyle . onDidWriteSGR ( args ) ;
1171- return false ;
1172- } ) ) ;
11731208 this . _register ( terminal . onData ( e => this . onUserData ( e ) ) ) ;
11741209 this . _register ( terminal . onResize ( ( ) => {
11751210 timeline . setShowPredictions ( false ) ;
11761211 timeline . clearCursor ( ) ;
11771212 this . reevaluatePredictorState ( stats , timeline ) ;
11781213 } ) ) ;
11791214 this . _register ( this . config . onConfigChanged ( ( ) => {
1180- this . typeaheadStyle . onUpdate ( this . config . config . localEchoStyle ) ;
1215+ style . onUpdate ( this . config . config . localEchoStyle ) ;
11811216 this . typeaheadThreshold = this . config . config . localEchoLatencyThreshold ;
11821217 this . reevaluatePredictorState ( stats , timeline ) ;
11831218 } ) ) ;
@@ -1192,6 +1227,10 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon {
11921227 } , statsSendTelemetryEvery ) ;
11931228 }
11941229
1230+ if ( timeline . length === 0 ) {
1231+ style . debounceStopTracking ( ) ;
1232+ }
1233+
11951234 this . reevaluatePredictorState ( stats , timeline ) ;
11961235 } ) ) ;
11971236 }
@@ -1306,7 +1345,7 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon {
13061345
13071346 if ( reader . eatCharCode ( 32 , 126 ) ) { // alphanum
13081347 const char = data [ reader . index - 1 ] ;
1309- if ( this . timeline . addPrediction ( buffer , new CharacterPrediction ( this . typeaheadStyle , char ) ) && this . timeline . getCursor ( buffer ) . x === terminal . cols ) {
1348+ if ( this . timeline . addPrediction ( buffer , new CharacterPrediction ( this . typeaheadStyle ! , char ) ) && this . timeline . getCursor ( buffer ) . x === terminal . cols ) {
13101349 this . timeline . addBoundary ( buffer , new TentativeBoundary ( new LinewrapPrediction ( ) ) ) ;
13111350 }
13121351 continue ;
@@ -1346,6 +1385,7 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon {
13461385
13471386 if ( this . timeline . length === 1 ) {
13481387 this . deferClearingPredictions ( ) ;
1388+ this . typeaheadStyle ! . startTracking ( ) ;
13491389 }
13501390 }
13511391
0 commit comments