forked from DonJayamanne/pythonVSCode
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathbaseShellDetector.ts
81 lines (72 loc) · 3.21 KB
/
baseShellDetector.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
'use strict';
import { injectable, unmanaged } from 'inversify';
import { Terminal } from 'vscode';
import { traceVerbose } from '../../../logging';
import { IShellDetector, ShellIdentificationTelemetry, TerminalShellType } from '../types';
/*
When identifying the shell use the following algorithm:
* 1. Identify shell based on the name of the terminal (if there is one already opened and used).
* 2. Identify shell based on the api provided by VSC.
* 2. Identify shell based on the settings in VSC.
* 3. Identify shell based on users environment variables.
* 4. Use default shells (bash for mac and linux, cmd for windows).
*/
// Types of shells can be found here:
// 1. https://wiki.ubuntu.com/ChangingShells
const IS_GITBASH = /(gitbash$)/i;
const IS_BASH = /(bash$)/i;
const IS_WSL = /(wsl$)/i;
const IS_ZSH = /(zsh$)/i;
const IS_KSH = /(ksh$)/i;
const IS_COMMAND = /(cmd$)/i;
const IS_POWERSHELL = /(powershell$)/i;
const IS_POWERSHELL_CORE = /(pwsh$)/i;
const IS_FISH = /(fish$)/i;
const IS_CSHELL = /(csh$)/i;
const IS_TCSHELL = /(tcsh$)/i;
const IS_NUSHELL = /(nu$)/i;
const IS_XONSH = /(xonsh$)/i;
const detectableShells = new Map<TerminalShellType, RegExp>();
detectableShells.set(TerminalShellType.powershell, IS_POWERSHELL);
detectableShells.set(TerminalShellType.gitbash, IS_GITBASH);
detectableShells.set(TerminalShellType.bash, IS_BASH);
detectableShells.set(TerminalShellType.wsl, IS_WSL);
detectableShells.set(TerminalShellType.zsh, IS_ZSH);
detectableShells.set(TerminalShellType.ksh, IS_KSH);
detectableShells.set(TerminalShellType.commandPrompt, IS_COMMAND);
detectableShells.set(TerminalShellType.fish, IS_FISH);
detectableShells.set(TerminalShellType.tcshell, IS_TCSHELL);
detectableShells.set(TerminalShellType.cshell, IS_CSHELL);
detectableShells.set(TerminalShellType.nushell, IS_NUSHELL);
detectableShells.set(TerminalShellType.powershellCore, IS_POWERSHELL_CORE);
detectableShells.set(TerminalShellType.xonsh, IS_XONSH);
@injectable()
export abstract class BaseShellDetector implements IShellDetector {
constructor(@unmanaged() public readonly priority: number) {}
public abstract identify(
telemetryProperties: ShellIdentificationTelemetry,
terminal?: Terminal,
): TerminalShellType | undefined;
public identifyShellFromShellPath(shellPath: string): TerminalShellType {
return identifyShellFromShellPath(shellPath);
}
}
export function identifyShellFromShellPath(shellPath: string): TerminalShellType {
// Remove .exe extension so shells can be more consistently detected
// on Windows (including Cygwin).
const basePath = shellPath.replace(/\.exe$/, '');
const shell = Array.from(detectableShells.keys()).reduce((matchedShell, shellToDetect) => {
if (matchedShell === TerminalShellType.other) {
const pat = detectableShells.get(shellToDetect);
if (pat && pat.test(basePath)) {
return shellToDetect;
}
}
return matchedShell;
}, TerminalShellType.other);
traceVerbose(`Shell path '${shellPath}', base path '${basePath}'`);
traceVerbose(`Shell path identified as shell '${shell}'`);
return shell;
}