@oclif/core 3.0.0-beta.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +4 -2
  2. package/flush.d.ts +3 -0
  3. package/flush.js +1 -0
  4. package/handle.js +1 -0
  5. package/lib/args.d.ts +2 -2
  6. package/lib/args.js +17 -18
  7. package/lib/{ux → cli-ux}/action/base.d.ts +19 -21
  8. package/lib/{ux → cli-ux}/action/base.js +126 -120
  9. package/lib/{ux → cli-ux}/action/simple.js +25 -30
  10. package/lib/{ux → cli-ux}/action/spinner.d.ts +9 -7
  11. package/lib/{ux → cli-ux}/action/spinner.js +45 -37
  12. package/lib/{ux → cli-ux}/action/spinners.js +187 -187
  13. package/lib/cli-ux/action/types.d.ts +5 -0
  14. package/lib/cli-ux/action/types.js +2 -0
  15. package/lib/{ux → cli-ux}/config.d.ts +5 -5
  16. package/lib/{ux → cli-ux}/config.js +17 -17
  17. package/lib/{ux → cli-ux}/exit.js +3 -0
  18. package/lib/cli-ux/flush.d.ts +1 -0
  19. package/lib/cli-ux/flush.js +28 -0
  20. package/lib/cli-ux/index.d.ts +39 -0
  21. package/lib/{ux → cli-ux}/index.js +74 -97
  22. package/lib/{ux → cli-ux}/list.js +3 -3
  23. package/lib/{ux → cli-ux}/prompt.d.ts +3 -3
  24. package/lib/{ux → cli-ux}/prompt.js +35 -25
  25. package/lib/{ux → cli-ux}/stream.d.ts +6 -6
  26. package/lib/{ux → cli-ux}/stream.js +11 -10
  27. package/lib/cli-ux/styled/index.d.ts +4 -0
  28. package/lib/cli-ux/styled/index.js +11 -0
  29. package/lib/{ux → cli-ux}/styled/object.js +7 -9
  30. package/lib/{ux → cli-ux}/styled/table.d.ts +10 -10
  31. package/lib/{ux → cli-ux}/styled/table.js +130 -133
  32. package/lib/{ux → cli-ux}/styled/tree.js +11 -13
  33. package/lib/cli-ux/wait.js +5 -0
  34. package/lib/command.d.ts +82 -88
  35. package/lib/command.js +196 -175
  36. package/lib/config/config.d.ts +89 -90
  37. package/lib/config/config.js +466 -566
  38. package/lib/config/index.d.ts +0 -1
  39. package/lib/config/index.js +1 -3
  40. package/lib/config/plugin-loader.d.ts +12 -12
  41. package/lib/config/plugin-loader.js +72 -56
  42. package/lib/config/plugin.d.ts +25 -24
  43. package/lib/config/plugin.js +188 -154
  44. package/lib/config/ts-node.d.ts +2 -1
  45. package/lib/config/ts-node.js +71 -58
  46. package/lib/config/util.d.ts +1 -11
  47. package/lib/config/util.js +6 -59
  48. package/lib/errors/config.d.ts +1 -1
  49. package/lib/errors/config.js +6 -6
  50. package/lib/errors/errors/cli.d.ts +7 -7
  51. package/lib/errors/errors/cli.js +20 -16
  52. package/lib/errors/errors/exit.d.ts +1 -4
  53. package/lib/errors/errors/exit.js +1 -1
  54. package/lib/errors/errors/module-load.d.ts +1 -4
  55. package/lib/errors/errors/module-load.js +1 -1
  56. package/lib/errors/errors/pretty-print.d.ts +1 -1
  57. package/lib/errors/errors/pretty-print.js +12 -10
  58. package/lib/errors/handle.d.ts +12 -2
  59. package/lib/errors/handle.js +26 -14
  60. package/lib/errors/index.d.ts +10 -10
  61. package/lib/errors/index.js +25 -24
  62. package/lib/errors/logger.d.ts +2 -2
  63. package/lib/errors/logger.js +14 -13
  64. package/lib/execute.d.ts +6 -6
  65. package/lib/execute.js +10 -9
  66. package/lib/flags.d.ts +103 -32
  67. package/lib/flags.js +79 -45
  68. package/lib/help/command.d.ts +16 -14
  69. package/lib/help/command.js +178 -163
  70. package/lib/help/docopts.d.ts +5 -5
  71. package/lib/help/docopts.js +50 -54
  72. package/lib/help/formatter.d.ts +37 -37
  73. package/lib/help/formatter.js +66 -55
  74. package/lib/help/index.d.ts +25 -21
  75. package/lib/help/index.js +169 -147
  76. package/lib/help/root.d.ts +1 -1
  77. package/lib/help/root.js +15 -17
  78. package/lib/help/util.d.ts +2 -8
  79. package/lib/help/util.js +8 -28
  80. package/lib/index.d.ts +19 -20
  81. package/lib/index.js +37 -43
  82. package/lib/interfaces/config.d.ts +67 -66
  83. package/lib/interfaces/errors.d.ts +5 -5
  84. package/lib/interfaces/help.d.ts +17 -17
  85. package/lib/interfaces/hooks.d.ts +49 -49
  86. package/lib/interfaces/index.d.ts +7 -7
  87. package/lib/interfaces/manifest.d.ts +1 -1
  88. package/lib/interfaces/parser.d.ts +175 -51
  89. package/lib/interfaces/pjson.d.ts +41 -41
  90. package/lib/interfaces/plugin.d.ts +47 -41
  91. package/lib/interfaces/s3-manifest.d.ts +7 -7
  92. package/lib/interfaces/topic.d.ts +1 -1
  93. package/lib/interfaces/ts-config.d.ts +7 -7
  94. package/lib/main.d.ts +2 -2
  95. package/lib/main.js +16 -16
  96. package/lib/module-loader.d.ts +67 -77
  97. package/lib/module-loader.js +183 -150
  98. package/lib/parser/errors.d.ts +7 -7
  99. package/lib/parser/errors.js +29 -22
  100. package/lib/parser/help.js +5 -5
  101. package/lib/parser/index.js +2 -2
  102. package/lib/parser/parse.d.ts +9 -6
  103. package/lib/parser/parse.js +253 -221
  104. package/lib/parser/validate.js +53 -33
  105. package/lib/performance.d.ts +43 -32
  106. package/lib/performance.js +133 -91
  107. package/lib/screen.js +2 -2
  108. package/lib/settings.d.ts +11 -12
  109. package/lib/settings.js +2 -2
  110. package/lib/util/aggregate-flags.d.ts +2 -0
  111. package/lib/util/aggregate-flags.js +13 -0
  112. package/lib/util/cache-command.d.ts +3 -0
  113. package/lib/util/cache-command.js +109 -0
  114. package/lib/util/cache-default-value.d.ts +2 -0
  115. package/lib/util/cache-default-value.js +28 -0
  116. package/lib/util/ensure-arg-object.d.ts +12 -0
  117. package/lib/util/ensure-arg-object.js +14 -0
  118. package/lib/util/fs.d.ts +7 -0
  119. package/lib/util/fs.js +54 -0
  120. package/lib/util/os.d.ts +19 -0
  121. package/lib/util/os.js +28 -0
  122. package/lib/{util.d.ts → util/util.d.ts} +7 -16
  123. package/lib/util/util.js +98 -0
  124. package/package.json +35 -37
  125. package/lib/util.js +0 -126
  126. package/lib/ux/flush.d.ts +0 -1
  127. package/lib/ux/flush.js +0 -27
  128. package/lib/ux/index.d.ts +0 -64
  129. package/lib/ux/styled/index.d.ts +0 -6
  130. package/lib/ux/styled/index.js +0 -13
  131. package/lib/ux/styled/json.d.ts +0 -1
  132. package/lib/ux/styled/json.js +0 -15
  133. package/lib/ux/wait.js +0 -7
  134. package/lib/{ux → cli-ux}/action/simple.d.ts +4 -4
  135. package/lib/{ux → cli-ux}/action/spinners.d.ts +117 -117
  136. package/lib/{ux → cli-ux}/exit.d.ts +2 -2
  137. package/lib/{ux → cli-ux}/list.d.ts +0 -0
  138. package/lib/{ux → cli-ux}/styled/object.d.ts +0 -0
  139. package/lib/{ux → cli-ux}/styled/progress.d.ts +0 -0
  140. package/lib/{ux → cli-ux}/styled/progress.js +0 -0
  141. package/lib/{ux → cli-ux}/styled/tree.d.ts +1 -1
  142. /package/lib/{ux → cli-ux}/wait.d.ts +0 -0
