diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index dd6aaa07bb15a89cf5fca46de8ffd942bc565820..a72b1835f9839a0324d48f9709518c625727883b 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -5,7 +5,6 @@ import * as os from 'os'; import * as minimist from 'minimist'; -import pkg from 'vs/platform/package'; import { localize } from 'vs/nls'; export interface ParsedArgs extends minimist.ParsedArgs { @@ -89,20 +88,53 @@ export const optionsHelp: { [name: string]: string; } = { '--verbose': localize('verbose', "Print verbose output (implies --wait)."), '-w, --wait': localize('wait', "Wait for the window to be closed before returning."), '--list-extensions': localize('listExtensions', "List the installed extensions."), - '--install-extension ': localize('installExtension', "Installs an extension."), - '--uninstall-extension ': localize('uninstallExtension', "Uninstalls an extension."), + '--install-extension ': localize('installExtension', "Installs an extension."), + '--uninstall-extension ': localize('uninstallExtension', "Uninstalls an extension."), '-v, --version': localize('version', "Print version."), '-h, --help': localize('help', "Print usage.") }; -function formatOptions(options: { [name: string]: string; }): string { - return Object.keys(options) - .reduce((r, key) => r.concat([` ${ key }`, ` ${ options[key] }`]), []).join('\n'); +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 + return keys.reduce((r, key) => r.concat([` ${ key }`, ` ${ options[key] }`]), []).join('\n'); + } + let descriptionColumns = columns - argLength - 1; + let result = ''; + keys.forEach(k => { + let wrappedDescription = wrapText(options[k], descriptionColumns); + let keyPadding = (' ').repeat(argLength - k.length - 2/*left padding*/); + if (result.length > 0) { + result += '\n'; + } + result += ' ' + k + keyPadding + wrappedDescription[0]; + for (var i = 1; i < wrappedDescription.length; i++) { + result += '\n' + (' ').repeat(argLength) + wrappedDescription[i]; + } + }); + return result; } -export const helpMessage = `Visual Studio Code v${ pkg.version } +function wrapText(text: string, columns: number) : string[] { + let lines = []; + while (text.length) { + let index = text.length < columns ? text.length : text.lastIndexOf(' ', columns); + let line = text.slice(0, index).trim(); + text = text.slice(index); + lines.push(line); + } + return lines; +} + +export function buildHelpMessage(version: string): string { + let columns = (process.stdout).isTTY ? (process.stdout).columns : 80; + return `Visual Studio Code v${ version } + Usage: ${ executable } [arguments] [paths...] Options: -${formatOptions(optionsHelp)}`; \ No newline at end of file +${formatOptions(optionsHelp, columns)}`; +} \ No newline at end of file diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 59472225457a01ce07852d86670a6609ca491e2f..ee5beb41a03e0738fd575b11c4969685eae02cb2 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -6,7 +6,7 @@ import { spawn } from 'child_process'; import { TPromise } from 'vs/base/common/winjs.base'; import { assign } from 'vs/base/common/objects'; -import { parseArgs, helpMessage, ParsedArgs } from 'vs/code/node/argv'; +import { parseArgs, buildHelpMessage, ParsedArgs } from 'vs/code/node/argv'; import pkg from 'vs/platform/package'; function shouldSpawnCliProcess(argv: ParsedArgs): boolean { @@ -21,7 +21,7 @@ export function main(args: string[]): TPromise { const argv = parseArgs(args); if (argv.help) { - console.log(helpMessage); + console.log(buildHelpMessage(pkg.version)); } else if (argv.version) { console.log(pkg.version); } else if (shouldSpawnCliProcess(argv)) { diff --git a/src/vs/code/test/node/argv.test.ts b/src/vs/code/test/node/argv.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..685ca737cf9e181f58754d7d2d4f9f506489bb01 --- /dev/null +++ b/src/vs/code/test/node/argv.test.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import assert = require('assert'); +import {formatOptions} from 'vs/code/node/argv'; + +suite('formatOptions', () => { + test('Text should display small columns correctly', () => { + assert.equal(formatOptions({'foo': 'bar'}, 80), ' foo bar'); + assert.equal( + formatOptions({ + 'f': 'bar', + 'fo': 'ba', + 'foo': 'b' + }, 80), + ' f bar\n' + + ' fo ba\n' + + ' foo b'); + }); + + test('Text should wrap', () => { + assert.equal( + formatOptions({ + 'foo': ('bar ').repeat(9) + }, 40), + ' foo bar bar bar bar bar bar bar bar\n' + + ' bar'); + }); + + test('Text should revert to the condensed view when the terminal is too narrow', () => { + assert.equal( + formatOptions({ + 'foo': ('bar ').repeat(9) + }, 30), + ' foo\n' + + ' bar bar bar bar bar bar bar bar bar '); + }); +});