33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
55
6- import type { Terminal } from '@xterm/xterm' ;
6+ import type { IDecoration , IDecorationOptions , Terminal } from '@xterm/xterm' ;
77import { deepStrictEqual , ok , strictEqual } from 'assert' ;
88import { importAMDNodeModule } from '../../../../../../amdX.js' ;
99import { Color , RGBA } from '../../../../../../base/common/color.js' ;
@@ -12,6 +12,9 @@ import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../../base/
1212import { IEditorOptions } from '../../../../../../editor/common/config/editorOptions.js' ;
1313import { TestConfigurationService } from '../../../../../../platform/configuration/test/common/testConfigurationService.js' ;
1414import { TestInstantiationService } from '../../../../../../platform/instantiation/test/common/instantiationServiceMock.js' ;
15+ import { ITerminalCommand , TerminalCapability } from '../../../../../../platform/terminal/common/capabilities/capabilities.js' ;
16+ import { CommandDetectionCapability } from '../../../../../../platform/terminal/common/capabilities/commandDetectionCapability.js' ;
17+ import { PartialCommandDetectionCapability } from '../../../../../../platform/terminal/common/capabilities/partialCommandDetectionCapability.js' ;
1518import { TerminalCapabilityStore } from '../../../../../../platform/terminal/common/capabilities/terminalCapabilityStore.js' ;
1619import { IThemeService } from '../../../../../../platform/theme/common/themeService.js' ;
1720import { TestColorTheme , TestThemeService } from '../../../../../../platform/theme/test/common/testThemeService.js' ;
@@ -53,7 +56,11 @@ const defaultTerminalConfig: Partial<ITerminalConfiguration> = {
5356 scrollback : 10 ,
5457 fastScrollSensitivity : 2 ,
5558 mouseWheelScrollSensitivity : 1 ,
56- unicodeVersion : '6'
59+ unicodeVersion : '6' ,
60+ shellIntegration : {
61+ enabled : true ,
62+ decorationsEnabled : 'both'
63+ }
5764} ;
5865
5966suite ( 'XtermTerminal' , ( ) => {
@@ -64,6 +71,7 @@ suite('XtermTerminal', () => {
6471 let themeService : TestThemeService ;
6572 let xterm : XtermTerminal ;
6673 let XTermBaseCtor : typeof Terminal ;
74+ let capabilityStore : TerminalCapabilityStore ;
6775
6876 function write ( data : string ) : Promise < void > {
6977 return new Promise < void > ( ( resolve ) => {
@@ -90,7 +98,7 @@ suite('XtermTerminal', () => {
9098
9199 XTermBaseCtor = ( await importAMDNodeModule < typeof import ( '@xterm/xterm' ) > ( '@xterm/xterm' , 'lib/xterm.js' ) ) . Terminal ;
92100
93- const capabilityStore = store . add ( new TerminalCapabilityStore ( ) ) ;
101+ capabilityStore = store . add ( new TerminalCapabilityStore ( ) ) ;
94102 xterm = store . add ( instantiationService . createInstance ( XtermTerminal , undefined , XTermBaseCtor , {
95103 cols : 80 ,
96104 rows : 30 ,
@@ -109,6 +117,79 @@ suite('XtermTerminal', () => {
109117 strictEqual ( xterm . raw . rows , 30 ) ;
110118 } ) ;
111119
120+ test ( 'clearBuffer should clear rich and partial command history including scrollback' , async ( ) => {
121+ class TestTerminal extends XTermBaseCtor {
122+ override registerDecoration ( options : IDecorationOptions ) : IDecoration | undefined {
123+ const disposeListeners = new Set < ( ) => unknown > ( ) ;
124+ let isDisposed = false ;
125+ return {
126+ marker : options . marker ,
127+ options,
128+ get isDisposed ( ) { return isDisposed ; } ,
129+ dispose : ( ) => {
130+ isDisposed = true ;
131+ for ( const listener of disposeListeners ) {
132+ listener ( ) ;
133+ }
134+ disposeListeners . clear ( ) ;
135+ } ,
136+ onDispose : ( listener : ( ) => unknown ) => {
137+ disposeListeners . add ( listener ) ;
138+ return { dispose : ( ) => disposeListeners . delete ( listener ) } ;
139+ } ,
140+ onRender : ( listener : ( element : HTMLElement ) => unknown ) => {
141+ listener ( document . createElement ( 'div' ) ) ;
142+ return { dispose ( ) { } } ;
143+ }
144+ } as unknown as IDecoration ;
145+ }
146+ }
147+ capabilityStore = store . add ( new TerminalCapabilityStore ( ) ) ;
148+ xterm = store . add ( instantiationService . createInstance ( XtermTerminal , undefined , TestTerminal , {
149+ cols : 80 ,
150+ rows : 30 ,
151+ xtermColorProvider : { getBackgroundColor : ( ) => undefined } ,
152+ capabilities : capabilityStore ,
153+ disableShellIntegrationReporting : true ,
154+ xtermAddonImporter : new TestXtermAddonImporter ( ) ,
155+ } , undefined ) ) ;
156+ const commandDetection = store . add ( instantiationService . createInstance ( CommandDetectionCapability , xterm . raw ) ) ;
157+ const onDidExecuteText = store . add ( new Emitter < void > ( ) ) ;
158+ const partialCommandDetection = store . add ( new PartialCommandDetectionCapability ( xterm . raw , onDidExecuteText . event ) ) ;
159+ capabilityStore . add ( TerminalCapability . CommandDetection , commandDetection ) ;
160+ capabilityStore . add ( TerminalCapability . PartialCommandDetection , partialCommandDetection ) ;
161+
162+ xterm . raw . registerMarker ( 0 ) ;
163+ commandDetection . handlePromptStart ( ) ;
164+ await write ( '$ ' ) ;
165+ commandDetection . handleCommandStart ( ) ;
166+ await write ( 'echo test' ) ;
167+ commandDetection . handleCommandExecuted ( ) ;
168+ await write ( '\r\noutput\r\n' ) ;
169+ commandDetection . handleCommandFinished ( 0 ) ;
170+
171+ await write ( 'partial' ) ;
172+ xterm . raw . input ( '\r' ) ;
173+ await write ( '\r\n' ) ;
174+ await write ( 'line\r\n' . repeat ( xterm . raw . rows ) ) ;
175+
176+ strictEqual ( xterm . raw . buffer . active . baseY > 0 , true ) ;
177+ strictEqual ( commandDetection . commands . length , 1 ) ;
178+ strictEqual ( partialCommandDetection . commands . length , 1 ) ;
179+ const decorations = ( xterm . decorationAddon as unknown as { _decorations : Map < number , unknown > } ) . _decorations ;
180+ const clearedCommandMarkerId = commandDetection . commands [ 0 ] . marker ! . id ;
181+ strictEqual ( decorations . has ( clearedCommandMarkerId ) , true ) ;
182+ const invalidatedCommands : ITerminalCommand [ ] = [ ] ;
183+ store . add ( commandDetection . onCommandInvalidated ( commands => invalidatedCommands . push ( ...commands ) ) ) ;
184+
185+ xterm . clearBuffer ( ) ;
186+
187+ deepStrictEqual ( commandDetection . commands , [ ] ) ;
188+ deepStrictEqual ( partialCommandDetection . commands , [ ] ) ;
189+ deepStrictEqual ( invalidatedCommands . map ( e => e . command ) , [ 'echo test' ] ) ;
190+ strictEqual ( decorations . has ( clearedCommandMarkerId ) , false ) ;
191+ } ) ;
192+
112193 suite ( 'getContentsAsText' , ( ) => {
113194 test ( 'should return all buffer contents when no markers provided' , async ( ) => {
114195 await write ( 'line 1\r\nline 2\r\nline 3\r\nline 4\r\nline 5' ) ;
0 commit comments