@@ -1,31 +1,33 @@
1
+ import { Command } from '../command';
1
2
  import * as Interfaces from '../interfaces';
2
3
  import { HelpFormatter, HelpSectionRenderer } from './formatter';
3
- import { Command } from '../command';
4
4
  export declare class CommandHelp extends HelpFormatter {
5
- command: Command.Class | Command.Loadable | Command.Cached;
5
+ command: Command.Cached | Command.Class | Command.Loadable;
6
6
  config: Interfaces.Config;
7
7
  opts: Interfaces.HelpOptions;
8
- constructor(command: Command.Class | Command.Loadable | Command.Cached, config: Interfaces.Config, opts: Interfaces.HelpOptions);
8
+ constructor(command: Command.Cached | Command.Class | Command.Loadable, config: Interfaces.Config, opts: Interfaces.HelpOptions);
9
+ private formatIfCommand;
10
+ private isCommand;
11
+ protected aliases(aliases: string[] | undefined): string | undefined;
12
+ protected arg(arg: Command.Arg.Any): string;
13
+ protected args(args: Command.Arg.Any[]): [string, string | undefined][] | undefined;
14
+ protected defaultUsage(): string;
15
+ protected description(): string | undefined;
16
+ protected examples(examples: Command.Example[] | string | undefined): string | undefined;
17
+ protected flagHelpLabel(flag: Command.Flag.Any, showOptions?: boolean): string;
18
+ protected flags(flags: Array<Command.Flag.Any>): [string, string | undefined][] | undefined;
19
+ protected flagsDescriptions(flags: Array<Command.Flag.Any>): string | undefined;
9
20
  generate(): string;
10
21
  protected groupFlags(flags: Array<Command.Flag.Any>): {
11
- mainFlags: Array<Command.Flag.Any>;
12
22
  flagGroups: {
13
23
  [name: string]: Array<Command.Flag.Any>;
14
24
  };
25
+ mainFlags: Array<Command.Flag.Any>;
15
26
  };
16
27
  protected sections(): Array<{
17
- header: string;
18
28
  generate: HelpSectionRenderer;
29
+ header: string;
19
30
  }>;
20
31
  protected usage(): string;
21
- protected defaultUsage(): string;
22
- protected description(): string | undefined;
23
- protected aliases(aliases: string[] | undefined): string | undefined;
24
- protected examples(examples: Command.Example[] | undefined | string): string | undefined;
25
- protected args(args: Command.Arg.Any[]): [string, string | undefined][] | undefined;
26
- protected arg(arg: Command.Arg.Any): string;
27
- protected flagHelpLabel(flag: Command.Flag.Any, showOptions?: boolean): string;
28
- protected flags(flags: Array<Command.Flag.Any>): [string, string | undefined][] | undefined;
29
- protected flagsDescriptions(flags: Array<Command.Flag.Any>): string | undefined;
30
32
  }
