sussudio
Version:
An unofficial VS Code Internal API
152 lines (151 loc) • 5.69 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { timeout } from "../../../base/common/async.mjs";
import { debounce } from "../../../base/common/decorators.mjs";
import { Emitter } from "../../../base/common/event.mjs";
import { Disposable } from "../../../base/common/lifecycle.mjs";
import { isWindows, platform } from "../../../base/common/platform.mjs";
const SHELL_EXECUTABLES = [
'cmd.exe',
'powershell.exe',
'pwsh.exe',
'bash.exe',
'wsl.exe',
'ubuntu.exe',
'ubuntu1804.exe',
'kali.exe',
'debian.exe',
'opensuse-42.exe',
'sles-12.exe'
];
let windowsProcessTree;
export class WindowsShellHelper extends Disposable {
_rootProcessId;
_isDisposed;
_currentRequest;
_shellType;
get shellType() { return this._shellType; }
_shellTitle = '';
get shellTitle() { return this._shellTitle; }
_onShellNameChanged = new Emitter();
get onShellNameChanged() { return this._onShellNameChanged.event; }
_onShellTypeChanged = new Emitter();
get onShellTypeChanged() { return this._onShellTypeChanged.event; }
constructor(_rootProcessId) {
super();
this._rootProcessId = _rootProcessId;
if (!isWindows) {
throw new Error(`WindowsShellHelper cannot be instantiated on ${platform}`);
}
this._isDisposed = false;
this._startMonitoringShell();
}
async _startMonitoringShell() {
if (this._isDisposed) {
return;
}
this.checkShell();
}
async checkShell() {
if (isWindows) {
// Wait to give the shell some time to actually launch a process, this
// could lead to a race condition but it would be recovered from when
// data stops and should cover the majority of cases
await timeout(300);
this.getShellName().then(title => {
const type = this.getShellType(title);
if (type !== this._shellType) {
this._onShellTypeChanged.fire(type);
this._onShellNameChanged.fire(title);
this._shellType = type;
this._shellTitle = title;
}
});
}
}
traverseTree(tree) {
if (!tree) {
return '';
}
if (SHELL_EXECUTABLES.indexOf(tree.name) === -1) {
return tree.name;
}
if (!tree.children || tree.children.length === 0) {
return tree.name;
}
let favouriteChild = 0;
for (; favouriteChild < tree.children.length; favouriteChild++) {
const child = tree.children[favouriteChild];
if (!child.children || child.children.length === 0) {
break;
}
if (child.children[0].name !== 'conhost.exe') {
break;
}
}
if (favouriteChild >= tree.children.length) {
return tree.name;
}
return this.traverseTree(tree.children[favouriteChild]);
}
dispose() {
this._isDisposed = true;
super.dispose();
}
/**
* Returns the innermost shell executable running in the terminal
*/
async getShellName() {
if (this._isDisposed) {
return Promise.resolve('');
}
// Prevent multiple requests at once, instead return current request
if (this._currentRequest) {
return this._currentRequest;
}
if (!windowsProcessTree) {
windowsProcessTree = await import('windows-process-tree');
}
this._currentRequest = new Promise(resolve => {
windowsProcessTree.getProcessTree(this._rootProcessId, tree => {
const name = this.traverseTree(tree);
this._currentRequest = undefined;
resolve(name);
});
});
return this._currentRequest;
}
getShellType(executable) {
switch (executable.toLowerCase()) {
case 'cmd.exe':
return "cmd" /* WindowsShellType.CommandPrompt */;
case 'powershell.exe':
case 'pwsh.exe':
return "pwsh" /* WindowsShellType.PowerShell */;
case 'bash.exe':
case 'git-cmd.exe':
return "gitbash" /* WindowsShellType.GitBash */;
case 'wsl.exe':
case 'ubuntu.exe':
case 'ubuntu1804.exe':
case 'kali.exe':
case 'debian.exe':
case 'opensuse-42.exe':
case 'sles-12.exe':
return "wsl" /* WindowsShellType.Wsl */;
default:
return undefined;
}
}
}
__decorate([
debounce(500)
], WindowsShellHelper.prototype, "checkShell", null);