Skip to content

Commit

Permalink
Keep terminal open when exited within 5 seconds
Browse files Browse the repository at this point in the history
  • Loading branch information
SchoofsKelvin committed Oct 24, 2021
1 parent 8de941f commit a57886a
Showing 1 changed file with 42 additions and 17 deletions.
59 changes: 42 additions & 17 deletions src/pseudoTerminal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as path from 'path';
import type { ClientChannel, PseudoTtyOptions } from "ssh2";
import type { Readable } from "stream";
import * as vscode from "vscode";
import { getFlagBoolean } from './config';
import type { Connection } from './connection';
Expand All @@ -17,7 +16,7 @@ export interface SSHPseudoTerminal extends vscode.Pseudoterminal {
onDidClose: vscode.Event<number>; // Redeclaring that it isn't undefined
onDidOpen: vscode.Event<void>;
handleInput(data: string): void; // We don't support/need read-only terminals for now
status: 'opening' | 'open' | 'closed';
status: 'opening' | 'open' | 'closed' | 'wait-to-close';
connection: Connection;
/** Could be undefined if it only gets created during psy.open() instead of beforehand */
channel?: ClientChannel;
Expand Down Expand Up @@ -151,14 +150,22 @@ export async function createTerminal(options: TerminalOptions): Promise<SSHPseud
onDidClose: onDidClose.event,
onDidOpen: onDidOpen.event,
close() {
const { channel } = pseudo;
if (!channel) return;
pseudo.status = 'closed';
channel.signal('INT');
channel.signal('SIGINT');
channel.write('\x03');
channel.close();
pseudo.channel = undefined;
const { channel, status } = pseudo;
if (status === 'closed') return;
if (channel) {
pseudo.status = 'closed';
channel.signal('INT');
channel.signal('SIGINT');
channel.write('\x03');
channel.close();
pseudo.channel = undefined;
}
if (status === 'wait-to-close') {
pseudo.terminal?.dispose();
pseudo.terminal = undefined;
pseudo.status = 'closed';
onDidClose.fire(0);
}
},
async open(dims) {
onDidWrite.fire(`Connecting to ${actualConfig.label || actualConfig.name}...\r\n`);
Expand Down Expand Up @@ -204,19 +211,36 @@ export async function createTerminal(options: TerminalOptions): Promise<SSHPseud
const channel = await toPromise<ClientChannel | undefined>(cb => client.exec(cmd, { pty: pseudoTtyOptions }, cb));
if (!channel) throw new Error('Could not create remote terminal');
pseudo.channel = channel;
channel.on('exit', onDidClose.fire);
channel.on('close', () => onDidClose.fire(0));
(channel as Readable).on('data', chunk => onDidWrite.fire(chunk.toString()));
// TODO: Keep track of stdout's color, switch to red, output, then switch back?
const startTime = Date.now();
channel.once('exit', (code, signal, _, description) => {
Logging.debug`Terminal session closed: ${{ code, signal, description, status: pseudo.status }}`;
if (code && (Date.now() < startTime + 1000) && !options.command) {
// Terminal failed within a second, let's keep it open for the user to see the error (if this isn't a task)
onDidWrite.fire(`Got error code ${code}${signal ? ` with signal ${signal}` : ''}\r\n`);
if (description) onDidWrite.fire(`Extra info: ${description}\r\n`);
onDidWrite.fire('Press a key to close the terminal\r\n');
onDidWrite.fire('Possible more stdout/stderr below:\r\n');
pseudo.status = 'wait-to-close';
} else {
onDidClose.fire(code || 0);
pseudo.status = 'closed';
}
});
channel.once('readable', () => {
// Inform others (e.g. createTaskTerminal) that the terminal is ready to be used
if (pseudo.status === 'opening') pseudo.status = 'open';
onDidOpen.fire();
});
channel.stdout.on('data', chunk => onDidWrite.fire(chunk.toString()));
channel.stderr.on('data', chunk => onDidWrite.fire(chunk.toString()));
// Inform others (e.g. createTaskTerminal) that the terminal is ready to be used
pseudo.status = 'open';
onDidOpen.fire();
// TODO: ^ Keep track of stdout's color, switch to red, output, then switch back?
} catch (e) {
Logging.error`Error starting SSH terminal:\n${e}`;
onDidWrite.fire(`Error starting SSH terminal:\r\n${e}\r\n`);
onDidClose.fire(1);
pseudo.status = 'closed';
pseudo.channel?.destroy();
pseudo.channel = undefined;
}
},
get terminal(): vscode.Terminal | undefined {
Expand All @@ -229,6 +253,7 @@ export async function createTerminal(options: TerminalOptions): Promise<SSHPseud
pseudo.channel?.setWindow(dims.rows, dims.columns, HEIGHT, WIDTH);
},
handleInput(data) {
if (pseudo.status === 'wait-to-close') return pseudo.close();
pseudo.channel?.write(data);
},
};
Expand Down

0 comments on commit a57886a

Please sign in to comment.