-
Notifications
You must be signed in to change notification settings - Fork 30.9k
/
Copy pathstdin.ts
87 lines (70 loc) · 2.89 KB
/
stdin.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
82
83
84
85
86
87
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
import { tmpdir } from 'os';
import { Queue } from '../../../base/common/async.js';
import { randomPath } from '../../../base/common/extpath.js';
import { resolveTerminalEncoding } from '../../../base/node/terminalEncoding.js';
export function hasStdinWithoutTty() {
try {
return !process.stdin.isTTY; // Via https://twitter.com/MylesBorins/status/782009479382626304
} catch (error) {
// Windows workaround for https://github.com/nodejs/node/issues/11656
}
return false;
}
export function stdinDataListener(durationinMs: number): Promise<boolean> {
return new Promise(resolve => {
const dataListener = () => resolve(true);
// wait for 1s maximum...
setTimeout(() => {
process.stdin.removeListener('data', dataListener);
resolve(false);
}, durationinMs);
// ...but finish early if we detect data
process.stdin.once('data', dataListener);
});
}
export function getStdinFilePath(): string {
return randomPath(tmpdir(), 'code-stdin', 3);
}
async function createStdInFile(targetPath: string) {
await fs.promises.appendFile(targetPath, '');
await fs.promises.chmod(targetPath, 0o600); // Ensure the file is only read/writable by the user: https://github.com/microsoft/vscode-remote-release/issues/9048
}
export async function readFromStdin(targetPath: string, verbose: boolean, onEnd?: Function): Promise<void> {
let [encoding, iconv] = await Promise.all([
resolveTerminalEncoding(verbose), // respect terminal encoding when piping into file
import('@vscode/iconv-lite-umd'), // lazy load encoding module for usage
createStdInFile(targetPath) // make sure file exists right away (https://github.com/microsoft/vscode/issues/155341)
]);
if (!iconv.default.encodingExists(encoding)) {
console.log(`Unsupported terminal encoding: ${encoding}, falling back to UTF-8.`);
encoding = 'utf8';
}
// Use a `Queue` to be able to use `appendFile`
// which helps file watchers to be aware of the
// changes because each append closes the underlying
// file descriptor.
// (https://github.com/microsoft/vscode/issues/148952)
const appendFileQueue = new Queue();
const decoder = iconv.default.getDecoder(encoding);
process.stdin.on('data', chunk => {
const chunkStr = decoder.write(chunk);
appendFileQueue.queue(() => fs.promises.appendFile(targetPath, chunkStr));
});
process.stdin.on('end', () => {
const end = decoder.end();
appendFileQueue.queue(async () => {
try {
if (typeof end === 'string') {
await fs.promises.appendFile(targetPath, end);
}
} finally {
onEnd?.();
}
});
});
}