command-line-usage added (#24787)

* command-line-usage types good default bad

* Type adjustments

export Section, raw optional

* No errors - try remove tslint rule override

* Linting .d.ts works great!

* typings pass all given examples

* Removed type-annotation causing Travis to fail

* Re-added Dvorsky as contributor

Even though the new definitions completely overwrite the old, it was requested that the original author be re-added.

* Fixed a silly, silly mistake - missing comment slashes
This commit is contained in:
Mathew Rumsey 2018-04-24 19:42:48 -04:00 committed by Wesley Wigham
parent cd39e74f6b
commit 593a956550
2 changed files with 461 additions and 54 deletions

View File

@ -1,24 +1,397 @@
import commandLineUsage = require("command-line-usage");
import getUsage = require('command-line-usage');
const sections = [
let usage: string;
let sections: getUsage.Section[];
let optionDefinitions: getUsage.OptionDefinition[] = [];
// chalk-escaping.js
usage = getUsage([
{
header: 'A typical app',
content: 'Generates something {italic very} important.'
header: 'A typical app',
content: 'Generates something \\{very important\\}, also retaining `backticks`.'
},
{
header: 'Options',
optionList: [
{
name: 'input',
typeLabel: '{underline file}',
description: 'The input to process.'
},
{
name: 'help',
description: 'Print this usage guide.'
}
]
header: 'Options',
optionList: [
{ name: 'files', typeLabel: '\\{something\\}', description: 'This is not \\{red red\\}.'}
]
}
];
]);
const usage = commandLineUsage(sections);
// chalk-formatting.js
usage = getUsage([
{
header: 'A typical app',
content: 'Generates something {italic.keyword("orange") very {rgb(255,231,0).bold important}}. This is a rather long, but {hex("#1ef").underline ultimately} inconsequential '
+ 'description intended {yellow.bgRed.bold solely {bgBlue to}} demonstrate description appearance. '
},
{
header: 'Options',
optionList: [
{ name: 'files', typeLabel: '{magenta {underline files}}', description: 'This is {red red}.'}
]
},
{
content: 'Project home: {underline https://github.com/me/example}'
}
]);
// command-list.js
sections = [
{
header: 'Example App',
content: 'Generates something {italic very} important. This is a rather long, but ultimately inconsequential description intended solely to demonstrate description appearance. '
},
{
header: 'Synopsis',
content: '$ app <options> <command>'
},
{
header: 'Command List',
content: [
{ name: 'help', summary: 'Display help information about Git.' },
{ name: 'commit', summary: 'Record changes to the repository.' },
{ name: 'Version', summary: 'Print the version.' },
{ name: 'etc', summary: 'Etc.' }
]
}
];
usage = getUsage(sections);
// description-columns.js
sections = [
{
header: 'Soviet Union',
content: {
options: {
columns: [
{ name: 'one', maxWidth: 40 },
{ name: 'two', width: 40, noWrap: true }
]
},
data: [
{
one: "this was waaaay too long",
two: null
}
]
}
},
{
header: 'Synopsis',
content: [
'$ example [{bold --timeout} {underline ms}] {bold --src} {underline file} ...',
'$ example {bold --help}'
]
},
{
header: 'Options',
optionList: optionDefinitions
}
];
getUsage(sections);
// examples.js
sections = [
{
header: 'A typical app',
content: 'Generates something {italic very} important.'
},
{
header: 'Synopsis',
content: [
'$ example [{bold --timeout} {underline ms}] {bold --src} {underline file} ...',
'$ example {bold --help}'
]
},
{
header: 'Options',
optionList: optionDefinitions
},
{
header: 'Examples',
content: [
{
desc: '1. A concise example. ',
example: '$ example -t 100 lib/*.js'
},
{
desc: '2. A long example. ',
example: '$ example --timeout 100 --src lib/*.js'
},
{
desc: '3. This example will scan space for unknown things. Take cure when scanning space, it could take some time. ',
example: '$ example --src galaxy1.facts galaxy1.facts galaxy2.facts galaxy3.facts galaxy4.facts galaxy5.facts'
}
]
},
{
content: 'Project home: {underline https://github.com/me/example}'
}
];
getUsage(sections);
// footer.js
sections = [
{
header: 'A typical app',
content: 'Generates something {italic very} important.'
},
{
header: 'Synopsis',
content: [
'$ example [{bold --timeout} {underline ms}] {bold --src} {underline file} ...',
'$ example {bold --help}'
]
},
{
header: 'Options',
optionList: optionDefinitions
},
{
content: [
'{italic This app was tested by dragons in Wales.}',
'',
null
],
raw: true
}
];
getUsage(sections);
// groups.js
optionDefinitions = [
{
name: 'help',
description: 'Display this usage guide.',
alias: 'h',
type: Boolean,
group: 'main'
},
{
name: 'src',
description: 'The input files to process',
multiple: true,
defaultOption: true,
typeLabel: '{underline file} ...',
group: 'input'
},
{
name: 'timeout',
description: 'Timeout value in ms',
alias: 't',
typeLabel: '{underline ms}',
group: 'main'
},
{
name: 'plugin',
description: 'A plugin path',
type: String
}
];
sections = [
{
header: 'A typical app',
content: 'Generates something {italic very} important.'
},
{
header: 'Main options',
optionList: optionDefinitions,
group: [ 'main', 'input' ]
},
{
header: 'Misc',
optionList: optionDefinitions,
group: '_none'
}
];
getUsage(sections);
// header-only.js
sections = [
{
header: 'a header only'
},
{
content: 'content only'
}
];
getUsage(sections);
// header.js
sections = [
{
content: "",
raw: true
},
{
header: 'Synopsis',
content: [
'$ example [{bold --timeout} {underline ms}] {bold --src} {underline file} ...',
'$ example {bold --help}'
]
}
];
getUsage(sections);
// hide.js
usage = getUsage([
{
header: 'A typical app',
content: 'Generates something {italic very} important. This is a rather long, but ultimately inconsequential description intended solely to demonstrate description appearance. '
},
{
header: 'Options',
optionList: optionDefinitions,
hide: 'src'
},
{
content: 'Project home: {underline https://github.com/me/example}'
}
]);
// option-list-options.js
sections = [
{
header: 'A typical app',
content: 'Generates something {italic very} important.'
},
{
header: 'Options',
optionList: optionDefinitions,
tableOptions: {
columns: [
{
name: 'option',
noWrap: true,
padding: { left: '🔥 ', right: '' },
width: 30
},
{
name: 'description',
width: 50,
padding: { left: '', right: ' 🔥' }
}
]
}
}
];
getUsage(sections);
// simple-reverse-name-order.js
usage = getUsage([
{
header: 'A typical app',
content: 'Generates something {italic very} important. This is a rather long, but ultimately inconsequential description intended solely to demonstrate description appearance. '
},
{
header: 'Options',
optionList: optionDefinitions,
reverseNameOrder: true
},
{
content: 'Project home: {underline https://github.com/me/example}'
}
]);
// simple-width.js
usage = getUsage([
{
header: 'A typical app',
content: {
options: { maxWidth: 40 },
data: [
{ col: 'Generates something {italic very} important. This is a rather long, but ultimately inconsequential description intended solely to demonstrate description appearance. ' }
]
}
}
]);
// synopsis.js
sections = [
{
header: 'A typical app',
content: 'Generates something {italic very} important.'
},
{
header: 'Options',
optionList: [
{
name: 'input',
typeLabel: '{underline file}',
description: 'The input to process.'
},
{
name: 'help',
description: 'Print this usage guide.'
}
]
}
];
usage = getUsage(sections);
// whitespace.js
/* When using default options, the whitespace before the bullets is trimmed */
sections = [
{
header: 'Example app',
content: [
'Generates something {italic very} important. This description is:',
'',
' • rather long',
' • inconsequential',
' • demonstrative',
'',
'And the text continues underneath as this {cyan might} be required in cases where text is required underneath.'
]
}
];
usage = getUsage(sections);
/* Solution 1: Use `raw` option and supply your own whitespace */
sections = [
{
header: 'Example app',
content: [
' Generates something {italic very} important. This description is:',
' ',
' • rather long',
' • inconsequential',
' • demonstrative',
' ',
' And the text continues underneath as this {cyan might} be required in cases where',
' text is required underneath.'
],
raw: true
}
];
usage = getUsage(sections);
/* Section 2: use separate sections with the `noTrim` option on the bullets */
sections = [
{
header: 'Example app',
content: [
'Generates something {italic very} important. This description is:'
]
},
{
content: {
options: {
noTrim: true
},
data: [
{ col: ' • rather long' },
{ col: ' • inconsequential' },
{ col: ' • demonstrative' }
]
}
},
{
content: [
'And the text continues underneath as this {cyan might} be required in cases where text is required underneath.'
]
}
];
usage = getUsage(sections);

View File

@ -1,48 +1,82 @@
// Type definitions for command-line-usage 5.0
// Project: https://github.com/75lb/command-line-usage#readme
// Definitions by: Andrija Dvorski <https://github.com/Dvorsky>
// Definitions by: matrumz <https://github.com/matrumz>
// Andrija Dvorski <https://github.com/Dvorsky>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
/**
* Generates a usage guide suitable for a command-line app.
* @param sections One or more Section objects
* @alias module:command-line-usage
*/
declare function commandLineUsage(sections: commandLineUsage.Section | commandLineUsage.Section[]): string;
export = commandLineUsage;
declare namespace commandLineUsage {
interface Section {
list: string[];
/** Section object. */
type Section = Content | OptionList;
add(content: object): void;
emptyLine(): void;
header(text: string): void;
toString(): string;
}
interface SectionData {
optionList?: OptionListData[];
hide?: string[];
group?: string[];
/** A Content section comprises a header and one or more lines of content. */
interface Content {
/** The section header, always bold and underlined. */
header?: string;
reverseNameOrder?: boolean;
tableOptions?: any;
}
interface OptionListData extends SectionData {
name: string;
typeLabel?: string;
description?: string;
}
interface ContentSectionData extends SectionData {
content: string;
/**
* Overloaded property, accepting data in one of four formats.
* 1. A single string (one line of text).
* 2. An array of strings (multiple lines of text).
* 3. An array of objects (recordset-style data). In this case, the data will be rendered in table format. The property names of each object are not important, so long as they are
* consistent throughout the array.
* 4. An object with two properties - data and options. In this case, the data and options will be passed directly to the underlying table layout module for rendering.
*/
content?: string | string[] | any[] | { data: any; options: any };
/** Set to true to avoid indentation and wrapping. Useful for banners. */
raw?: boolean;
}
type CommandLineUsageInput =
SectionData
| SectionData[]
| OptionListData
| OptionListData[]
| ContentSectionData
| ContentSectionData[];
/** Describes a command-line option. Additionally, if generating a usage guide with command-line-usage you could optionally add description and typeLabel properties to each definition. */
interface OptionDefinition {
name: string;
/**
* The type value is a setter function (you receive the output from this), enabling you to be specific about the type and value received.
*
* The most common values used are String (the default), Number and Boolean but you can use a custom function.
*/
type?: any;
/** getopt-style short option names. Can be any single character (unicode included) except a digit or hyphen. */
alias?: string;
/** Set this flag if the option takes a list of values. You will receive an array of values, each passed through the type function (if specified). */
multiple?: boolean;
/** Identical to multiple but with greedy parsing disabled. */
lazyMultiple?: boolean;
/** Any values unaccounted for by an option definition will be set on the defaultOption. This flag is typically set on the most commonly-used option to make for more concise usage. */
defaultOption?: boolean;
/** An initial value for the option. */
defaultValue?: any;
/**
* When your app has a large amount of options it makes sense to organise them in groups.
*
* There are two automatic groups: _all (contains all options) and _none (contains options without a group specified in their definition).
*/
group?: string | string[];
/** A string describing the option. */
description?: string;
/** A string to replace the default type string (e.g. <string>). It's often more useful to set a more descriptive type label, like <ms>, <files>, <command>, etc.. */
typeLabel?: string;
}
/** A OptionList section adds a table displaying details of the available options. */
interface OptionList {
header?: string;
/** An array of option definition objects. */
optionList?: OptionDefinition[];
/** If specified, only options from this particular group will be printed. */
group?: string | string[];
/** The names of one of more option definitions to hide from the option list. */
hide?: string | string[];
/** If true, the option alias will be displayed after the name, i.e. --verbose, -v instead of -v, --verbose). */
reverseNameOrder?: boolean;
/** An options object suitable for passing into table-layout. */
tableOptions?: any;
}
}
declare function commandLineUsage(sections: commandLineUsage.CommandLineUsageInput): string | undefined | commandLineUsage.Section;
export = commandLineUsage;