@@ -12,7 +12,7 @@ import type { SerializeAddon as SerializeAddonType } from 'xterm-addon-serialize
12
12
import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private' ;
13
13
import { ConfigurationTarget , IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
14
14
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper' ;
15
- import { DisposableStore } from 'vs/base/common/lifecycle' ;
15
+ import { DisposableStore , IDisposable } from 'vs/base/common/lifecycle' ;
16
16
import { IEditorOptions } from 'vs/editor/common/config/editorOptions' ;
17
17
import { IShellIntegration , TerminalLocation , TerminalSettingId } from 'vs/platform/terminal/common/terminal' ;
18
18
import { ITerminalFont , TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal' ;
@@ -776,7 +776,10 @@ class AccessibleBuffer extends DisposableStore {
776
776
private _accessibleBuffer : HTMLElement ;
777
777
private _bufferEditor : CodeEditorWidget ;
778
778
private _editorContainer : HTMLElement ;
779
+ private _commandFinishedDisposable : IDisposable | undefined ;
780
+ private _refreshSelection : boolean = true ;
779
781
private _registered : boolean = false ;
782
+ private _lastContentLength : number = 0 ;
780
783
private _font : ITerminalFont ;
781
784
782
785
constructor (
@@ -824,27 +827,45 @@ class AccessibleBuffer extends DisposableStore {
824
827
825
828
async focus ( ) : Promise < void > {
826
829
await this . _updateBufferEditor ( ) ;
827
- // Updates xterm's accessibleBufferActive property
828
- // such that mouse events do not cause the terminal buffer
829
- // to steal the focus
830
- this . _accessibleBuffer . focus ( ) ;
831
- this . _bufferEditor . focus ( ) ;
832
830
}
833
831
834
832
private async _updateBufferEditor ( ) : Promise < void > {
833
+ const commandDetection = this . _capabilities . get ( TerminalCapability . CommandDetection ) ;
834
+ const fragment = ! ! commandDetection ? this . _getShellIntegrationContent ( ) : this . _getAllContent ( ) ;
835
+ const model = await this . _getTextModel ( URI . from ( { scheme : ACCESSIBLE_BUFFER . Scheme , fragment } ) ) ;
836
+ if ( model ) {
837
+ this . _bufferEditor . setModel ( model ) ;
838
+ }
839
+
835
840
if ( ! this . _registered ) {
836
- // Registration is delayed until focus so the capability has time to have been added
837
841
this . add ( this . _terminal . raw . registerBufferElementProvider ( { provideBufferElements : ( ) => this . _editorContainer } ) ) ;
842
+ // When this is created, the element isn't yet attached so the dimensions are tiny
843
+ this . _bufferEditor . layout ( { width : this . _accessibleBuffer . clientWidth , height : this . _accessibleBuffer . clientHeight } ) ;
838
844
this . _registered = true ;
839
845
}
840
- // When this is created, the element isn't yet attached so the dimensions are tiny
841
- this . _bufferEditor . layout ( { width : this . _accessibleBuffer . clientWidth , height : this . _accessibleBuffer . clientHeight } ) ;
842
- const commandDetection = this . _capabilities . has ( TerminalCapability . CommandDetection ) ;
843
- const fragment = commandDetection ? this . _getShellIntegrationContent ( ) : this . _getAllContent ( ) ;
844
- const model = await this . _getTextModel ( URI . from ( { scheme : ACCESSIBLE_BUFFER . Scheme , fragment } ) ) ;
845
- if ( model ) {
846
- this . _bufferEditor . setModel ( model ) ;
846
+
847
+ if ( ! this . _commandFinishedDisposable && commandDetection ) {
848
+ this . _commandFinishedDisposable = commandDetection . onCommandFinished ( ( ) => this . _refreshSelection = true ) ;
849
+ this . add ( this . _commandFinishedDisposable ) ;
850
+ }
851
+
852
+ if ( this . _lastContentLength !== fragment . length || this . _refreshSelection ) {
853
+ let lineNumber = 1 ;
854
+ const lineCount = model ?. getLineCount ( ) ;
855
+ if ( lineCount && model ) {
856
+ lineNumber = commandDetection ? lineCount - 1 : lineCount > 2 ? lineCount - 2 : 1 ;
857
+ }
858
+ this . _bufferEditor . setSelection ( { startLineNumber : lineNumber , startColumn : 1 , endLineNumber : lineNumber , endColumn : 1 } ) ;
859
+ this . _bufferEditor . setScrollTop ( this . _bufferEditor . getScrollHeight ( ) ) ;
860
+ this . _refreshSelection = false ;
861
+ this . _lastContentLength = fragment . length ;
847
862
}
863
+
864
+ // Updates xterm's accessibleBufferActive property
865
+ // such that mouse events do not cause the terminal buffer
866
+ // to steal the focus
867
+ this . _accessibleBuffer . focus ( ) ;
868
+ this . _bufferEditor . focus ( ) ;
848
869
}
849
870
850
871
async _getTextModel ( resource : URI ) : Promise < ITextModel | null > {
@@ -887,7 +908,7 @@ class AccessibleBuffer extends DisposableStore {
887
908
}
888
909
const isWrapped = buffer . getLine ( i + 1 ) ?. isWrapped ;
889
910
currentLine += line . translateToString ( ! isWrapped ) ;
890
- if ( ! isWrapped || i === end - 1 ) {
911
+ if ( currentLine && ! isWrapped || i === end - 1 ) {
891
912
lines . push ( currentLine . replace ( new RegExp ( ' ' , 'g' ) , '\xA0' ) ) ;
892
913
currentLine = '' ;
893
914
}
0 commit comments