@@ -24,10 +24,13 @@ interface IConsoleMixin extends TerminalMixin {
2424 escapeEnabled : Boolean ;
2525 insertMode : Boolean ;
2626 readonly currentLine : string ;
27+ prompt : string ;
2728}
2829
2930class ConsoleAddon extends TerminalAddon < IConsoleMixin > {
3031
32+ __yPrompt : Number = - 1 ;
33+
3134 get currentLine ( ) : string {
3235 let inputHandler = ( ( this . $core ) as any ) . _inputHandler ;
3336 let buffer = inputHandler . _bufferService . buffer ;
@@ -37,37 +40,48 @@ class ConsoleAddon extends TerminalAddon<IConsoleMixin> {
3740 line += buffer . lines . get ( i ) . translateToString ( ) ;
3841 }
3942 line = line . replace ( / \s + $ / , "" ) ;
43+ if ( this . __yPrompt == range . first ) line = line . substring ( this . $ . prompt . length ) ;
4044 return line ;
4145 }
4246
4347 activateCallback ( terminal : Terminal ) : void {
4448
4549 var inputHandler = ( ( this . $core ) as any ) . _inputHandler ;
4650
51+ let promptLength = ( ) => this . $ . prompt ? this . $ . prompt . length : 0 ;
52+
4753 let scanEOL = ( function ( ) {
4854 let buffer = this . _bufferService . buffer ;
4955 let col = this . _bufferService . buffer . lines . get ( buffer . ybase + buffer . y ) . getTrimmedLength ( ) ;
5056 this . cursorCharAbsolute ( { params :[ col + 1 ] } ) ;
5157 } ) . bind ( inputHandler ) ;
5258
53- let cursorForwardWrapped = ( function ( ) {
59+ let cursorForwardWrapped = ( function ( params : any ) {
5460 let buffer = this . _bufferService . buffer ;
55- if ( buffer . x == this . _bufferService . cols - 1 ) {
56- let next = buffer . lines . get ( buffer . y + buffer . ybase + 1 ) ;
57- if ( next && next . isWrapped ) {
58- this . cursorNextLine ( { params :1 } ) ;
61+ let x = buffer . x + ( params && params [ 0 ] || 1 ) ;
62+ do {
63+ if ( x >= this . _bufferService . cols ) {
64+ let next = buffer . lines . get ( buffer . y + buffer . ybase ) ;
65+ if ( next && next . isWrapped ) {
66+ this . cursorNextLine ( { params :1 } ) ;
67+ }
68+ x -= this . _bufferService . cols ;
69+ } else {
70+ x = Math . min ( x , this . _bufferService . buffer . lines . get ( buffer . y + buffer . ybase ) . getTrimmedLength ( ) ) ;
71+ x > 0 && this . cursorCharAbsolute ( { params :[ x + 1 ] } ) ;
5972 }
60- } else if ( buffer . x < this . _bufferService . buffer . lines . get ( buffer . y + buffer . ybase ) . getTrimmedLength ( ) ) {
61- this . cursorForward ( { params :[ 1 ] } ) ;
62- }
73+ } while ( x >= this . _bufferService . cols ) ;
6374 } ) . bind ( inputHandler ) ;
6475
6576 let cursorBackwardWrapped = ( function ( ) {
6677 let buffer = this . _bufferService . buffer ;
67- if ( buffer . x > 0 ) {
78+ let line = buffer . lines . get ( buffer . y + buffer . ybase ) ;
79+ if ( ! line . isWrapped && buffer . x < 1 + promptLength ( ) ) {
80+ return false ;
81+ } else if ( buffer . x > 0 ) {
6882 this . cursorBackward ( { params :[ 1 ] } ) ;
6983 return true ;
70- } else if ( buffer . lines . get ( buffer . y + buffer . ybase ) . isWrapped ) {
84+ } else if ( line . isWrapped ) {
7185 this . cursorPrecedingLine ( { params :[ 1 ] } ) ;
7286 scanEOL ( ) ;
7387 return true ;
@@ -76,25 +90,27 @@ class ConsoleAddon extends TerminalAddon<IConsoleMixin> {
7690 }
7791 } ) . bind ( inputHandler ) ;
7892
79- let deleteChar = ( function ( ) {
93+ let deleteChar = ( function ( params : any ) {
8094 let buffer = this . _bufferService . buffer ;
81- this . deleteChars ( { params :[ 1 ] } ) ;
8295 let x = buffer . x ;
8396 let y = buffer . y ;
84- let line = buffer . lines . get ( buffer . ybase + buffer . y ) ;
85- let range = buffer . getWrappedRangeForLine ( buffer . y + buffer . ybase )
86- for ( let i = buffer . y + buffer . ybase ; i < range . last ; i ++ ) {
87- let next = buffer . lines . get ( buffer . ybase + buffer . y + 1 ) ;
88- line . set ( line . length - 1 , next . get ( 0 ) ) ;
89- this . cursorNextLine ( { params :1 } ) ;
97+ for ( let i = 0 ; i < ( params && params [ 0 ] || 1 ) ; i ++ ) {
9098 this . deleteChars ( { params :[ 1 ] } ) ;
91- line = next ;
92- }
93- if ( line . isWrapped && line . getTrimmedLength ( ) == 0 ) {
94- line . isWrapped = false ;
95- if ( y == range . last ) {
96- y -- ;
97- x = this . _bufferService . cols - 1 ;
99+ let line = buffer . lines . get ( buffer . ybase + buffer . y ) ;
100+ let range = buffer . getWrappedRangeForLine ( buffer . y + buffer . ybase )
101+ for ( let i = buffer . y + buffer . ybase ; i < range . last ; i ++ ) {
102+ let next = buffer . lines . get ( buffer . ybase + buffer . y + 1 ) ;
103+ line . set ( line . length - 1 , next . get ( 0 ) ) ;
104+ this . cursorNextLine ( { params :1 } ) ;
105+ this . deleteChars ( { params :[ 1 ] } ) ;
106+ line = next ;
107+ }
108+ if ( line . isWrapped && line . getTrimmedLength ( ) == 0 ) {
109+ line . isWrapped = false ;
110+ if ( y == range . last ) {
111+ y -- ;
112+ x = this . _bufferService . cols - 1 ;
113+ }
98114 }
99115 }
100116 buffer . y = y ;
@@ -116,6 +132,7 @@ class ConsoleAddon extends TerminalAddon<IConsoleMixin> {
116132 } else {
117133 this . cursorCharAbsolute ( { params :[ 1 ] } ) ;
118134 }
135+ promptLength ( ) && cursorForwardWrapped ( [ promptLength ( ) ] ) ;
119136 } ) . bind ( inputHandler ) ;
120137
121138 let backspace = ( function ( ) {
@@ -212,6 +229,32 @@ class ConsoleAddon extends TerminalAddon<IConsoleMixin> {
212229
213230 }
214231
232+ writePrompt ( ) {
233+ if ( ! this . $ . prompt ) return ;
234+
235+ let inputHandler = ( ( this . $core ) as any ) . _inputHandler ;
236+ let buffer = inputHandler . _bufferService . buffer ;
237+ let range = buffer . getWrappedRangeForLine ( buffer . y + buffer . ybase ) ;
238+
239+ let prepare = "" ;
240+ let restore = this . $ . insertMode ? "\x1b[4h" : "\x1b[4l"
241+
242+ console . error ( this . __yPrompt + " " + range . first + " " + buffer . y + " " + buffer . ybase ) ;
243+ if ( this . __yPrompt == range . first ) {
244+ //prompt has been written in this line
245+ prepare += "\x1b[4l" ; //Override mode
246+ } else {
247+ //prompt has not been written in this line
248+ this . __yPrompt = range . first ;
249+ prepare += "\x1b[s" ; //Save cursor position
250+ prepare += "\x1b[4h" ; //Insert mode
251+ restore += "\x1b[u" ; //Restore cursor position
252+ restore += "\x1b[<" + this . $ . prompt . length + "R" ; //cursor forward wrapped
253+ }
254+
255+ prepare += "\x1b[<H\x1b[G" ; //Cursor Home Logical, Cursor Horizontal Absolute
256+ this . $ . prompt && this . $ . node . terminal . write ( prepare + this . $ . prompt + restore ) ;
257+ }
215258}
216259
217260type Constructor < T = { } > = new ( ...args : any [ ] ) => T ;
@@ -220,6 +263,7 @@ export function XTermConsoleMixin<TBase extends Constructor<TerminalMixin>>(Base
220263
221264 _addon ? : ConsoleAddon ;
222265 escapeEnabled : Boolean ;
266+ prompt : string ;
223267
224268 connectedCallback ( ) {
225269 super . connectedCallback ( ) ;
@@ -245,5 +289,10 @@ export function XTermConsoleMixin<TBase extends Constructor<TerminalMixin>>(Base
245289 return this . _addon . currentLine ;
246290 }
247291
292+ writePrompt ( ) {
293+ //execute writePrompt with blocking semantics
294+ this . node . terminal . write ( '' , ( ) => this . _addon . writePrompt ( ) ) ;
295+ }
296+
248297 }
249298}
0 commit comments