argv.ts 9.1 KB
Newer Older
J
Joao Moreno 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

J
Joao Moreno 已提交
6
import * as os from 'os';
J
Joao Moreno 已提交
7
import * as minimist from 'minimist';
J
Joao Moreno 已提交
8
import * as assert from 'assert';
J
Joao Moreno 已提交
9
import { firstIndex } from 'vs/base/common/arrays';
J
Joao Moreno 已提交
10
import { localize } from 'vs/nls';
J
Joao Moreno 已提交
11
import { ParsedArgs } from '../common/environment';
12 13
import { isWindows } from 'vs/base/common/platform';
import product from 'vs/platform/node/product';
14
import { MIN_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files';
J
Joao Moreno 已提交
15

J
Joao Moreno 已提交
16
const options: minimist.Opts = {
17 18
	string: [
		'locale',
J
Joao Moreno 已提交
19
		'user-data-dir',
20
		'extensions-dir',
21
		'folder-uri',
22
		'file-uri',
J
Joao Moreno 已提交
23 24
		'extensionDevelopmentPath',
		'extensionTestsPath',
J
Joao Moreno 已提交
25
		'install-extension',
S
Sandeep Somavarapu 已提交
26
		'disable-extension',
27
		'uninstall-extension',
28
		'debugId',
J
Joao Moreno 已提交
29
		'debugPluginHost',
30
		'debugBrkPluginHost',
31 32
		'debugSearch',
		'debugBrkSearch',
33
		'enable-proposed-api',
34
		'export-default-configuration',
35
		'install-source',
36 37
		'upload-logs',
		'driver'
38 39 40 41 42 43
	],
	boolean: [
		'help',
		'version',
		'wait',
		'diff',
44
		'add',
45 46
		'goto',
		'new-window',
47
		'unity-launch',
J
Joao Moreno 已提交
48
		'reuse-window',
D
Fixes  
Daniel Imms 已提交
49
		'open-url',
J
Joao Moreno 已提交
50
		'performance',
J
Johannes Rieken 已提交
51
		'prof-startup',
J
Joao Moreno 已提交
52 53
		'verbose',
		'logExtensionHostCommunication',
J
Joao Moreno 已提交
54
		'disable-extensions',
G
greams 已提交
55
		'list-extensions',
B
Benjamin Pasero 已提交
56
		'show-versions',
57
		'nolazy',
58
		'issue',
59
		'skip-getting-started',
60
		'skip-release-notes',
61
		'sticky-quickopen',
B
Benjamin Pasero 已提交
62
		'disable-restore-windows',
J
Joao Moreno 已提交
63
		'disable-telemetry',
64
		'disable-updates',
65
		'disable-crash-reporter',
B
Benjamin Pasero 已提交
66
		'skip-add-to-recently-opened',
67
		'status',
B
Benjamin Pasero 已提交
68
		'file-write',
69 70
		'file-chmod',
		'driver-verbose'
71
	],
J
Joao Moreno 已提交
72
	alias: {
73
		add: 'a',
J
Joao Moreno 已提交
74 75
		help: 'h',
		version: 'v',
76 77 78
		wait: 'w',
		diff: 'd',
		goto: 'g',
79
		status: 's',
80
		'new-window': 'n',
J
Joao Moreno 已提交
81 82
		'reuse-window': 'r',
		performance: 'p',
83
		'disable-extensions': 'disableExtensions',
84 85 86
		'extensions-dir': 'extensionHomePath',
		'debugPluginHost': 'inspect-extensions',
		'debugBrkPluginHost': 'inspect-brk-extensions',
87 88
		'debugSearch': 'inspect-search',
		'debugBrkSearch': 'inspect-brk-search',
J
Joao Moreno 已提交
89
	}
J
Joao Moreno 已提交
90
};
J
Joao Moreno 已提交
91

J
Joao Moreno 已提交
92 93
function validate(args: ParsedArgs): ParsedArgs {
	if (args.goto) {
94
		args._.forEach(arg => assert(/^(\w:)?[^:]+(:\d*){0,2}$/.test(arg), localize('gotoValidation', "Arguments in `--goto` mode should be in the format of `FILE(:LINE(:CHARACTER))`.")));
J
Joao Moreno 已提交
95 96
	}

97 98 99 100
	if (args['max-memory']) {
		assert(args['max-memory'] >= MIN_MAX_MEMORY_SIZE_MB, `The max-memory argument cannot be specified lower than ${MIN_MAX_MEMORY_SIZE_MB} MB.`);
	}

J
Joao Moreno 已提交
101 102 103 104 105 106 107 108 109
	return args;
}

function stripAppPath(argv: string[]): string[] {
	const index = firstIndex(argv, a => !/^-/.test(a));

	if (index > -1) {
		return [...argv.slice(0, index), ...argv.slice(index + 1)];
	}
M
Matt Bierner 已提交
110
	return undefined;
J
Joao Moreno 已提交
111 112
}

J
Joao Moreno 已提交
113 114 115 116
/**
 * Use this to parse raw code process.argv such as: `Electron . --verbose --wait`
 */
export function parseMainProcessArgv(processArgv: string[]): ParsedArgs {
J
Joao Moreno 已提交
117
	let [, ...args] = processArgv;
J
Joao Moreno 已提交
118 119 120

	// If dev, remove the first non-option argument: it's the app location
	if (process.env['VSCODE_DEV']) {
J
Joao Moreno 已提交
121 122 123 124 125
		args = stripAppPath(args);
	}

	return validate(parseArgs(args));
}
J
Joao Moreno 已提交
126

J
Joao Moreno 已提交
127 128 129 130
/**
 * Use this to parse raw code CLI process.argv such as: `Electron cli.js . --verbose --wait`
 */
export function parseCLIProcessArgv(processArgv: string[]): ParsedArgs {
J
Johannes Rieken 已提交
131
	let [, , ...args] = processArgv;
J
Joao Moreno 已提交
132 133 134

	if (process.env['VSCODE_DEV']) {
		args = stripAppPath(args);
J
Joao Moreno 已提交
135 136
	}

J
Joao Moreno 已提交
137
	return validate(parseArgs(args));
J
Joao Moreno 已提交
138 139 140 141 142
}

/**
 * Use this to parse code arguments such as `--verbose --wait`
 */
B
Benjamin Pasero 已提交
143
export function parseArgs(args: string[]): ParsedArgs {
144
	return minimist(args, options) as ParsedArgs;
J
Joao Moreno 已提交
145 146
}

B
Benjamin Pasero 已提交
147
const optionsHelp: { [name: string]: string; } = {
B
Benjamin Pasero 已提交
148 149 150
	'-d, --diff <file> <file>': localize('diff', "Compare two files with each other."),
	'-a, --add <dir>': localize('add', "Add folder(s) to the last active window."),
	'-g, --goto <file:line[:character]>': localize('goto', "Open a file at the path on the specified line and character position."),
B
Benjamin Pasero 已提交
151
	'-n, --new-window': localize('newWindow', "Force to open a new window."),
B
Benjamin Pasero 已提交
152
	'-r, --reuse-window': localize('reuseWindow', "Force to open a file or folder in an already opened window."),
153
	'-w, --wait': localize('wait', "Wait for the files to be closed before returning."),
B
Benjamin Pasero 已提交
154
	'--locale <locale>': localize('locale', "The locale to use (e.g. en-US or zh-TW)."),
B
wording  
Benjamin Pasero 已提交
155
	'--user-data-dir <dir>': localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code."),
B
Benjamin Pasero 已提交
156
	'-v, --version': localize('version', "Print version."),
157 158 159
	'-h, --help': localize('help', "Print usage."),
	'--folder-uri <uri>': localize('folder uri', "Opens a window with given folder uri(s)"),
	'--file-uri <uri>': localize('file uri', "Opens a window with given file uri(s)")
B
Benjamin Pasero 已提交
160 161 162
};

const extensionsHelp: { [name: string]: string; } = {
163
	'--extensions-dir <dir>': localize('extensionHomePath', "Set the root path for extensions."),
J
Joao Moreno 已提交
164
	'--list-extensions': localize('listExtensions', "List the installed extensions."),
J
Joao Moreno 已提交
165
	'--show-versions': localize('showVersions', "Show versions of installed extensions, when using --list-extension."),
J
Joao 已提交
166
	'--install-extension (<extension-id> | <extension-vsix-path>)': localize('installExtension', "Installs an extension."),
167
	'--uninstall-extension (<extension-id> | <extension-vsix-path>)': localize('uninstallExtension', "Uninstalls an extension."),
168
	'--enable-proposed-api (<extension-id>)': localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.")
B
Benjamin Pasero 已提交
169 170 171 172 173
};

const troubleshootingHelp: { [name: string]: string; } = {
	'--verbose': localize('verbose', "Print verbose output (implies --wait)."),
	'--log <level>': localize('log', "Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'."),
174
	'-s, --status': localize('status', "Print process usage and diagnostics information."),
B
Benjamin Pasero 已提交
175 176 177
	'-p, --performance': localize('performance', "Start with the 'Developer: Startup Performance' command enabled."),
	'--prof-startup': localize('prof-startup', "Run CPU profiler during startup"),
	'--disable-extensions': localize('disableExtensions', "Disable all installed extensions."),
S
Sandeep Somavarapu 已提交
178
	'--disable-extension <extension-id>': localize('disableExtension', "Disable an extension."),
B
Benjamin Pasero 已提交
179 180
	'--inspect-extensions': localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection URI."),
	'--inspect-brk-extensions': localize('inspect-brk-extensions', "Allow debugging and profiling of extensions with the extension host being paused after start. Check the developer tools for the connection URI."),
181
	'--disable-gpu': localize('disableGPU', "Disable GPU hardware acceleration."),
182
	'--upload-logs': localize('uploadLogs', "Uploads logs from current session to a secure endpoint."),
P
Peng Lyu 已提交
183
	'--max-memory': localize('maxMemory', "Max memory size for a window (in Mbytes).")
J
Joao Moreno 已提交
184 185
};

D
Daniel Imms 已提交
186 187 188 189 190
export function formatOptions(options: { [name: string]: string; }, columns: number): string {
	let keys = Object.keys(options);
	let argLength = Math.max.apply(null, keys.map(k => k.length)) + 2/*left padding*/ + 1/*right padding*/;
	if (columns - argLength < 25) {
		// Use a condensed version on narrow terminals
J
Johannes Rieken 已提交
191
		return keys.reduce((r, key) => r.concat([`  ${key}`, `      ${options[key]}`]), []).join('\n');
D
Daniel Imms 已提交
192 193 194 195 196
	}
	let descriptionColumns = columns - argLength - 1;
	let result = '';
	keys.forEach(k => {
		let wrappedDescription = wrapText(options[k], descriptionColumns);
D
Daniel Imms 已提交
197 198 199 200 201
		let keyPadding = (<any>' ').repeat(argLength - k.length - 2/*left padding*/);
		if (result.length > 0) {
			result += '\n';
		}
		result += '  ' + k + keyPadding + wrappedDescription[0];
202
		for (let i = 1; i < wrappedDescription.length; i++) {
D
Daniel Imms 已提交
203
			result += '\n' + (<any>' ').repeat(argLength) + wrappedDescription[i];
D
Daniel Imms 已提交
204 205 206
		}
	});
	return result;
J
Joao Moreno 已提交
207 208
}

J
Johannes Rieken 已提交
209
function wrapText(text: string, columns: number): string[] {
B
Benjamin Pasero 已提交
210
	let lines: string[] = [];
D
Daniel Imms 已提交
211 212
	while (text.length) {
		let index = text.length < columns ? text.length : text.lastIndexOf(' ', columns);
D
Daniel Imms 已提交
213
		let line = text.slice(0, index).trim();
D
Daniel Imms 已提交
214 215 216 217 218 219
		text = text.slice(index);
		lines.push(line);
	}
	return lines;
}

J
Joao Moreno 已提交
220 221
export function buildHelpMessage(fullName: string, name: string, version: string): string {
	const columns = (<any>process.stdout).isTTY ? (<any>process.stdout).columns : 80;
J
Johannes Rieken 已提交
222
	const executable = `${name}${os.platform() === 'win32' ? '.exe' : ''}`;
D
Daniel Imms 已提交
223

J
Johannes Rieken 已提交
224
	return `${fullName} ${version}
J
Joao Moreno 已提交
225

J
Johannes Rieken 已提交
226
${ localize('usage', "Usage")}: ${executable} [${localize('options', "options")}] [${localize('paths', 'paths')}...]
J
Joao Moreno 已提交
227

228 229
${ isWindows ? localize('stdinWindows', "To read output from another program, append '-' (e.g. 'echo Hello World | {0} -')", product.applicationName) : localize('stdinUnix', "To read from stdin, append '-' (e.g. 'ps aux | grep code | {0} -')", product.applicationName)}

J
Johannes Rieken 已提交
230
${ localize('optionsUpperCase', "Options")}:
B
Benjamin Pasero 已提交
231 232 233 234 235 236 237
${formatOptions(optionsHelp, columns)}

${ localize('extensionsManagement', "Extensions Management")}:
${formatOptions(extensionsHelp, columns)}

${ localize('troubleshooting', "Troubleshooting")}:
${formatOptions(troubleshootingHelp, columns)}`;
238
}