mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge pull request #80560 from microsoft/aeschli/optiondescriptions
optionDescriptions as parameter of parseArgs
This commit is contained in:
@@ -11,7 +11,7 @@ import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, R
|
||||
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, getTitleBarStyle } from 'vs/platform/windows/common/windows';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -574,7 +574,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
windowConfiguration.partsSplashPath = path.join(this.environmentService.userDataPath, 'rapid_render.json');
|
||||
|
||||
// Config (combination of process.argv and window configuration)
|
||||
const environment = parseArgs(process.argv);
|
||||
const environment = parseArgs(process.argv, OPTIONS);
|
||||
const config = objects.assign(environment, windowConfiguration);
|
||||
for (const key in config) {
|
||||
const configValue = (config as any)[key];
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { spawn, ChildProcess, SpawnOptions } from 'child_process';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { buildHelpMessage, buildVersionMessage, addArg, createWaitMarkerFile } from 'vs/platform/environment/node/argv';
|
||||
import { buildHelpMessage, buildVersionMessage, addArg, createWaitMarkerFile, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { parseCLIProcessArgv } from 'vs/platform/environment/node/argvHelper';
|
||||
import { ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
@@ -47,7 +47,7 @@ export async function main(argv: string[]): Promise<any> {
|
||||
// Help
|
||||
if (args.help) {
|
||||
const executable = `${product.applicationName}${os.platform() === 'win32' ? '.exe' : ''}`;
|
||||
console.log(buildHelpMessage(product.nameLong, executable, pkg.version));
|
||||
console.log(buildHelpMessage(product.nameLong, executable, pkg.version, OPTIONS));
|
||||
}
|
||||
|
||||
// Version Info
|
||||
|
||||
@@ -4,29 +4,28 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { formatOptions, Option, addArg } from 'vs/platform/environment/node/argv';
|
||||
import { ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
|
||||
suite('formatOptions', () => {
|
||||
|
||||
function o(id: keyof ParsedArgs, description: string): Option {
|
||||
function o(description: string): Option<any> {
|
||||
return {
|
||||
id, description, type: 'string'
|
||||
description, type: 'string'
|
||||
};
|
||||
}
|
||||
|
||||
test('Text should display small columns correctly', () => {
|
||||
assert.deepEqual(
|
||||
formatOptions([
|
||||
o('add', 'bar')
|
||||
], 80),
|
||||
formatOptions({
|
||||
'add': o('bar')
|
||||
}, 80),
|
||||
[' --add bar']
|
||||
);
|
||||
assert.deepEqual(
|
||||
formatOptions([
|
||||
o('add', 'bar'),
|
||||
o('wait', 'ba'),
|
||||
o('trace', 'b')
|
||||
], 80),
|
||||
formatOptions({
|
||||
'add': o('bar'),
|
||||
'wait': o('ba'),
|
||||
'trace': o('b')
|
||||
}, 80),
|
||||
[
|
||||
' --add bar',
|
||||
' --wait ba',
|
||||
@@ -36,9 +35,9 @@ suite('formatOptions', () => {
|
||||
|
||||
test('Text should wrap', () => {
|
||||
assert.deepEqual(
|
||||
formatOptions([
|
||||
o('add', (<any>'bar ').repeat(9))
|
||||
], 40),
|
||||
formatOptions({
|
||||
'add': o((<any>'bar ').repeat(9))
|
||||
}, 40),
|
||||
[
|
||||
' --add bar bar bar bar bar bar bar bar',
|
||||
' bar'
|
||||
@@ -47,9 +46,9 @@ suite('formatOptions', () => {
|
||||
|
||||
test('Text should revert to the condensed view when the terminal is too narrow', () => {
|
||||
assert.deepEqual(
|
||||
formatOptions([
|
||||
o('add', (<any>'bar ').repeat(9))
|
||||
], 30),
|
||||
formatOptions({
|
||||
'add': o((<any>'bar ').repeat(9))
|
||||
}, 30),
|
||||
[
|
||||
' --add',
|
||||
' bar bar bar bar bar bar bar bar bar '
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as path from 'vs/base/common/path';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { URI as Uri, URI } from 'vs/base/common/uri';
|
||||
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
|
||||
import { IBackupWorkspacesFormat, ISerializedWorkspace, IWorkspaceBackupInfo } from 'vs/platform/backup/common/backup';
|
||||
import { HotExitConfiguration } from 'vs/platform/files/common/files';
|
||||
@@ -32,7 +32,7 @@ suite('BackupMainService', () => {
|
||||
const backupHome = path.join(parentDir, 'Backups');
|
||||
const backupWorkspacesPath = path.join(backupHome, 'workspaces.json');
|
||||
|
||||
const environmentService = new EnvironmentService(parseArgs(process.argv), process.execPath);
|
||||
const environmentService = new EnvironmentService(parseArgs(process.argv, OPTIONS), process.execPath);
|
||||
|
||||
class TestBackupMainService extends BackupMainService {
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export interface ParsedArgs {
|
||||
'reuse-window'?: boolean;
|
||||
locale?: string;
|
||||
'user-data-dir'?: string;
|
||||
'prof-startup'?: string;
|
||||
'prof-startup'?: boolean;
|
||||
'prof-startup-prefix'?: string;
|
||||
'prof-append-timers'?: string;
|
||||
verbose?: boolean;
|
||||
@@ -61,8 +61,8 @@ export interface ParsedArgs {
|
||||
'disable-telemetry'?: boolean;
|
||||
'export-default-configuration'?: string;
|
||||
'install-source'?: string;
|
||||
'disable-updates'?: string;
|
||||
'disable-crash-reporter'?: string;
|
||||
'disable-updates'?: boolean;
|
||||
'disable-crash-reporter'?: boolean;
|
||||
'skip-add-to-recently-opened'?: boolean;
|
||||
'max-memory'?: string;
|
||||
'file-write'?: boolean;
|
||||
@@ -76,7 +76,7 @@ export interface ParsedArgs {
|
||||
'force'?: boolean;
|
||||
'gitCredential'?: string;
|
||||
// node flags
|
||||
'js-flags'?: boolean;
|
||||
'js-flags'?: string;
|
||||
'disable-gpu'?: boolean;
|
||||
'nolazy'?: boolean;
|
||||
|
||||
|
||||
@@ -20,84 +20,96 @@ const helpCategories = {
|
||||
t: localize('troubleshooting', "Troubleshooting")
|
||||
};
|
||||
|
||||
export interface Option {
|
||||
id: keyof ParsedArgs;
|
||||
type: 'boolean' | 'string' | 'string[]';
|
||||
export interface Option<OptionType> {
|
||||
type: OptionType;
|
||||
alias?: string;
|
||||
deprecates?: string; // old deprecated id
|
||||
args?: string | string[];
|
||||
description?: string;
|
||||
cat?: keyof typeof helpCategories;
|
||||
}
|
||||
//_urls
|
||||
export const options: Option[] = [
|
||||
{ id: 'diff', type: 'boolean', cat: 'o', alias: 'd', args: ['file', 'file'], description: localize('diff', "Compare two files with each other.") },
|
||||
{ id: 'add', type: 'boolean', cat: 'o', alias: 'a', args: 'folder', description: localize('add', "Add folder(s) to the last active window.") },
|
||||
{ id: 'goto', type: 'boolean', cat: 'o', alias: 'g', args: 'file:line[:character]', description: localize('goto', "Open a file at the path on the specified line and character position.") },
|
||||
{ id: 'new-window', type: 'boolean', cat: 'o', alias: 'n', description: localize('newWindow', "Force to open a new window.") },
|
||||
{ id: 'reuse-window', type: 'boolean', cat: 'o', alias: 'r', description: localize('reuseWindow', "Force to open a file or folder in an already opened window.") },
|
||||
{ id: 'wait', type: 'boolean', cat: 'o', alias: 'w', description: localize('wait', "Wait for the files to be closed before returning.") },
|
||||
{ id: 'locale', type: 'string', cat: 'o', args: 'locale', description: localize('locale', "The locale to use (e.g. en-US or zh-TW).") },
|
||||
{ id: 'user-data-dir', type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") },
|
||||
{ id: 'version', type: 'boolean', cat: 'o', alias: 'v', description: localize('version', "Print version.") },
|
||||
{ id: 'help', type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },
|
||||
{ id: 'telemetry', type: 'boolean', cat: 'o', description: localize('telemetry', "Shows all telemetry events which VS code collects.") },
|
||||
{ id: 'folder-uri', type: 'string[]', cat: 'o', args: 'uri', description: localize('folderUri', "Opens a window with given folder uri(s)") },
|
||||
{ id: 'file-uri', type: 'string[]', cat: 'o', args: 'uri', description: localize('fileUri', "Opens a window with given file uri(s)") },
|
||||
|
||||
{ id: 'extensions-dir', type: 'string', deprecates: 'extensionHomePath', cat: 'e', args: 'dir', description: localize('extensionHomePath', "Set the root path for extensions.") },
|
||||
{ id: 'list-extensions', type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") },
|
||||
{ id: 'show-versions', type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") },
|
||||
{ id: 'category', type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") },
|
||||
{ id: 'install-extension', type: 'string[]', cat: 'e', args: 'extension-id | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. Use `--force` argument to avoid prompts.") },
|
||||
{ id: 'uninstall-extension', type: 'string[]', cat: 'e', args: 'extension-id', description: localize('uninstallExtension', "Uninstalls an extension.") },
|
||||
{ id: 'enable-proposed-api', type: 'string[]', cat: 'e', args: 'extension-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") },
|
||||
export type OptionDescriptions<T> = {
|
||||
[P in keyof T]: Option<OptionTypeName<T[P]>>;
|
||||
};
|
||||
|
||||
{ id: 'verbose', type: 'boolean', cat: 't', description: localize('verbose', "Print verbose output (implies --wait).") },
|
||||
{ id: 'log', type: 'string', cat: 't', args: 'level', description: localize('log', "Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.") },
|
||||
{ id: 'status', type: 'boolean', alias: 's', cat: 't', description: localize('status', "Print process usage and diagnostics information.") },
|
||||
{ id: 'prof-startup', type: 'boolean', cat: 't', description: localize('prof-startup', "Run CPU profiler during startup") },
|
||||
{ id: 'disable-extensions', type: 'boolean', deprecates: 'disableExtensions', cat: 't', description: localize('disableExtensions', "Disable all installed extensions.") },
|
||||
{ id: 'disable-extension', type: 'string[]', cat: 't', args: 'extension-id', description: localize('disableExtension', "Disable an extension.") },
|
||||
type OptionTypeName<T> =
|
||||
T extends boolean ? 'boolean' :
|
||||
T extends string ? 'string' :
|
||||
T extends string[] ? 'string[]' :
|
||||
T extends undefined ? 'undefined' :
|
||||
'unknown';
|
||||
|
||||
{ id: 'inspect-extensions', type: 'string', deprecates: 'debugPluginHost', args: 'port', cat: 't', description: localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection URI.") },
|
||||
{ id: 'inspect-brk-extensions', type: 'string', deprecates: 'debugBrkPluginHost', args: 'port', cat: 't', description: 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.") },
|
||||
{ id: 'disable-gpu', type: 'boolean', cat: 't', description: localize('disableGPU', "Disable GPU hardware acceleration.") },
|
||||
{ id: 'max-memory', type: 'string', cat: 't', description: localize('maxMemory', "Max memory size for a window (in Mbytes).") },
|
||||
export const OPTIONS: OptionDescriptions<ParsedArgs> = {
|
||||
'diff': { type: 'boolean', cat: 'o', alias: 'd', args: ['file', 'file'], description: localize('diff', "Compare two files with each other.") },
|
||||
'add': { type: 'boolean', cat: 'o', alias: 'a', args: 'folder', description: localize('add', "Add folder(s) to the last active window.") },
|
||||
'goto': { type: 'boolean', cat: 'o', alias: 'g', args: 'file:line[:character]', description: localize('goto', "Open a file at the path on the specified line and character position.") },
|
||||
'new-window': { type: 'boolean', cat: 'o', alias: 'n', description: localize('newWindow', "Force to open a new window.") },
|
||||
'reuse-window': { type: 'boolean', cat: 'o', alias: 'r', description: localize('reuseWindow', "Force to open a file or folder in an already opened window.") },
|
||||
'wait': { type: 'boolean', cat: 'o', alias: 'w', description: localize('wait', "Wait for the files to be closed before returning.") },
|
||||
'locale': { type: 'string', cat: 'o', args: 'locale', description: localize('locale', "The locale to use (e.g. en-US or zh-TW).") },
|
||||
'user-data-dir': { type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") },
|
||||
'version': { type: 'boolean', cat: 'o', alias: 'v', description: localize('version', "Print version.") },
|
||||
'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },
|
||||
'telemetry': { type: 'boolean', cat: 'o', description: localize('telemetry', "Shows all telemetry events which VS code collects.") },
|
||||
'folder-uri': { type: 'string[]', cat: 'o', args: 'uri', description: localize('folderUri', "Opens a window with given folder uri(s)") },
|
||||
'file-uri': { type: 'string[]', cat: 'o', args: 'uri', description: localize('fileUri', "Opens a window with given file uri(s)") },
|
||||
|
||||
{ id: 'remote', type: 'string' },
|
||||
{ id: 'locate-extension', type: 'string[]' },
|
||||
{ id: 'extensionDevelopmentPath', type: 'string[]' },
|
||||
{ id: 'extensionTestsPath', type: 'string' },
|
||||
{ id: 'extension-development-confirm-save', type: 'boolean' },
|
||||
{ id: 'debugId', type: 'string' },
|
||||
{ id: 'inspect-search', type: 'string', deprecates: 'debugSearch' },
|
||||
{ id: 'inspect-brk-search', type: 'string', deprecates: 'debugBrkSearch' },
|
||||
{ id: 'export-default-configuration', type: 'string' },
|
||||
{ id: 'install-source', type: 'string' },
|
||||
{ id: 'driver', type: 'string' },
|
||||
{ id: 'logExtensionHostCommunication', type: 'boolean' },
|
||||
{ id: 'skip-getting-started', type: 'boolean' },
|
||||
{ id: 'skip-release-notes', type: 'boolean' },
|
||||
{ id: 'sticky-quickopen', type: 'boolean' },
|
||||
{ id: 'disable-restore-windows', type: 'boolean' },
|
||||
{ id: 'disable-telemetry', type: 'boolean' },
|
||||
{ id: 'disable-updates', type: 'boolean' },
|
||||
{ id: 'disable-crash-reporter', type: 'boolean' },
|
||||
{ id: 'skip-add-to-recently-opened', type: 'boolean' },
|
||||
{ id: 'unity-launch', type: 'boolean' },
|
||||
{ id: 'open-url', type: 'boolean' },
|
||||
{ id: 'file-write', type: 'boolean' },
|
||||
{ id: 'file-chmod', type: 'boolean' },
|
||||
{ id: 'driver-verbose', type: 'boolean' },
|
||||
{ id: 'force', type: 'boolean' },
|
||||
{ id: 'trace-category-filter', type: 'string' },
|
||||
{ id: 'trace-options', type: 'string' },
|
||||
{ id: 'disable-inspect', type: 'boolean' },
|
||||
'extensions-dir': { type: 'string', deprecates: 'extensionHomePath', cat: 'e', args: 'dir', description: localize('extensionHomePath', "Set the root path for extensions.") },
|
||||
'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") },
|
||||
'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") },
|
||||
'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") },
|
||||
'install-extension': { type: 'string[]', cat: 'e', args: 'extension-id | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. Use `--force` argument to avoid prompts.") },
|
||||
'uninstall-extension': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('uninstallExtension', "Uninstalls an extension.") },
|
||||
'enable-proposed-api': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") },
|
||||
|
||||
{ id: 'js-flags', type: 'string' }, // chrome js flags
|
||||
{ id: 'nolazy', type: 'boolean' }, // node inspect
|
||||
];
|
||||
'verbose': { type: 'boolean', cat: 't', description: localize('verbose', "Print verbose output (implies --wait).") },
|
||||
'log': { type: 'string', cat: 't', args: 'level', description: localize('log', "Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.") },
|
||||
'status': { type: 'boolean', alias: 's', cat: 't', description: localize('status', "Print process usage and diagnostics information.") },
|
||||
'prof-startup': { type: 'boolean', cat: 't', description: localize('prof-startup', "Run CPU profiler during startup") },
|
||||
'disable-extensions': { type: 'boolean', deprecates: 'disableExtensions', cat: 't', description: localize('disableExtensions', "Disable all installed extensions.") },
|
||||
'disable-extension': { type: 'string[]', cat: 't', args: 'extension-id', description: localize('disableExtension', "Disable an extension.") },
|
||||
|
||||
'inspect-extensions': { type: 'string', deprecates: 'debugPluginHost', args: 'port', cat: 't', description: localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection URI.") },
|
||||
'inspect-brk-extensions': { type: 'string', deprecates: 'debugBrkPluginHost', args: 'port', cat: 't', description: 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.") },
|
||||
'disable-gpu': { type: 'boolean', cat: 't', description: localize('disableGPU', "Disable GPU hardware acceleration.") },
|
||||
'max-memory': { type: 'string', cat: 't', description: localize('maxMemory', "Max memory size for a window (in Mbytes).") },
|
||||
|
||||
'remote': { type: 'string' },
|
||||
'locate-extension': { type: 'string[]' },
|
||||
'extensionDevelopmentPath': { type: 'string[]' },
|
||||
'extensionTestsPath': { type: 'string' },
|
||||
'extension-development-confirm-save': { type: 'boolean' },
|
||||
'debugId': { type: 'string' },
|
||||
'inspect-search': { type: 'string', deprecates: 'debugSearch' },
|
||||
'inspect-brk-search': { type: 'string', deprecates: 'debugBrkSearch' },
|
||||
'export-default-configuration': { type: 'string' },
|
||||
'install-source': { type: 'string' },
|
||||
'driver': { type: 'string' },
|
||||
'logExtensionHostCommunication': { type: 'boolean' },
|
||||
'skip-getting-started': { type: 'boolean' },
|
||||
'skip-release-notes': { type: 'boolean' },
|
||||
'sticky-quickopen': { type: 'boolean' },
|
||||
'disable-restore-windows': { type: 'boolean' },
|
||||
'disable-telemetry': { type: 'boolean' },
|
||||
'disable-updates': { type: 'boolean' },
|
||||
'disable-crash-reporter': { type: 'boolean' },
|
||||
'skip-add-to-recently-opened': { type: 'boolean' },
|
||||
'unity-launch': { type: 'boolean' },
|
||||
'open-url': { type: 'boolean' },
|
||||
'file-write': { type: 'boolean' },
|
||||
'file-chmod': { type: 'boolean' },
|
||||
'driver-verbose': { type: 'boolean' },
|
||||
'force': { type: 'boolean' },
|
||||
'trace-category-filter': { type: 'string' },
|
||||
'trace-options': { type: 'string' },
|
||||
'disable-inspect': { type: 'boolean' },
|
||||
|
||||
'js-flags': { type: 'string' }, // chrome js flags
|
||||
'nolazy': { type: 'boolean' }, // node inspect
|
||||
|
||||
_: { type: 'string[]' } // main arguments
|
||||
};
|
||||
|
||||
export interface ErrorReporter {
|
||||
onUnknownOption(id: string): void;
|
||||
@@ -109,24 +121,23 @@ const ignoringReporter: ErrorReporter = {
|
||||
onMultipleValues: () => { }
|
||||
};
|
||||
|
||||
export function parseArgs(args: string[], isOptionSupported = (_: Option) => true, errorReporter: ErrorReporter = ignoringReporter): ParsedArgs {
|
||||
export function parseArgs<T>(args: string[], options: OptionDescriptions<T>, errorReporter: ErrorReporter = ignoringReporter): T {
|
||||
const alias: { [key: string]: string } = {};
|
||||
const string: string[] = [];
|
||||
const boolean: string[] = [];
|
||||
for (let o of options) {
|
||||
if (isOptionSupported(o)) {
|
||||
if (o.alias) {
|
||||
alias[o.id] = o.alias;
|
||||
}
|
||||
for (let optionId in options) {
|
||||
const o = options[optionId];
|
||||
if (o.alias) {
|
||||
alias[optionId] = o.alias;
|
||||
}
|
||||
|
||||
if (o.type === 'string' || o.type === 'string[]') {
|
||||
string.push(o.id);
|
||||
string.push(optionId);
|
||||
if (o.deprecates) {
|
||||
string.push(o.deprecates);
|
||||
}
|
||||
} else if (o.type === 'boolean') {
|
||||
boolean.push(o.id);
|
||||
boolean.push(optionId);
|
||||
if (o.deprecates) {
|
||||
boolean.push(o.deprecates);
|
||||
}
|
||||
@@ -137,12 +148,17 @@ export function parseArgs(args: string[], isOptionSupported = (_: Option) => tru
|
||||
|
||||
const cleanedArgs: any = {};
|
||||
|
||||
for (const o of options) {
|
||||
// https://github.com/microsoft/vscode/issues/58177
|
||||
cleanedArgs._ = parsedArgs._.filter(arg => arg.length > 0);
|
||||
delete parsedArgs._;
|
||||
|
||||
for (let optionId in options) {
|
||||
const o = options[optionId];
|
||||
if (o.alias) {
|
||||
delete parsedArgs[o.alias];
|
||||
}
|
||||
|
||||
let val = parsedArgs[o.id];
|
||||
let val = parsedArgs[optionId];
|
||||
if (o.deprecates && parsedArgs.hasOwnProperty(o.deprecates)) {
|
||||
if (!val) {
|
||||
val = parsedArgs[o.deprecates];
|
||||
@@ -151,29 +167,21 @@ export function parseArgs(args: string[], isOptionSupported = (_: Option) => tru
|
||||
}
|
||||
|
||||
if (val) {
|
||||
if (isOptionSupported(o)) {
|
||||
if (o.type === 'string[]') {
|
||||
if (val && !Array.isArray(val)) {
|
||||
val = [val];
|
||||
}
|
||||
} else if (o.type === 'string') {
|
||||
if (Array.isArray(val)) {
|
||||
val = val.pop(); // take the last
|
||||
errorReporter.onMultipleValues(o.id, val);
|
||||
}
|
||||
if (o.type === 'string[]') {
|
||||
if (val && !Array.isArray(val)) {
|
||||
val = [val];
|
||||
}
|
||||
} else if (o.type === 'string') {
|
||||
if (Array.isArray(val)) {
|
||||
val = val.pop(); // take the last
|
||||
errorReporter.onMultipleValues(optionId, val);
|
||||
}
|
||||
cleanedArgs[o.id] = val;
|
||||
} else {
|
||||
errorReporter.onUnknownOption(o.id);
|
||||
}
|
||||
cleanedArgs[optionId] = val;
|
||||
}
|
||||
delete parsedArgs[o.id];
|
||||
delete parsedArgs[optionId];
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/58177
|
||||
cleanedArgs._ = parsedArgs._.filter(arg => arg.length > 0);
|
||||
delete parsedArgs._;
|
||||
|
||||
for (let key in parsedArgs) {
|
||||
errorReporter.onUnknownOption(key);
|
||||
}
|
||||
@@ -181,7 +189,7 @@ export function parseArgs(args: string[], isOptionSupported = (_: Option) => tru
|
||||
return cleanedArgs;
|
||||
}
|
||||
|
||||
function formatUsage(option: Option) {
|
||||
function formatUsage(optionId: string, option: Option<any>) {
|
||||
let args = '';
|
||||
if (option.args) {
|
||||
if (Array.isArray(option.args)) {
|
||||
@@ -191,30 +199,37 @@ function formatUsage(option: Option) {
|
||||
}
|
||||
}
|
||||
if (option.alias) {
|
||||
return `-${option.alias} --${option.id}${args}`;
|
||||
return `-${option.alias} --${optionId}${args}`;
|
||||
}
|
||||
return `--${option.id}${args}`;
|
||||
return `--${optionId}${args}`;
|
||||
}
|
||||
|
||||
// exported only for testing
|
||||
export function formatOptions(docOptions: Option[], columns: number): string[] {
|
||||
let usageTexts = docOptions.map(formatUsage);
|
||||
let argLength = Math.max.apply(null, usageTexts.map(k => k.length)) + 2/*left padding*/ + 1/*right padding*/;
|
||||
export function formatOptions(options: OptionDescriptions<any>, columns: number): string[] {
|
||||
let maxLength = 0;
|
||||
let usageTexts: [string, string][] = [];
|
||||
for (const optionId in options) {
|
||||
const o = options[optionId];
|
||||
const usageText = formatUsage(optionId, o);
|
||||
maxLength = Math.max(maxLength, usageText.length);
|
||||
usageTexts.push([usageText, o.description!]);
|
||||
}
|
||||
let argLength = maxLength + 2/*left padding*/ + 1/*right padding*/;
|
||||
if (columns - argLength < 25) {
|
||||
// Use a condensed version on narrow terminals
|
||||
return docOptions.reduce<string[]>((r, o, i) => r.concat([` ${usageTexts[i]}`, ` ${o.description}`]), []);
|
||||
return usageTexts.reduce<string[]>((r, ut) => r.concat([` ${ut[0]}`, ` ${ut[1]}`]), []);
|
||||
}
|
||||
let descriptionColumns = columns - argLength - 1;
|
||||
let result: string[] = [];
|
||||
docOptions.forEach((o, i) => {
|
||||
let usage = usageTexts[i];
|
||||
let wrappedDescription = wrapText(o.description!, descriptionColumns);
|
||||
for (const ut of usageTexts) {
|
||||
let usage = ut[0];
|
||||
let wrappedDescription = wrapText(ut[1], descriptionColumns);
|
||||
let keyPadding = indent(argLength - usage.length - 2/*left padding*/);
|
||||
result.push(' ' + usage + keyPadding + wrappedDescription[0]);
|
||||
for (let i = 1; i < wrappedDescription.length; i++) {
|
||||
result.push(indent(argLength) + wrappedDescription[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -233,7 +248,7 @@ function wrapText(text: string, columns: number): string[] {
|
||||
return lines;
|
||||
}
|
||||
|
||||
export function buildHelpMessage(productName: string, executableName: string, version: string, isOptionSupported = (_: Option) => true, isPipeSupported = true): string {
|
||||
export function buildHelpMessage(productName: string, executableName: string, version: string, options: OptionDescriptions<any>, isPipeSupported = true): string {
|
||||
const columns = (process.stdout).isTTY && (process.stdout).columns || 80;
|
||||
|
||||
let help = [`${productName} ${version}`];
|
||||
@@ -248,11 +263,23 @@ export function buildHelpMessage(productName: string, executableName: string, ve
|
||||
}
|
||||
help.push('');
|
||||
}
|
||||
for (let helpCategoryKey in helpCategories) {
|
||||
const optionsByCategory: { [P in keyof typeof helpCategories]?: OptionDescriptions<any> } = {};
|
||||
for (const optionId in options) {
|
||||
const o = options[optionId];
|
||||
if (o.description && o.cat) {
|
||||
let optionsByCat = optionsByCategory[o.cat];
|
||||
if (!optionsByCat) {
|
||||
optionsByCategory[o.cat] = optionsByCat = {};
|
||||
}
|
||||
optionsByCat[optionId] = o;
|
||||
}
|
||||
}
|
||||
|
||||
for (let helpCategoryKey in optionsByCategory) {
|
||||
const key = <keyof typeof helpCategories>helpCategoryKey;
|
||||
|
||||
let categoryOptions = options.filter(o => !!o.description && o.cat === key && isOptionSupported(o));
|
||||
if (categoryOptions.length) {
|
||||
let categoryOptions = optionsByCategory[key];
|
||||
if (categoryOptions) {
|
||||
help.push(helpCategories[key]);
|
||||
help.push(...formatOptions(categoryOptions, columns));
|
||||
help.push('');
|
||||
|
||||
@@ -8,7 +8,7 @@ import { firstIndex } from 'vs/base/common/arrays';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ParsedArgs } from '../common/environment';
|
||||
import { MIN_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files';
|
||||
import { parseArgs, ErrorReporter } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, ErrorReporter, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
|
||||
function parseAndValidate(cmdLineArgs: string[], reportWarnings: boolean): ParsedArgs {
|
||||
const errorReporter: ErrorReporter = {
|
||||
@@ -20,7 +20,7 @@ function parseAndValidate(cmdLineArgs: string[], reportWarnings: boolean): Parse
|
||||
}
|
||||
};
|
||||
|
||||
const args = parseArgs(cmdLineArgs, undefined, reportWarnings ? errorReporter : undefined);
|
||||
const args = parseArgs(cmdLineArgs, OPTIONS, reportWarnings ? errorReporter : undefined);
|
||||
if (args.goto) {
|
||||
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))`.")));
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { parseExtensionHostPort, parseUserDataDir } from 'vs/platform/environment/node/environmentService';
|
||||
|
||||
suite('EnvironmentService', () => {
|
||||
|
||||
test('parseExtensionHostPort when built', () => {
|
||||
const parse = (a: string[]) => parseExtensionHostPort(parseArgs(a), true);
|
||||
const parse = (a: string[]) => parseExtensionHostPort(parseArgs(a, OPTIONS), true);
|
||||
|
||||
assert.deepEqual(parse([]), { port: null, break: false, debugId: undefined });
|
||||
assert.deepEqual(parse(['--debugPluginHost']), { port: null, break: false, debugId: undefined });
|
||||
@@ -28,7 +28,7 @@ suite('EnvironmentService', () => {
|
||||
});
|
||||
|
||||
test('parseExtensionHostPort when unbuilt', () => {
|
||||
const parse = (a: string[]) => parseExtensionHostPort(parseArgs(a), false);
|
||||
const parse = (a: string[]) => parseExtensionHostPort(parseArgs(a, OPTIONS), false);
|
||||
|
||||
assert.deepEqual(parse([]), { port: 5870, break: false, debugId: undefined });
|
||||
assert.deepEqual(parse(['--debugPluginHost']), { port: 5870, break: false, debugId: undefined });
|
||||
@@ -45,7 +45,7 @@ suite('EnvironmentService', () => {
|
||||
});
|
||||
|
||||
test('userDataPath', () => {
|
||||
const parse = (a: string[], b: { cwd: () => string, env: { [key: string]: string } }) => parseUserDataDir(parseArgs(a), <any>b);
|
||||
const parse = (a: string[], b: { cwd: () => string, env: { [key: string]: string } }) => parseUserDataDir(parseArgs(a, OPTIONS), <any>b);
|
||||
|
||||
assert.equal(parse(['--user-data-dir', './dir'], { cwd: () => '/foo', env: {} }), path.resolve('/foo/dir'),
|
||||
'should use cwd when --user-data-dir is specified');
|
||||
@@ -55,11 +55,11 @@ suite('EnvironmentService', () => {
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/78440
|
||||
test('careful with boolean file names', function () {
|
||||
let actual = parseArgs(['-r', 'arg.txt']);
|
||||
let actual = parseArgs(['-r', 'arg.txt'], OPTIONS);
|
||||
assert(actual['reuse-window']);
|
||||
assert.deepEqual(actual._, ['arg.txt']);
|
||||
|
||||
actual = parseArgs(['-r', 'true.txt']);
|
||||
actual = parseArgs(['-r', 'true.txt'], OPTIONS);
|
||||
assert(actual['reuse-window']);
|
||||
assert.deepEqual(actual._, ['true.txt']);
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import * as os from 'os';
|
||||
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { mkdirp, RimRafMode, rimraf } from 'vs/base/node/pfs';
|
||||
@@ -51,7 +51,7 @@ suite('Extension Gallery Service', () => {
|
||||
|
||||
test('marketplace machine id', () => {
|
||||
const args = ['--user-data-dir', marketplaceHome];
|
||||
const environmentService = new EnvironmentService(parseArgs(args), process.execPath);
|
||||
const environmentService = new EnvironmentService(parseArgs(args, OPTIONS), process.execPath);
|
||||
|
||||
return resolveMarketplaceHeaders(pkg.version, environmentService, fileService).then(headers => {
|
||||
assert.ok(isUUID(headers['X-Market-User-Id']));
|
||||
@@ -61,4 +61,4 @@ suite('Extension Gallery Service', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/node/issue';
|
||||
import { BrowserWindow, ipcMain, screen, Event, dialog } from 'electron';
|
||||
import { ILaunchService } from 'vs/platform/launch/electron-main/launchService';
|
||||
@@ -372,7 +372,7 @@ export class IssueService implements IIssueService {
|
||||
}
|
||||
|
||||
function toLauchUrl<T>(pathToHtml: string, windowConfiguration: T): string {
|
||||
const environment = parseArgs(process.argv);
|
||||
const environment = parseArgs(process.argv, OPTIONS);
|
||||
const config = objects.assign(environment, windowConfiguration);
|
||||
for (const keyValue of Object.keys(config)) {
|
||||
const key = keyValue as keyof typeof config;
|
||||
|
||||
@@ -12,7 +12,7 @@ import { tmpdir } from 'os';
|
||||
import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { InMemoryStorageDatabase } from 'vs/base/parts/storage/common/storage';
|
||||
|
||||
suite('StorageService', () => {
|
||||
@@ -86,7 +86,7 @@ suite('StorageService', () => {
|
||||
class StorageTestEnvironmentService extends EnvironmentService {
|
||||
|
||||
constructor(private workspaceStorageFolderPath: string, private _extensionsPath: string) {
|
||||
super(parseArgs(process.argv), process.execPath);
|
||||
super(parseArgs(process.argv, OPTIONS), process.execPath);
|
||||
}
|
||||
|
||||
get workspaceStorageHome(): string {
|
||||
@@ -117,4 +117,4 @@ suite('StorageService', () => {
|
||||
await storage.close();
|
||||
await rimraf(storageDir, RimRafMode.MOVE);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as os from 'os';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { WorkspacesMainService, IStoredWorkspace } from 'vs/platform/workspaces/electron-main/workspacesMainService';
|
||||
import { WORKSPACE_EXTENSION, IWorkspaceIdentifier, IRawFileWorkspaceFolder, IWorkspaceFolderCreationData, IRawUriWorkspaceFolder, rewriteWorkspaceFileForNewLocation } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
@@ -47,7 +47,7 @@ suite('WorkspacesMainService', () => {
|
||||
return service.createUntitledWorkspaceSync(folders.map((folder, index) => ({ uri: URI.file(folder), name: names ? names[index] : undefined } as IWorkspaceFolderCreationData)));
|
||||
}
|
||||
|
||||
const environmentService = new TestEnvironmentService(parseArgs(process.argv), process.execPath);
|
||||
const environmentService = new TestEnvironmentService(parseArgs(process.argv, OPTIONS), process.execPath);
|
||||
const logService = new NullLogService();
|
||||
|
||||
let service: TestWorkspacesMainService;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
|
||||
import { WorkbenchEnvironmentService } from 'vs/workbench/services/environment/node/environmentService';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { snapshotToString } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { hashPath, BackupFileService } from 'vs/workbench/services/backup/node/backupFileService';
|
||||
@@ -49,7 +49,7 @@ const untitledBackupPath = path.join(workspaceBackupPath, 'untitled', hashPath(u
|
||||
class TestBackupEnvironmentService extends WorkbenchEnvironmentService {
|
||||
|
||||
constructor(backupPath: string) {
|
||||
super({ ...parseArgs(process.argv), ...{ backupPath, 'user-data-dir': userdataDir } } as IWindowConfiguration, process.execPath);
|
||||
super({ ...parseArgs(process.argv, OPTIONS), ...{ backupPath, 'user-data-dir': userdataDir } } as IWindowConfiguration, process.execPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import * as fs from 'fs';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { TestTextFileService, workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import * as uuid from 'vs/base/common/uuid';
|
||||
@@ -46,7 +46,7 @@ import { FileUserDataProvider } from 'vs/workbench/services/userData/common/file
|
||||
class TestEnvironmentService extends WorkbenchEnvironmentService {
|
||||
|
||||
constructor(private _appSettingsHome: URI) {
|
||||
super(parseArgs(process.argv) as IWindowConfiguration, process.execPath);
|
||||
super(parseArgs(process.argv, OPTIONS) as IWindowConfiguration, process.execPath);
|
||||
}
|
||||
|
||||
get appSettingsHome() { return this._appSettingsHome; }
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import * as os from 'os';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import * as uuid from 'vs/base/common/uuid';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
@@ -51,7 +51,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
|
||||
class TestEnvironmentService extends WorkbenchEnvironmentService {
|
||||
|
||||
constructor(private _appSettingsHome: URI) {
|
||||
super(parseArgs(process.argv) as IWindowConfiguration, process.execPath);
|
||||
super(parseArgs(process.argv, OPTIONS) as IWindowConfiguration, process.execPath);
|
||||
}
|
||||
|
||||
get appSettingsHome() { return this._appSettingsHome; }
|
||||
|
||||
+2
-2
@@ -46,14 +46,14 @@ import { Schemas } from 'vs/base/common/network';
|
||||
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { FileUserDataProvider } from 'vs/workbench/services/userData/common/fileUserDataProvider';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { WorkbenchEnvironmentService } from 'vs/workbench/services/environment/node/environmentService';
|
||||
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
|
||||
|
||||
class TestEnvironmentService extends WorkbenchEnvironmentService {
|
||||
|
||||
constructor(private _appSettingsHome: URI) {
|
||||
super(parseArgs(process.argv) as IWindowConfiguration, process.execPath);
|
||||
super(parseArgs(process.argv, OPTIONS) as IWindowConfiguration, process.execPath);
|
||||
}
|
||||
|
||||
get appSettingsHome() { return this._appSettingsHome; }
|
||||
|
||||
@@ -30,7 +30,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
|
||||
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
|
||||
import { ITextFileStreamContent, ITextFileService, IResourceEncoding, IReadTextFileOptions } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -91,7 +91,7 @@ export function createFileInput(instantiationService: IInstantiationService, res
|
||||
return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined);
|
||||
}
|
||||
|
||||
export const TestEnvironmentService = new WorkbenchEnvironmentService(parseArgs(process.argv) as IWindowConfiguration, process.execPath);
|
||||
export const TestEnvironmentService = new WorkbenchEnvironmentService(parseArgs(process.argv, OPTIONS) as IWindowConfiguration, process.execPath);
|
||||
|
||||
export class TestContextService implements IWorkspaceContextService {
|
||||
public _serviceBrand: undefined;
|
||||
|
||||
Reference in New Issue
Block a user