Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve when $LANG is set and expand the number of languages supported #80830

Merged
merged 7 commits into from
Sep 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/vs/workbench/api/node/extHostTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
this._variableResolver,
isWorkspaceShellAllowed,
pkg.version,
terminalConfig.get<boolean>('setLocaleVariables', false),
terminalConfig.get<'auto' | 'off' | 'on'>('detectLocale', 'auto'),
baseEnv
);

Expand Down
14 changes: 10 additions & 4 deletions src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,16 @@ configurationRegistry.registerConfiguration({
type: 'number',
default: 1000
},
'terminal.integrated.setLocaleVariables': {
markdownDescription: nls.localize('terminal.integrated.setLocaleVariables', "Controls whether locale variables are set at startup of the terminal."),
type: 'boolean',
default: true
'terminal.integrated.detectLocale': {
markdownDescription: nls.localize('terminal.integrated.detectLocale', "Controls whether to detect and set the `$LANG` environment variable to a UTF-8 compliant option since VS Code's terminal only supports UTF-8 encoded data coming from the shell."),
type: 'string',
enum: ['auto', 'off', 'on'],
enumDescriptions: [
nls.localize('terminal.integrated.detectLocale.auto', "Set the `$LANG` environment variable if the existing variable does not exist or it does not end in `'.UTF-8'`."),
nls.localize('terminal.integrated.detectLocale.off', "Do not set the `$LANG` environment variable."),
nls.localize('terminal.integrated.detectLocale.on', "Always set the `$LANG` environment variable.")
],
default: 'auto'
},
'terminal.integrated.rendererType': {
type: 'string',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
const isWorkspaceShellAllowed = this._configHelper.checkWorkspaceShellPermissions();
this._configHelper.showRecommendations(shellLaunchConfig);
const baseEnv = this._configHelper.config.inheritEnv ? processEnv : await this._terminalInstanceService.getMainProcessParentEnv();
const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, lastActiveWorkspace, envFromConfigValue, this._configurationResolverService, isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.setLocaleVariables, baseEnv);
const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, lastActiveWorkspace, envFromConfigValue, this._configurationResolverService, isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.detectLocale, baseEnv);

const useConpty = this._configHelper.config.windowsEnableConpty && !isScreenReaderModeEnabled;
return this._terminalInstanceService.createTerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, useConpty);
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/contrib/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export interface ITerminalConfiguration {
fontSize: number;
letterSpacing: number;
lineHeight: number;
setLocaleVariables: boolean;
detectLocale: 'auto' | 'off' | 'on';
scrollback: number;
commandsToSkipShell: string[];
cwd: string;
Expand Down
72 changes: 61 additions & 11 deletions src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ function _mergeEnvironmentValue(env: ITerminalEnvironment, key: string, value: s
}
}

export function addTerminalEnvironmentKeys(env: platform.IProcessEnvironment, version: string | undefined, locale: string | undefined, setLocaleVariables: boolean): void {
export function addTerminalEnvironmentKeys(env: platform.IProcessEnvironment, version: string | undefined, locale: string | undefined, detectLocale: 'auto' | 'off' | 'on'): void {
env['TERM_PROGRAM'] = 'vscode';
if (version) {
env['TERM_PROGRAM_VERSION'] = version;
}
if (setLocaleVariables) {
env['LANG'] = _getLangEnvVariable(locale);
if (shouldSetLangEnvVariable(env, detectLocale)) {
env['LANG'] = getLangEnvVariable(locale);
}
env['COLORTERM'] = 'truecolor';
}
Expand Down Expand Up @@ -88,37 +88,87 @@ function resolveConfigurationVariables(configurationResolverService: IConfigurat
return env;
}

function _getLangEnvVariable(locale?: string) {
export function shouldSetLangEnvVariable(env: platform.IProcessEnvironment, detectLocale: 'auto' | 'off' | 'on'): boolean {
if (detectLocale === 'on') {
return true;
}
if (detectLocale === 'auto') {
return !env['LANG'] || env['LANG'].search(/\.UTF\-8$/) === -1;
}
return false; // 'off'
}

export function getLangEnvVariable(locale?: string): string {
const parts = locale ? locale.split('-') : [];
const n = parts.length;
if (n === 0) {
// Fallback to en_US to prevent possible encoding issues.
// Fallback to en_US if the locale is unknown
return 'en_US.UTF-8';
}
if (n === 1) {
// app.getLocale can return just a language without a variant, fill in the variant for
// supported languages as many shells expect a 2-part locale.
// The local may only contain the language, not the variant, if this is the case guess the
// variant such that it can be used as a valid $LANG variable. The language variant chosen
// is the original and/or most prominent with help from
// https://stackoverflow.com/a/2502675/1156119
// The list of locales was generated by running `locale -a` on macOS
const languageVariants: { [key: string]: string } = {
af: 'ZA',
am: 'ET',
be: 'BY',
bg: 'BG',
ca: 'ES',
cs: 'CZ',
da: 'DK',
// de: 'AT',
// de: 'CH',
de: 'DE',
el: 'GR',
// en: 'AU',
// en: 'CA',
// en: 'GB',
// en: 'IE',
// en: 'NZ',
en: 'US',
es: 'ES',
et: 'EE',
eu: 'ES',
fi: 'FI',
// fr: 'BE',
// fr: 'CA',
// fr: 'CH',
fr: 'FR',
he: 'IL',
hr: 'HR',
hu: 'HU',
hy: 'AM',
is: 'IS',
// it: 'CH',
it: 'IT',
ja: 'JP',
kk: 'KZ',
ko: 'KR',
lt: 'LT',
// nl: 'BE',
nl: 'NL',
no: 'NO',
pl: 'PL',
pt: 'BR',
// pt: 'PT',
ro: 'RO',
ru: 'RU',
sk: 'SK',
zh: 'CN'
sl: 'SI',
sr: 'YU',
sv: 'SE',
tr: 'TR',
uk: 'UA',
zh: 'CN',
};
if (parts[0] in languageVariants) {
parts.push(languageVariants[parts[0]]);
}
} else {
// Ensure the variant is uppercase
// Ensure the variant is uppercase to be a valid $LANG
parts[1] = parts[1].toUpperCase();
}
return parts.join('_') + '.UTF-8';
Expand Down Expand Up @@ -294,7 +344,7 @@ export function createTerminalEnvironment(
configurationResolverService: IConfigurationResolverService | undefined,
isWorkspaceShellAllowed: boolean,
version: string | undefined,
setLocaleVariables: boolean,
detectLocale: 'auto' | 'off' | 'on',
baseEnv: platform.IProcessEnvironment
): platform.IProcessEnvironment {
// Create a terminal environment based on settings, launch config and permissions
Expand Down Expand Up @@ -329,7 +379,7 @@ export function createTerminalEnvironment(
mergeEnvironments(env, shellLaunchConfig.env);

// Adding other env keys necessary to create the process
addTerminalEnvironmentKeys(env, version, platform.locale, setLocaleVariables);
addTerminalEnvironmentKeys(env, version, platform.locale, detectLocale);
}
return env;
}
Loading