mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-12 11:39:57 +01:00
try to detect terminal encoding when reading from stdin (for #6161)
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
import stream = require('vs/base/node/stream');
|
||||
import iconv = require('iconv-lite');
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import { exec } from 'child_process';
|
||||
|
||||
export const UTF8 = 'utf8';
|
||||
export const UTF8_with_bom = 'utf8bom';
|
||||
@@ -165,3 +167,46 @@ export function toCanonicalName(enc: string): string {
|
||||
return enc;
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveTerminalEncoding(verbose?: boolean): TPromise<string> {
|
||||
let rawEncodingPromise: TPromise<string>;
|
||||
|
||||
// Support a global environment variable to win over other mechanics
|
||||
const cliEncodingEnv = process.env['VSCODE_CLI_ENCODING'];
|
||||
if (cliEncodingEnv) {
|
||||
rawEncodingPromise = TPromise.as(cliEncodingEnv);
|
||||
}
|
||||
|
||||
// Linux/Mac: use "locale charmap" command
|
||||
else if (isLinux || isMacintosh) {
|
||||
rawEncodingPromise = new TPromise<string>(c => {
|
||||
if (verbose) {
|
||||
console.log('Running "locale charmap" to detect terminal encoding...');
|
||||
}
|
||||
|
||||
exec('locale charmap', (err, stdout, stderr) => c(stdout));
|
||||
});
|
||||
}
|
||||
|
||||
// Windows: educated guess
|
||||
else {
|
||||
rawEncodingPromise = TPromise.as('cp850');
|
||||
}
|
||||
|
||||
return rawEncodingPromise.then(rawEncoding => {
|
||||
if (verbose) {
|
||||
console.log(`Detected raw terminal encoding: ${rawEncoding}`);
|
||||
}
|
||||
|
||||
if (!rawEncoding || rawEncoding.toLowerCase() === 'utf-8' || rawEncoding.toLowerCase() === UTF8) {
|
||||
return UTF8;
|
||||
}
|
||||
|
||||
const iconvEncoding = toIconvLiteEncoding(rawEncoding);
|
||||
if (iconv.encodingExists(iconvEncoding)) {
|
||||
return iconvEncoding;
|
||||
}
|
||||
|
||||
return UTF8;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import assert = require('assert');
|
||||
|
||||
import encoding = require('vs/base/node/encoding');
|
||||
import { encodingExists } from 'vs/base/node/encoding';
|
||||
|
||||
suite('Encoding', () => {
|
||||
test('detectBOM UTF-8', (done: (err?: any) => void) => {
|
||||
@@ -54,4 +55,21 @@ suite('Encoding', () => {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
test('resolve terminal encoding (detect)', function (done: (err?: any) => void) {
|
||||
encoding.resolveTerminalEncoding().then(encoding => {
|
||||
assert.ok(encodingExists(encoding));
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
test('resolve terminal encoding (environment)', function (done: (err?: any) => void) {
|
||||
process.env['VSCODE_CLI_ENCODING'] = 'utf16le';
|
||||
|
||||
encoding.resolveTerminalEncoding().then(encoding => {
|
||||
assert.ok(encodingExists(encoding));
|
||||
assert.equal(encoding, 'utf16le');
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,6 +15,8 @@ import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import { whenDeleted } from 'vs/base/node/pfs';
|
||||
import { findFreePort } from 'vs/base/node/ports';
|
||||
import { resolveTerminalEncoding } from 'vs/base/node/encoding';
|
||||
import * as iconv from 'iconv-lite';
|
||||
|
||||
function shouldSpawnCliProcess(argv: ParsedArgs): boolean {
|
||||
return !!argv['install-source']
|
||||
@@ -93,10 +95,13 @@ export async function main(argv: string[]): TPromise<any> {
|
||||
let stdinFileError: Error;
|
||||
stdinFilePath = paths.join(os.tmpdir(), `stdin-${Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 6)}.txt`);
|
||||
try {
|
||||
const stdinFileStream = fs.createWriteStream(stdinFilePath);
|
||||
resolveTerminalEncoding(verbose).done(encoding => {
|
||||
|
||||
// Pipe into tmp file
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.pipe(fs.createWriteStream(stdinFilePath));
|
||||
// Pipe into tmp file using terminals encoding
|
||||
const converterStream = iconv.decodeStream(encoding);
|
||||
process.stdin.pipe(converterStream).pipe(stdinFileStream);
|
||||
});
|
||||
|
||||
// Make sure to open tmp file
|
||||
argv.push(stdinFilePath);
|
||||
|
||||
Reference in New Issue
Block a user