31
33
  export default CommandHelp;
@@ -1,126 +1,68 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CommandHelp = void 0;
4
- const chalk = require("chalk");
5
- const stripAnsi = require("strip-ansi");
6
- const util_1 = require("../util");
7
- const formatter_1 = require("./formatter");
4
+ const tslib_1 = require("tslib");
5
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const strip_ansi_1 = tslib_1.__importDefault(require("strip-ansi"));
7
+ const ensure_arg_object_1 = require("../util/ensure-arg-object");
8
+ const util_1 = require("../util/util");
8
9
  const docopts_1 = require("./docopts");
10
+ const formatter_1 = require("./formatter");
9
11
  // Don't use os.EOL because we need to ensure that a string
10
12
  // written on any platform, that may use \r\n or \n, will be
11
13
  // split on any platform, not just the os specific EOL at runtime.
12
14
  const POSSIBLE_LINE_FEED = /\r\n|\n/;
13
- const { underline, } = chalk;
14
- let { dim, } = chalk;
15
+ let { dim } = chalk_1.default;
15
16
  if (process.env.ConEmuANSI === 'ON') {
16
17
  // eslint-disable-next-line unicorn/consistent-destructuring
17
- dim = chalk.gray;
18
+ dim = chalk_1.default.gray;
18
19
  }
