@@ -23,13 +23,20 @@ const writeOutput = (data: string) => {
2323 process . stdout . write ( data ) ;
2424} ;
2525
26- const _render = ( term : ISTerm , suggestionManager : SuggestionManager , data : string , handlingBackspace : boolean ) : boolean => {
27- const direction = term . getCursorState ( ) . remainingLines > MAX_LINES ? "below" : "above" ;
26+ const _render = ( term : ISTerm , suggestionManager : SuggestionManager , data : string , handlingBackspace : boolean , handlingSuggestion : boolean ) : boolean => {
27+ const direction = _direction ( term ) ;
2828 const { hidden : cursorHidden , shift : cursorShift } = term . getCursorState ( ) ;
2929 const linesOfInterest = MAX_LINES ;
3030
3131 const suggestion = suggestionManager . render ( direction ) ;
3232 const hasSuggestion = suggestion . length != 0 ;
33+
34+ if ( ! handlingSuggestion && ! hasSuggestion ) {
35+ // there is no rendered suggestion and this will not render a suggestion
36+ writeOutput ( data ) ;
37+ return false ;
38+ }
39+
3340 const commandState = term . getCommandState ( ) ;
3441 const cursorTerminated = handlingBackspace ? true : commandState . cursorTerminated ?? false ;
3542 const showSuggestions = hasSuggestion && cursorTerminated && ! commandState . hasOutput && ! cursorShift ;
@@ -46,10 +53,28 @@ const _render = (term: ISTerm, suggestionManager: SuggestionManager, data: strin
4653 return showSuggestions ;
4754} ;
4855
56+ const _clear = ( term : ISTerm ) : void => {
57+ const clearDirection = _direction ( term ) == "above" ? "below" : "above" ; // invert direction to clear what was previously rendered
58+ const { hidden : cursorHidden } = term . getCursorState ( ) ;
59+ const patch = term . getPatch ( MAX_LINES , [ ] , clearDirection ) ;
60+
61+ const ansiCursorShow = cursorHidden ? "" : ansi . cursorShow ;
62+ if ( clearDirection == "above" ) {
63+ writeOutput ( ansi . cursorHide + ansi . cursorSavePosition + ansi . cursorPrevLine . repeat ( MAX_LINES ) + patch + ansi . cursorRestorePosition + ansiCursorShow ) ;
64+ } else {
65+ writeOutput ( ansi . cursorHide + ansi . cursorSavePosition + ansi . cursorNextLine + patch + ansi . cursorRestorePosition + ansiCursorShow ) ;
66+ }
67+ } ;
68+
69+ const _direction = ( term : ISTerm ) : "above" | "below" => {
70+ return term . getCursorState ( ) . remainingLines > MAX_LINES ? "below" : "above" ;
71+ } ;
72+
4973export const render = async ( program : Command , shell : Shell , underTest : boolean , login : boolean ) => {
5074 const term = await isterm . spawn ( program , { shell, rows : process . stdout . rows , cols : process . stdout . columns , underTest, login } ) ;
5175 const suggestionManager = new SuggestionManager ( term , shell ) ;
5276 let hasSuggestion = false ;
77+ let direction = _direction ( term ) ;
5378 let handlingBackspace = false ; // backspace normally consistent of two data points (move back & delete), so on the first data point, we won't enforce the cursor terminated rule. this will help reduce flicker
5479 const stdinStartedInRawMode = process . stdin . isRaw ;
5580 if ( process . stdin . isTTY ) process . stdin . setRawMode ( true ) ;
@@ -63,11 +88,17 @@ export const render = async (program: Command, shell: Shell, underTest: boolean,
6388 writeOutput ( ansi . clearTerminal ) ;
6489
6590 term . onData ( async ( data ) => {
66- hasSuggestion = _render ( term , suggestionManager , data , handlingBackspace ) ;
91+ const handlingDirectionChange = direction != _direction ( term ) ;
92+ if ( handlingDirectionChange ) {
93+ _clear ( term ) ;
94+ }
95+
96+ hasSuggestion = _render ( term , suggestionManager , data , handlingBackspace , hasSuggestion ) ;
6797 await suggestionManager . exec ( ) ;
68- hasSuggestion = _render ( term , suggestionManager , "" , handlingBackspace ) ;
98+ hasSuggestion = _render ( term , suggestionManager , "" , handlingBackspace , hasSuggestion ) ;
6999
70100 handlingBackspace = false ;
101+ direction = _direction ( term ) ;
71102 } ) ;
72103
73104 process . stdin . on ( "keypress" , ( ...keyPress : KeyPressEvent ) => {
0 commit comments