@@ -10,6 +10,7 @@ import * as resources from 'vs/base/common/resources';
1010import { ReadableStreamEventPayload } from 'vs/base/common/stream' ;
1111import { URI , UriComponents } from 'vs/base/common/uri' ;
1212import { transformOutgoingURIs } from 'vs/base/common/uriIpc' ;
13+ import { getSystemShell } from 'vs/base/node/shell' ;
1314import { IServerChannel } from 'vs/base/parts/ipc/common/ipc' ;
1415import { IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics' ;
1516import { INativeEnvironmentService } from 'vs/platform/environment/common/environment' ;
@@ -27,10 +28,9 @@ import { IEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/co
2728import { MergedEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableCollection' ;
2829import { deserializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared' ;
2930import * as terminal from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel' ;
30- import { IShellLaunchConfig , ITerminalEnvironment , ITerminalLaunchError } from 'vs/workbench/contrib/terminal/common/terminal' ;
31+ import { IShellLaunchConfig , ITerminalEnvironment , ITerminalLaunchError , ITerminalsLayoutInfo } from 'vs/workbench/contrib/terminal/common/terminal' ;
3132import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering' ;
3233import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment' ;
33- import { getSystemShell } from 'vs/base/node/shell' ;
3434import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment' ;
3535import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess' ;
3636import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/common/variableResolver' ;
@@ -611,6 +611,22 @@ class Terminal {
611611 this . rows = rows ;
612612 return this . process . resize ( cols , rows ) ;
613613 }
614+
615+ /**
616+ * Serializable terminal information that can be sent to the client.
617+ */
618+ public async description ( id : number ) : Promise < terminal . IRemoteTerminalDescriptionDto > {
619+ const cwd = await this . getCwd ( ) ;
620+ return {
621+ id,
622+ pid : this . pid ,
623+ title : this . title ,
624+ cwd,
625+ workspaceId : this . workspaceId ,
626+ workspaceName : this . workspaceName ,
627+ isOrphan : this . isOrphan ,
628+ } ;
629+ }
614630}
615631
616632// References: - ../../workbench/api/node/extHostTerminalService.ts
@@ -619,6 +635,8 @@ export class TerminalProviderChannel implements IServerChannel<RemoteAgentConnec
619635 private readonly terminals = new Map < number , Terminal > ( ) ;
620636 private id = 0 ;
621637
638+ private readonly layouts = new Map < string , terminal . ISetTerminalLayoutInfoArgs > ( ) ;
639+
622640 public constructor ( private readonly logService : ILogService ) {
623641
624642 }
@@ -647,6 +665,8 @@ export class TerminalProviderChannel implements IServerChannel<RemoteAgentConnec
647665 case '$sendCommandResultToTerminalProcess' : return this . sendCommandResultToTerminalProcess ( args ) ;
648666 case '$orphanQuestionReply' : return this . orphanQuestionReply ( args [ 0 ] ) ;
649667 case '$listTerminals' : return this . listTerminals ( args [ 0 ] ) ;
668+ case '$setTerminalLayoutInfo' : return this . setTerminalLayoutInfo ( args ) ;
669+ case '$getTerminalLayoutInfo' : return this . getTerminalLayoutInfo ( args ) ;
650670 }
651671
652672 throw new Error ( `Invalid call '${ command } '` ) ;
@@ -839,24 +859,53 @@ export class TerminalProviderChannel implements IServerChannel<RemoteAgentConnec
839859 // do differently. Maybe it's to reset the terminal dispose timeouts or
840860 // something like that, but why not do it each time you list?
841861 const terminals = await Promise . all ( Array . from ( this . terminals ) . map ( async ( [ id , terminal ] ) => {
842- const cwd = await terminal . getCwd ( ) ;
843- return {
844- id,
845- pid : terminal . pid ,
846- title : terminal . title ,
847- cwd,
848- workspaceId : terminal . workspaceId ,
849- workspaceName : terminal . workspaceName ,
850- isOrphan : terminal . isOrphan ,
851- } ;
862+ return terminal . description ( id ) ;
852863 } ) ) ;
864+
853865 // Only returned orphaned terminals so we don't end up attaching to
854866 // terminals already attached elsewhere.
855867 return terminals . filter ( ( t ) => t . isOrphan ) ;
856868 }
869+
870+ public async setTerminalLayoutInfo ( args : terminal . ISetTerminalLayoutInfoArgs ) : Promise < void > {
871+ this . layouts . set ( args . workspaceId , args ) ;
872+ }
873+
874+ public async getTerminalLayoutInfo ( args : terminal . IGetTerminalLayoutInfoArgs ) : Promise < ITerminalsLayoutInfo | undefined > {
875+ const layout = this . layouts . get ( args . workspaceId ) ;
876+ if ( ! layout ) {
877+ return undefined ;
878+ }
879+
880+ const tabs = await Promise . all ( layout . tabs . map ( async ( tab ) => {
881+ // The terminals are stored by ID so look them up.
882+ const terminals = await Promise . all ( tab . terminals . map ( async ( t ) => {
883+ const terminal = this . terminals . get ( t . terminal ) ;
884+ if ( ! terminal ) {
885+ return undefined ;
886+ }
887+ return {
888+ ...t ,
889+ terminal : await terminal . description ( t . terminal ) ,
890+ } ;
891+ } ) ) ;
892+
893+ return {
894+ ...tab ,
895+ // Filter out terminals that have been killed.
896+ terminals : terminals . filter ( isDefined ) ,
897+ } ;
898+ } ) ) ;
899+
900+ return { tabs } ;
901+ }
857902}
858903
859904function transformIncoming ( remoteAuthority : string , uri : UriComponents | undefined ) : URI | undefined {
860905 const transformer = getUriTransformer ( remoteAuthority ) ;
861906 return uri ? URI . revive ( transformer . transformIncoming ( uri ) ) : uri ;
862907}
908+
909+ function isDefined < T > ( t : T | undefined ) : t is T {
910+ return typeof t !== "undefined" ;
911+ }
0 commit comments