19
20
  class CommandHelp extends formatter_1.HelpFormatter {
21
+ command;
22
+ config;
23
+ opts;
20
24
  constructor(command, config, opts) {
21
25
  super(config, opts);
22
26
  this.command = command;
23
27
  this.config = config;
24
28
  this.opts = opts;
25
29
  }
26
- generate() {
27
- const cmd = this.command;
28
- const flags = (0, util_1.sortBy)(Object.entries(cmd.flags || {})
29
- .filter(([, v]) => !v.hidden)
30
- .map(([k, v]) => {
31
- v.name = k;
32
- return v;
33
- }), f => [!f.char, f.char, f.name]);
34
- const args = Object.values((0, util_1.ensureArgObject)(cmd.args)).filter(a => !a.hidden);
35
- const output = (0, util_1.compact)(this.sections().map(({ header, generate }) => {
36
- const body = generate({ cmd, flags, args }, header);
37
- // Generate can return a list of sections
38
- if (Array.isArray(body)) {
39
- return body.map(helpSection => helpSection && helpSection.body && this.section(helpSection.header, helpSection.body)).join('\n\n');
40
- }
41
- return body && this.section(header, body);
42
- })).join('\n\n');
43
- return output;
30
+ formatIfCommand(example) {
31
+ example = this.render(example);
32
+ if (example.startsWith(this.config.bin))
33
+ return dim(`$ ${example}`);
34
+ if (example.startsWith(`$ ${this.config.bin}`))
35
+ return dim(example);
36
+ return example;
44
37
  }
45
- groupFlags(flags) {
46
- const mainFlags = [];
47
- const flagGroups = {};
48
- for (const flag of flags) {
49
- const group = flag.helpGroup;
50
- if (group) {
51
- if (!flagGroups[group])
52
- flagGroups[group] = [];
53
- flagGroups[group].push(flag);
54
- }
55
- else {
56
- mainFlags.push(flag);
57
- }
58
- }
59
- return { mainFlags, flagGroups };
38
+ isCommand(example) {
39
+ return (0, strip_ansi_1.default)(this.formatIfCommand(example)).startsWith(`$ ${this.config.bin}`);
60
40
  }
61
- sections() {
62
- return [
63
- {
64
- header: this.opts.usageHeader || 'USAGE',
65
- generate: () => this.usage(),
66
- },
67
- {
68
- header: 'ARGUMENTS',
69
- generate: ({ args }, header) => [{ header, body: this.args(args) }],
70
- },
71
- {
72
- header: 'FLAGS',
73
- generate: ({ flags }, header) => {
74
- const { mainFlags, flagGroups } = this.groupFlags(flags);
75
- const flagSections = [];
76
- const mainFlagBody = this.flags(mainFlags);
77
- if (mainFlagBody)
78
- flagSections.push({ header, body: mainFlagBody });
79
- for (const [name, flags] of Object.entries(flagGroups)) {
80
- const body = this.flags(flags);
81
- if (body)
82
- flagSections.push({ header: `${name.toUpperCase()} ${header}`, body });
83
- }
84
- return (0, util_1.compact)(flagSections);
85
- },
86
- },
87
- {
88
- header: 'DESCRIPTION',
89
- generate: () => this.description(),
90
- },
91
- {
92
- header: 'ALIASES',
93
- generate: ({ cmd }) => this.aliases(cmd.aliases),
94
- },
95
- {
96
- header: 'EXAMPLES',
97
- generate: ({ cmd }) => {
98
- const examples = cmd.examples || cmd.example;
99
- return this.examples(examples);
100
- },
101
- },
102
- {
103
- header: 'FLAG DESCRIPTIONS',
104
- generate: ({ flags }) => this.flagsDescriptions(flags),
105
- },
106
- ];
107
- }
108
- usage() {
109
- const usage = this.command.usage;
110
- const body = (usage ? (0, util_1.castArray)(usage) : [this.defaultUsage()])
111
- .map(u => {
112
- const allowedSpacing = this.opts.maxWidth - this.indentSpacing;
113
- const line = `$ ${this.config.bin} ${u}`.trim();
114
- if (line.length > allowedSpacing) {
115
- const splitIndex = line.slice(0, Math.max(0, allowedSpacing)).lastIndexOf(' ');
116
- return line.slice(0, Math.max(0, splitIndex)) + '\n' +
117
- this.indent(this.wrap(line.slice(Math.max(0, splitIndex)), this.indentSpacing * 2));
118
- }
119
- return this.wrap(line);
120
- })
121
- .join('\n');
41
+ aliases(aliases) {
42
+ if (!aliases || aliases.length === 0)
43
+ return;
44
+ const body = aliases.map((a) => ['$', this.config.bin, a].join(' ')).join('\n');
122
45
  return body;
123
46
  }
47
+ arg(arg) {
48
+ const name = arg.name.toUpperCase();
49
+ if (arg.required)
50
+ return `${name}`;
51
+ return `[${name}]`;
52
+ }
53
+ args(args) {
54
+ if (args.filter((a) => a.description).length === 0)
55
+ return;
56
+ return args.map((a) => {
57
+ const name = a.name.toUpperCase();
58
+ let description = a.description || '';
59
+ if (a.default)
60
+ description = `[default: ${a.default}] ${description}`;
61
+ if (a.options)
62
+ description = `(${a.options.join('|')}) ${description}`;
63
+ return [name, description ? dim(description) : undefined];
64
+ });
65
+ }
124
66
  defaultUsage() {
125
67
  // Docopts by default
126
68
  if (this.opts.docopts === undefined || this.opts.docopts) {
@@ -128,7 +70,10 @@ class CommandHelp extends formatter_1.HelpFormatter {
128
70
  }
129
71
  return (0, util_1.compact)([
130
72
  this.command.id,
131
- Object.values(this.command.args ?? {})?.filter(a => !a.hidden).map(a => this.arg(a)).join(' '),
73
+ Object.values(this.command.args ?? {})
74
+ ?.filter((a) => !a.hidden)
75
+ .map((a) => this.arg(a))
76
+ .join(' '),
132
77
  ]).join(' ');
133
78
  }
134
79
  description() {
@@ -139,88 +84,52 @@ class CommandHelp extends formatter_1.HelpFormatter {
139
84
  }
140
85
  else if (cmd.description) {
141
86
  const summary = cmd.summary ? `${cmd.summary}\n` : null;
142
- description = summary ? [
143
- ...summary.split(POSSIBLE_LINE_FEED),
144
- ...(cmd.description || '').split(POSSIBLE_LINE_FEED),
145
- ] : (cmd.description || '').split(POSSIBLE_LINE_FEED);
87
+ description = summary
88
+ ? [...summary.split(POSSIBLE_LINE_FEED), ...(cmd.description || '').split(POSSIBLE_LINE_FEED)]
89
+ : (cmd.description || '').split(POSSIBLE_LINE_FEED);
146
90
  }
147
91
  if (description) {
148
92
  return this.wrap(description.join('\n'));
149
93
  }
150
94
  }
151
- aliases(aliases) {
152
- if (!aliases || aliases.length === 0)
153
- return;
154
- const body = aliases.map(a => ['$', this.config.bin, a].join(' ')).join('\n');
155
- return body;
156
- }
157
95
  examples(examples) {
158
96
  if (!examples || examples.length === 0)
159
97
  return;
160
- const formatIfCommand = (example) => {
161
- example = this.render(example);
162
- if (example.startsWith(this.config.bin))
163
- return dim(`$ ${example}`);
164
- if (example.startsWith(`$ ${this.config.bin}`))
165
- return dim(example);
166
- return example;
167
- };
168
- const isCommand = (example) => stripAnsi(formatIfCommand(example)).startsWith(`$ ${this.config.bin}`);
169
- const body = (0, util_1.castArray)(examples).map(a => {
98
+ const body = (0, util_1.castArray)(examples)
99
+ .map((a) => {
170
100
  let description;
171
101
  let commands;
172
102
  if (typeof a === 'string') {
173
- const lines = a
174
- .split(POSSIBLE_LINE_FEED)
175
- .filter(line => Boolean(line));
103
+ const lines = a.split(POSSIBLE_LINE_FEED).filter(Boolean);
176
104
  // If the example is <description>\n<command> then format correctly
177
- // eslint-disable-next-line unicorn/no-array-callback-reference
178
- if (lines.length >= 2 && !isCommand(lines[0]) && lines.slice(1).every(isCommand)) {
105
+ if (lines.length >= 2 && !this.isCommand(lines[0]) && lines.slice(1).every((i) => this.isCommand(i))) {
179
106
  description = lines[0];
180
107
  commands = lines.slice(1);
181
108
  }
182
109
  else {
183
- return lines.map(line => formatIfCommand(line)).join('\n');
110
+ return lines.map((line) => this.formatIfCommand(line)).join('\n');
184
111
  }
185
112
  }
186
113
  else {
187
114
  description = a.description;
188
115
  commands = [a.command];
189
116
  }
190
- const multilineSeparator = this.config.platform === 'win32' ?
191
- (this.config.shell.includes('powershell') ? '`' : '^') :
192
- '\\';
117
+ const multilineSeparator = this.config.platform === 'win32' ? (this.config.shell.includes('powershell') ? '`' : '^') : '\\';
193
118
  // The command will be indented in the section, which is also indented
194
119
  const finalIndentedSpacing = this.indentSpacing * 2;
195
- const multilineCommands = commands.map(c => {
196
- // First indent keeping room for escaped newlines
197
- return this.indent(this.wrap(formatIfCommand(c), finalIndentedSpacing + 4))
198
- // Then add the escaped newline
199
- .split(POSSIBLE_LINE_FEED).join(` ${multilineSeparator}\n `);
200
- }).join('\n');
120
+ const multilineCommands = commands
121
+ .map((c) =>
122
+ // First indent keeping room for escaped newlines
123
+ this.indent(this.wrap(this.formatIfCommand(c), finalIndentedSpacing + 4))
124
+ // Then add the escaped newline
125
+ .split(POSSIBLE_LINE_FEED)
126
+ .join(` ${multilineSeparator}\n `))
127
+ .join('\n');
201
128
  return `${this.wrap(description, finalIndentedSpacing)}\n\n${multilineCommands}`;
202
- }).join('\n\n');
129
+ })
130
+ .join('\n\n');
203
131
  return body;
204
132
  }
205
- args(args) {
206
- if (args.filter(a => a.description).length === 0)
207
- return;
208
- return args.map(a => {
209
- const name = a.name.toUpperCase();
210
- let description = a.description || '';
211
- if (a.default)
212
- description = `[default: ${a.default}] ${description}`;
213
- if (a.options)
214
- description = `(${a.options.join('|')}) ${description}`;
215
- return [name, description ? dim(description) : undefined];
216
- });
217
- }
218
- arg(arg) {
219
- const name = arg.name.toUpperCase();
220
- if (arg.required)
221
- return `${name}`;
222
- return `[${name}]`;
223
- }
224
133
  flagHelpLabel(flag, showOptions = false) {
225
134
  let label = flag.helpLabel;
226
135
  if (!label) {
@@ -245,7 +154,7 @@ class CommandHelp extends formatter_1.HelpFormatter {
245
154
  if (flag.multiple)
246
155
  value += '...';
247
156
  if (!value.includes('|'))
248
- value = underline(value);
157
+ value = chalk_1.default.underline(value);
249
158
  label += `=${value}`;
250
159
  }
251
160
  return label;
@@ -253,7 +162,7 @@ class CommandHelp extends formatter_1.HelpFormatter {
253
162
  flags(flags) {
254
163
  if (flags.length === 0)
255
164
  return;
256
- return flags.map(flag => {
165
+ return flags.map((flag) => {
257
166
  const left = this.flagHelpLabel(flag);
258
167
  let right = flag.summary || flag.description || '';
259
168
  if (flag.type === 'option' && flag.default) {
@@ -268,16 +177,122 @@ class CommandHelp extends formatter_1.HelpFormatter {
268
177
  });
269
178
  }
270
179
  flagsDescriptions(flags) {
271
- const flagsWithExtendedDescriptions = flags.filter(flag => flag.summary && flag.description);
180
+ const flagsWithExtendedDescriptions = flags.filter((flag) => flag.summary && flag.description);
272
181
  if (flagsWithExtendedDescriptions.length === 0)
273
182
  return;
274
- const body = flagsWithExtendedDescriptions.map(flag => {
183
+ const body = flagsWithExtendedDescriptions
184
+ .map((flag) => {
275
185
  // Guaranteed to be set because of the filter above, but make ts happy
276
186
  const summary = flag.summary || '';
277
187
  let flagHelp = this.flagHelpLabel(flag, true);
278
- flagHelp += flagHelp.length + summary.length + 2 < this.opts.maxWidth ? ' ' + summary : '\n\n' + this.indent(this.wrap(summary, this.indentSpacing * 2));
188
+ flagHelp +=
189
+ flagHelp.length + summary.length + 2 < this.opts.maxWidth
190
+ ? ' ' + summary
191
+ : '\n\n' + this.indent(this.wrap(summary, this.indentSpacing * 2));
279
192
  return `${flagHelp}\n\n${this.indent(this.wrap(flag.description || '', this.indentSpacing * 2))}`;
280
- }).join('\n\n');
193
+ })
194
+ .join('\n\n');
195
+ return body;
196
+ }
197
+ generate() {
198
+ const cmd = this.command;
199
+ const flags = (0, util_1.sortBy)(Object.entries(cmd.flags || {})
200
+ .filter(([, v]) => !v.hidden)
201
+ .map(([k, v]) => {
202
+ v.name = k;
203
+ return v;
204
+ }), (f) => [!f.char, f.char, f.name]);
205
+ const args = Object.values((0, ensure_arg_object_1.ensureArgObject)(cmd.args)).filter((a) => !a.hidden);
206
+ const output = (0, util_1.compact)(this.sections().map(({ generate, header }) => {
207
+ const body = generate({ args, cmd, flags }, header);
208
+ // Generate can return a list of sections
209
+ if (Array.isArray(body)) {
210
+ return body
211
+ .map((helpSection) => helpSection && helpSection.body && this.section(helpSection.header, helpSection.body))
212
+ .join('\n\n');
213
+ }
214
+ return body && this.section(header, body);
215
+ })).join('\n\n');
216
+ return output;
217
+ }
218
+ groupFlags(flags) {
219
+ const mainFlags = [];
220
+ const flagGroups = {};
221
+ for (const flag of flags) {
222
+ const group = flag.helpGroup;
223
+ if (group) {
224
+ if (!flagGroups[group])
225
+ flagGroups[group] = [];
226
+ flagGroups[group].push(flag);
227
+ }
228
+ else {
229
+ mainFlags.push(flag);
230
+ }
231
+ }
232
+ return { flagGroups, mainFlags };
233
+ }
234
+ sections() {
235
+ return [
236
+ {
237
+ generate: () => this.usage(),
238
+ header: this.opts.usageHeader || 'USAGE',
239
+ },
240
+ {
241
+ generate: ({ args }, header) => [{ body: this.args(args), header }],
242
+ header: 'ARGUMENTS',
243
+ },
244
+ {
245
+ generate: ({ flags }, header) => {
246
+ const { flagGroups, mainFlags } = this.groupFlags(flags);
247
+ const flagSections = [];
248
+ const mainFlagBody = this.flags(mainFlags);
249
+ if (mainFlagBody)
250
+ flagSections.push({ body: mainFlagBody, header });
251
+ for (const [name, flags] of Object.entries(flagGroups)) {
252
+ const body = this.flags(flags);
253
+ if (body)
254
+ flagSections.push({ body, header: `${name.toUpperCase()} ${header}` });
255
+ }
256
+ return (0, util_1.compact)(flagSections);
257
+ },
258
+ header: 'FLAGS',
259
+ },
260
+ {
261
+ generate: () => this.description(),
262
+ header: 'DESCRIPTION',
263
+ },
264
+ {
265
+ generate: ({ cmd }) => this.aliases(cmd.aliases),
266
+ header: 'ALIASES',
267
+ },
268
+ {
269
+ generate: ({ cmd }) => {
270
+ const examples = cmd.examples || cmd.example;
271
+ return this.examples(examples);
272
+ },
273
+ header: 'EXAMPLES',
274
+ },
275
+ {
276
+ generate: ({ flags }) => this.flagsDescriptions(flags),
277
+ header: 'FLAG DESCRIPTIONS',
278
+ },
279
+ ];
280
+ }
281
+ usage() {
282
+ const { usage } = this.command;
283
+ const body = (usage ? (0, util_1.castArray)(usage) : [this.defaultUsage()])
284
+ .map((u) => {
285
+ const allowedSpacing = this.opts.maxWidth - this.indentSpacing;
286
+ const line = `$ ${this.config.bin} ${u}`.trim();
287
+ if (line.length > allowedSpacing) {
288
+ const splitIndex = line.slice(0, Math.max(0, allowedSpacing)).lastIndexOf(' ');
289
+ return (line.slice(0, Math.max(0, splitIndex)) +
290
+ '\n' +
291
+ this.indent(this.wrap(line.slice(Math.max(0, splitIndex)), this.indentSpacing * 2)));
292
+ }
293
+ return this.wrap(line);
294
+ })
295
+ .join('\n');
281
296
  return body;
282
297
  }
283
298
  }
@@ -57,12 +57,12 @@ import { Command } from '../command';
57
57
  */
58
58
  export declare class DocOpts {
59
59
  private cmd;
60
- private flagMap;
61
60
  private flagList;
62
- constructor(cmd: Command.Class | Command.Loadable | Command.Cached);
63
- static generate(cmd: Command.Class | Command.Loadable | Command.Cached): string;
64
- toString(): string;
65
- private groupFlagElements;
61
+ private flagMap;
62
+ constructor(cmd: Command.Cached | Command.Class | Command.Loadable);
63
+ static generate(cmd: Command.Cached | Command.Class | Command.Loadable): string;
66
64
  private combineElementsToFlag;
67
65
  private generateElements;
66
+ private groupFlagElements;
67
+ toString(): string;
68
68
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DocOpts = void 0;
4
- const util_1 = require("../util");
4
+ const ensure_arg_object_1 = require("../util/ensure-arg-object");
5
5
  /**
6
6
  * DocOpts - See http://docopt.org/.
7
7
  *
@@ -59,6 +59,9 @@ const util_1 = require("../util");
59
59
  *
60
60
  */
61
61
  class DocOpts {
62
+ cmd;
63
+ flagList;
64
+ flagMap;
62
65
  constructor(cmd) {
63
66
  this.cmd = cmd;
64
67
  // Create a new map with references to the flags that we can manipulate.
@@ -73,53 +76,6 @@ class DocOpts {
73
76
  static generate(cmd) {
74
77
  return new DocOpts(cmd).toString();
75
78
  }
76
- toString() {
77
- const opts = this.cmd.id === '.' || this.cmd.id === '' ? [] : ['<%= command.id %>'];
78
- if (this.cmd.args) {
79
- const a = Object.values((0, util_1.ensureArgObject)(this.cmd.args)).map(arg => {
80
- return arg.required ? arg.name.toUpperCase() : `[${arg.name.toUpperCase()}]`;
81
- }) || [];
82
- opts.push(...a);
83
- }
84
- try {
85
- opts.push(...Object.values(this.groupFlagElements()));
86
- }
87
- catch {
88
- // If there is an error, just return no usage so we don't fail command help.
89
- opts.push(...this.flagList.map(flag => {
90
- const name = flag.char ? `-${flag.char}` : `--${flag.name}`;
91
- if (flag.type === 'boolean')
92
- return name;
93
- return `${name}=<value>`;
94
- }));
95
- }
96
- return opts.join(' ');
97
- }
98
- groupFlagElements() {
99
- const elementMap = {};
100
- // Generate all doc opt elements for combining
101
- // Show required flags first
102
- this.generateElements(elementMap, this.flagList.filter(flag => flag.required));
103
- // Then show optional flags
104
- this.generateElements(elementMap, this.flagList.filter(flag => !flag.required));
105
- for (const flag of this.flagList) {
106
- if (Array.isArray(flag.dependsOn)) {
107
- this.combineElementsToFlag(elementMap, flag.name, flag.dependsOn, ' ');
108
- }
109
- if (Array.isArray(flag.exclusive)) {
110
- this.combineElementsToFlag(elementMap, flag.name, flag.exclusive, ' | ');
111
- }
112
- }
113
- // Since combineElementsToFlag deletes the references in this.flags when it combines
114
- // them, this will go through the remaining list of uncombined elements.
115
- for (const remainingFlagName of Object.keys(this.flagMap)) {
116
- const remainingFlag = this.flagMap[remainingFlagName] || {};
117
- if (!remainingFlag.required) {
118
- elementMap[remainingFlag.name] = `[${elementMap[remainingFlag.name] || ''}]`;
119
- }
120
- }
121
- return elementMap;
122
- }
123
79
  combineElementsToFlag(elementMap, flagName, flagNames, unionString) {
124
80
  if (!this.flagMap[flagName]) {
125
81
  return;
@@ -134,12 +90,7 @@ class DocOpts {
134
90
  delete elementMap[toCombine];
135
91
  delete this.flagMap[toCombine];
136
92
  }
137
- if (isRequired) {
138
- elementMap[flagName] = `(${elementMap[flagName] || ''})`;
139
- }
140
- else {
141
- elementMap[flagName] = `[${elementMap[flagName] || ''}]`;
142
- }
93
+ elementMap[flagName] = isRequired ? `(${elementMap[flagName] || ''})` : `[${elementMap[flagName] || ''}]`;
143
94
  // We handled this flag, don't handle it again
144
95
  delete this.flagMap[flagName];
145
96
  }
@@ -158,5 +109,50 @@ class DocOpts {
158
109
  }
159
110
  return elementStrs;
160
111
  }
112
+ groupFlagElements() {
113
+ const elementMap = {};
114
+ // Generate all doc opt elements for combining
115
+ // Show required flags first
116
+ this.generateElements(elementMap, this.flagList.filter((flag) => flag.required));
117
+ // Then show optional flags
118
+ this.generateElements(elementMap, this.flagList.filter((flag) => !flag.required));
119
+ for (const flag of this.flagList) {
120
+ if (Array.isArray(flag.dependsOn)) {
121
+ this.combineElementsToFlag(elementMap, flag.name, flag.dependsOn, ' ');
122
+ }
123
+ if (Array.isArray(flag.exclusive)) {
124
+ this.combineElementsToFlag(elementMap, flag.name, flag.exclusive, ' | ');
125
+ }
126
+ }
127
+ // Since combineElementsToFlag deletes the references in this.flags when it combines
128
+ // them, this will go through the remaining list of uncombined elements.
129
+ for (const remainingFlagName of Object.keys(this.flagMap)) {
130
+ const remainingFlag = this.flagMap[remainingFlagName] || {};
131
+ if (!remainingFlag.required) {
132
+ elementMap[remainingFlag.name] = `[${elementMap[remainingFlag.name] || ''}]`;
133
+ }
134
+ }
135
+ return elementMap;
136
+ }
137
+ toString() {
138
+ const opts = this.cmd.id === '.' || this.cmd.id === '' ? [] : ['<%= command.id %>'];
139
+ if (this.cmd.args) {
140
+ const a = Object.values((0, ensure_arg_object_1.ensureArgObject)(this.cmd.args)).map((arg) => arg.required ? arg.name.toUpperCase() : `[${arg.name.toUpperCase()}]`) || [];
141
+ opts.push(...a);
142
+ }
143
+ try {
144
+ opts.push(...Object.values(this.groupFlagElements()));
145
+ }
146
+ catch {
147
+ // If there is an error, just return no usage so we don't fail command help.
148
+ opts.push(...this.flagList.map((flag) => {
149
+ const name = flag.char ? `-${flag.char}` : `--${flag.name}`;
150
+ if (flag.type === 'boolean')
151
+ return name;
152
+ return `${name}=<value>`;
153
+ }));
154
+ }
155
+ return opts.join(' ');
156
+ }
161
157
  }
162
158
  exports.DocOpts = DocOpts;