@@ -578,6 +578,7 @@ private class PredictionInlineView : PredictionViewBase
578578 private uint ? _predictorSession ;
579579 private string _suggestionText ;
580580 private string _lastInputText ;
581+ private int _renderedLength ;
581582 private bool _alreadyAccepted ;
582583
583584 internal string SuggestionText => _suggestionText ;
@@ -671,11 +672,59 @@ internal override void RenderSuggestion(List<StringBuilder> consoleBufferLines,
671672 }
672673
673674 int inputLength = _inputText . Length ;
675+ int totalLength = _suggestionText . Length ;
676+
677+ // Get the maximum buffer cells that could be available to the current command line.
678+ int maxBufferCells = _singleton . _console . BufferHeight * _singleton . _console . BufferWidth - _singleton . _initialX ;
679+ bool skipRendering = false ;
680+
681+ // Assuming the suggestion text contains wide characters only (1 character takes up 2 buffer cells),
682+ // if it still can fit in the console buffer, then we are all good; otherwise, it is possible that
683+ // it could not fit, and thus more calculation is needed to check if that's really the case.
684+ if ( totalLength * 2 > maxBufferCells )
685+ {
686+ int length = SubstringLengthByCells ( _suggestionText , maxBufferCells ) ;
687+ if ( length <= inputLength )
688+ {
689+ // Even the user input cannot fit in the console buffer without having part of it scrolled up-off the buffer.
690+ // We don't attempt to render the suggestion text in this case.
691+ skipRendering = true ;
692+ }
693+ else if ( length < totalLength )
694+ {
695+ // The whole suggestion text cannot fit in the console buffer without having part of it scrolled up off the buffer.
696+ // We truncate the end part and append ellipsis.
697+
698+ // We need to truncate 4 buffer cells ealier (just to be safe), so we have enough room to add the ellipsis.
699+ int lenFromEnd = SubstringLengthByCellsFromEnd ( _suggestionText , length - 1 , countOfCells : 4 ) ;
700+ totalLength = length - lenFromEnd ;
701+ if ( totalLength <= inputLength )
702+ {
703+ // No suggestion left after truncation, so no need to render.
704+ skipRendering = true ;
705+ }
706+ }
707+ }
708+
709+ if ( skipRendering )
710+ {
711+ _renderedLength = 0 ;
712+ return ;
713+ }
714+
715+ _renderedLength = totalLength ;
674716 StringBuilder currentLineBuffer = consoleBufferLines [ currentLogicalLine ] ;
675717
676- currentLineBuffer . Append ( _singleton . _options . _inlinePredictionColor )
677- . Append ( _suggestionText , inputLength , _suggestionText . Length - inputLength )
678- . Append ( VTColorUtils . AnsiReset ) ;
718+ currentLineBuffer
719+ . Append ( _singleton . _options . _inlinePredictionColor )
720+ . Append ( _suggestionText , inputLength , _renderedLength - inputLength ) ;
721+
722+ if ( _renderedLength < _suggestionText . Length )
723+ {
724+ currentLineBuffer . Append ( "..." ) ;
725+ }
726+
727+ currentLineBuffer . Append ( VTColorUtils . AnsiReset ) ;
679728 }
680729
681730 internal override void OnSuggestionAccepted ( )
@@ -702,34 +751,38 @@ internal override void Clear(bool cursorAtEol)
702751 return ;
703752 }
704753
705- int left , top ;
706- int inputLen = _inputText . Length ;
707- IConsole console = _singleton . _console ;
708-
709- if ( cursorAtEol )
754+ if ( _renderedLength > 0 )
710755 {
711- left = console . CursorLeft ;
712- top = console . CursorTop ;
713- console . BlankRestOfLine ( ) ;
714- }
715- else
716- {
717- Point bufferEndPoint = _singleton . ConvertOffsetToPoint ( inputLen ) ;
718- left = bufferEndPoint . X ;
719- top = bufferEndPoint . Y ;
720- _singleton . WriteBlankRestOfLine ( left , top ) ;
721- }
756+ // Clear the suggestion only if we actually rendered it.
757+ int left , top ;
758+ int inputLen = _inputText . Length ;
759+ IConsole console = _singleton . _console ;
722760
723- int bufferWidth = console . BufferWidth ;
724- int columns = LengthInBufferCells ( _suggestionText , inputLen , _suggestionText . Length ) ;
761+ if ( cursorAtEol )
762+ {
763+ left = console . CursorLeft ;
764+ top = console . CursorTop ;
765+ console . BlankRestOfLine ( ) ;
766+ }
767+ else
768+ {
769+ Point bufferEndPoint = _singleton . ConvertOffsetToPoint ( inputLen ) ;
770+ left = bufferEndPoint . X ;
771+ top = bufferEndPoint . Y ;
772+ _singleton . WriteBlankRestOfLine ( left , top ) ;
773+ }
725774
726- int remainingLenInCells = bufferWidth - left ;
727- columns -= remainingLenInCells ;
728- if ( columns > 0 )
729- {
730- int extra = columns % bufferWidth > 0 ? 1 : 0 ;
731- int count = columns / bufferWidth + extra ;
732- _singleton . WriteBlankLines ( top + 1 , count ) ;
775+ int bufferWidth = console . BufferWidth ;
776+ int columns = LengthInBufferCells ( _suggestionText , inputLen , _renderedLength ) ;
777+
778+ int remainingLenInCells = bufferWidth - left ;
779+ columns -= remainingLenInCells ;
780+ if ( columns > 0 )
781+ {
782+ int extra = columns % bufferWidth > 0 ? 1 : 0 ;
783+ int count = columns / bufferWidth + extra ;
784+ _singleton . WriteBlankLines ( top + 1 , count ) ;
785+ }
733786 }
734787
735788 Reset ( ) ;
@@ -742,6 +795,7 @@ internal override void Reset()
742795 _predictorId = Guid . Empty ;
743796 _predictorSession = null ;
744797 _alreadyAccepted = false ;
798+ _renderedLength = 0 ;
745799 }
746800
747801 /// <summary>
0 commit comments