@oclif/core 3.10.8 → 3.11.1-dev.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.
@@ -37,4 +37,5 @@ export { Config, config } from './config';
37
37
  export { ExitError } from './exit';
38
38
  export { IPromptOptions } from './prompt';
39
39
  export { Table } from './styled';
40
+ export { colorize } from './theme';
40
41
  export { default as write } from './write';
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.write = exports.Table = exports.ExitError = exports.config = exports.Config = exports.ActionBase = exports.warn = exports.wait = exports.url = exports.tree = exports.trace = exports.table = exports.styledObject = exports.styledJSON = exports.styledHeader = exports.prompt = exports.progress = exports.logToStderr = exports.log = exports.info = exports.flush = exports.exit = exports.error = exports.done = exports.debug = exports.confirm = exports.anykey = exports.annotation = exports.action = exports.ux = void 0;
29
+ exports.write = exports.colorize = exports.Table = exports.ExitError = exports.config = exports.Config = exports.ActionBase = exports.warn = exports.wait = exports.url = exports.tree = exports.trace = exports.table = exports.styledObject = exports.styledJSON = exports.styledHeader = exports.prompt = exports.progress = exports.logToStderr = exports.log = exports.info = exports.flush = exports.exit = exports.error = exports.done = exports.debug = exports.confirm = exports.anykey = exports.annotation = exports.action = exports.ux = void 0;
30
30
  const chalk_1 = __importDefault(require("chalk"));
31
31
  const node_util_1 = require("node:util");
32
32
  const Errors = __importStar(require("../errors"));
@@ -177,5 +177,7 @@ var exit_1 = require("./exit");
177
177
  Object.defineProperty(exports, "ExitError", { enumerable: true, get: function () { return exit_1.ExitError; } });
178
178
  var styled_1 = require("./styled");
179
179
  Object.defineProperty(exports, "Table", { enumerable: true, get: function () { return styled_1.Table; } });
180
+ var theme_1 = require("./theme");
181
+ Object.defineProperty(exports, "colorize", { enumerable: true, get: function () { return theme_1.colorize; } });
180
182
  var write_2 = require("./write");
181
183
  Object.defineProperty(exports, "write", { enumerable: true, get: function () { return __importDefault(write_2).default; } });
@@ -0,0 +1,12 @@
1
+ import * as Color from 'color';
2
+ import { StandardChalk, Theme, Themes } from '../interfaces/theme';
3
+ /**
4
+ * Add color to text.
5
+ * @param color color to use. Can be hex code (e.g. `#ff0000`), rgb (e.g. `rgb(255, 255, 255)`) or a chalk color (e.g. `red`)
6
+ * @param text string to colorize
7
+ * @returns colorized string
8
+ */
9
+ export declare function colorize(color: Color | StandardChalk | undefined, text: string): string;
10
+ export declare function parseTheme(theme: Themes): Theme;
11
+ export declare function getColor(color: string): Color;
12
+ export declare function getColor(color: StandardChalk): StandardChalk;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.getColor = exports.parseTheme = exports.colorize = void 0;
30
+ const chalk_1 = __importDefault(require("chalk"));
31
+ const Color = __importStar(require("color"));
32
+ const theme_1 = require("../interfaces/theme");
33
+ function isStandardChalk(color) {
34
+ return theme_1.STANDARD_CHALK.includes(color);
35
+ }
36
+ /**
37
+ * Add color to text.
38
+ * @param color color to use. Can be hex code (e.g. `#ff0000`), rgb (e.g. `rgb(255, 255, 255)`) or a chalk color (e.g. `red`)
39
+ * @param text string to colorize
40
+ * @returns colorized string
41
+ */
42
+ function colorize(color, text) {
43
+ if (isStandardChalk(color))
44
+ return chalk_1.default[color](text);
45
+ return color ? chalk_1.default.hex(color.hex())(text) : text;
46
+ }
47
+ exports.colorize = colorize;
48
+ function parseTheme(theme) {
49
+ const themes = theme.themes ?? {};
50
+ const selected = theme.selected ? themes[theme.selected] ?? {} : {};
51
+ return Object.fromEntries(Object.entries(selected)
52
+ .map(([key, value]) => [key, getColor(value)])
53
+ .filter(([_, value]) => value));
54
+ }
55
+ exports.parseTheme = parseTheme;
56
+ function getColor(color) {
57
+ try {
58
+ // eslint-disable-next-line new-cap
59
+ return isStandardChalk(color) ? color : new Color.default(color);
60
+ }
61
+ catch { }
62
+ }
63
+ exports.getColor = getColor;
package/lib/command.js CHANGED
@@ -37,6 +37,7 @@ const util_1 = require("./help/util");
37
37
  const Parser = __importStar(require("./parser"));
38
38
  const aggregate_flags_1 = require("./util/aggregate-flags");
39
39
  const fs_1 = require("./util/fs");
40
+ const ids_1 = require("./util/ids");
40
41
  const util_2 = require("./util/util");
41
42
  const pjson = (0, fs_1.requireJson)(__dirname, '..', 'package.json');
42
43
  /**
@@ -260,12 +261,12 @@ class Command {
260
261
  warnIfCommandDeprecated() {
261
262
  const [id] = (0, util_1.normalizeArgv)(this.config);
262
263
  if (this.ctor.deprecateAliases && this.ctor.aliases.includes(id)) {
263
- const cmdName = (0, util_1.toConfiguredId)(this.ctor.id, this.config);
264
- const aliasName = (0, util_1.toConfiguredId)(id, this.config);
264
+ const cmdName = (0, ids_1.toConfiguredId)(this.ctor.id, this.config);
265
+ const aliasName = (0, ids_1.toConfiguredId)(id, this.config);
265
266
  this.warn((0, util_1.formatCommandDeprecationWarning)(aliasName, { to: cmdName }));
266
267
  }
267
268
  if (this.ctor.state === 'deprecated') {
268
- const cmdName = (0, util_1.toConfiguredId)(this.ctor.id, this.config);
269
+ const cmdName = (0, ids_1.toConfiguredId)(this.ctor.id, this.config);
269
270
  this.warn((0, util_1.formatCommandDeprecationWarning)(cmdName, this.ctor.deprecationOptions));
270
271
  }
271
272
  }
@@ -2,6 +2,7 @@ import { Command } from '../command';
2
2
  import { Hook, Hooks, PJSON, Topic } from '../interfaces';
3
3
  import { ArchTypes, Config as IConfig, LoadOptions, PlatformTypes, VersionDetails } from '../interfaces/config';
4
4
  import { Plugin as IPlugin, Options } from '../interfaces/plugin';
5
+ import { Theme, Themes } from '../interfaces/theme';
5
6
  export declare class Config implements IConfig {
6
7
  options: Options;
7
8
  arch: ArchTypes;
@@ -25,6 +26,7 @@ export declare class Config implements IConfig {
25
26
  plugins: Map<string, IPlugin>;
26
27
  root: string;
27
28
  shell: string;
29
+ theme?: Theme;
28
30
  topicSeparator: ' ' | ':';
29
31
  userAgent: string;
30
32
  userPJSON?: PJSON.User;
@@ -90,6 +92,11 @@ export declare class Config implements IConfig {
90
92
  loadPluginsAndCommands(opts?: {
91
93
  force: boolean;
92
94
  }): Promise<void>;
95
+ loadThemes(): Promise<{
96
+ file: string;
97
+ activeTheme: Theme | undefined;
98
+ themes: Themes | undefined;
99
+ }>;
93
100
  protected macosCacheDir(): string | undefined;
94
101
  runCommand<T = unknown>(id: string, argv?: string[], cachedCommand?: Command.Loadable | null): Promise<T>;
95
102
  runHook<T extends keyof Hooks>(event: T, opts: Hooks[T]['options'], timeout?: number, captureErrors?: boolean): Promise<Hook.Result<Hooks[T]['return']>>;
@@ -33,6 +33,7 @@ const node_os_1 = require("node:os");
33
33
  const node_path_1 = require("node:path");
34
34
  const node_url_1 = require("node:url");
35
35
  const cli_ux_1 = require("../cli-ux");
36
+ const theme_1 = require("../cli-ux/theme");
36
37
  const errors_1 = require("../errors");
37
38
  const util_1 = require("../help/util");
38
39
  const module_loader_1 = require("../module-loader");
@@ -105,6 +106,7 @@ class Config {
105
106
  plugins = new Map();
106
107
  root;
107
108
  shell;
109
+ theme;
108
110
  topicSeparator = ':';
109
111
  userAgent;
110
112
  userPJSON;
@@ -296,6 +298,10 @@ class Config {
296
298
  this.errlog = (0, node_path_1.join)(this.cacheDir, 'error.log');
297
299
  this.binPath = this.scopedEnvVar('BINPATH');
298
300
  this.npmRegistry = this.scopedEnvVar('NPM_REGISTRY') || this.pjson.oclif.npmRegistry;
301
+ if (!this.scopedEnvVarTrue('DISABLE_THEME')) {
302
+ const { activeTheme } = await this.loadThemes();
303
+ this.theme = activeTheme;
304
+ }
299
305
  this.pjson.oclif.update = this.pjson.oclif.update || {};
300
306
  this.pjson.oclif.update.node = this.pjson.oclif.update.node || {};
301
307
  const s3 = this.pjson.oclif.update.s3 || {};
@@ -351,6 +357,18 @@ class Config {
351
357
  this.warn(error);
352
358
  }
353
359
  }
360
+ async loadThemes() {
361
+ const themesFile = this.pjson.oclif.themesFile
362
+ ? (0, node_path_1.resolve)(this.root, this.pjson.oclif.themesFile)
363
+ : (0, node_path_1.resolve)(this.configDir, 'themes.json');
364
+ const themes = await (0, fs_1.safeReadJson)(themesFile);
365
+ const activeTheme = themes ? (0, theme_1.parseTheme)(themes) : undefined;
366
+ return {
367
+ activeTheme,
368
+ file: themesFile,
369
+ themes,
370
+ };
371
+ }
354
372
  macosCacheDir() {
355
373
  return (this.platform === 'darwin' && (0, node_path_1.join)(this.home, 'Library', 'Caches', this.dirname)) || undefined;
356
374
  }
@@ -537,7 +555,7 @@ class Config {
537
555
  .map((alias) => [alias.replaceAll('@', '').replaceAll(/[/-]/g, '_'), k].join('_').toUpperCase());
538
556
  }
539
557
  scopedEnvVarTrue(k) {
540
- const v = process.env[this.scopedEnvVarKeys(k).find((k) => process.env[k])];
558
+ const v = this.scopedEnvVar(k);
541
559
  return v === '1' || v === 'true';
542
560
  }
543
561
  warn(err, scope) {
@@ -6,7 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CommandHelp = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const strip_ansi_1 = __importDefault(require("strip-ansi"));
9
+ const theme_1 = require("../cli-ux/theme");
9
10
  const ensure_arg_object_1 = require("../util/ensure-arg-object");
11
+ const ids_1 = require("../util/ids");
10
12
  const util_1 = require("../util/util");
11
13
  const docopts_1 = require("./docopts");
12
14
  const formatter_1 = require("./formatter");
@@ -14,11 +16,6 @@ const formatter_1 = require("./formatter");
14
16
  // written on any platform, that may use \r\n or \n, will be
15
17
  // split on any platform, not just the os specific EOL at runtime.
16
18
  const POSSIBLE_LINE_FEED = /\r\n|\n/;
17
- let { dim } = chalk_1.default;
18
- if (process.env.ConEmuANSI === 'ON') {
19
- // eslint-disable-next-line unicorn/consistent-destructuring
20
- dim = chalk_1.default.gray;
21
- }
22
19
  class CommandHelp extends formatter_1.HelpFormatter {
23
20
  command;
24
21
  config;
@@ -32,7 +29,13 @@ class CommandHelp extends formatter_1.HelpFormatter {
32
29
  aliases(aliases) {
33
30
  if (!aliases || aliases.length === 0)
34
31
  return;
35
- const body = aliases.map((a) => ['$', this.config.bin, a].join(' ')).join('\n');
32
+ const body = aliases
33
+ .map((a) => [
34
+ (0, theme_1.colorize)(this.config?.theme?.dollarSign, '$'),
35
+ (0, theme_1.colorize)(this.config?.theme?.bin, this.config.bin),
36
+ (0, theme_1.colorize)(this.config?.theme?.alias, a),
37
+ ].join(' '))
38
+ .join('\n');
36
39
  return body;
37
40
  }
38
41
  arg(arg) {
@@ -48,10 +51,13 @@ class CommandHelp extends formatter_1.HelpFormatter {
48
51
  const name = a.name.toUpperCase();
49
52
  let description = a.description || '';
50
53
  if (a.default)
51
- description = `[default: ${a.default}] ${description}`;
54
+ description = `${(0, theme_1.colorize)(this.config?.theme?.flagDefaultValue, `[default: ${a.default}]`)} ${description}`;
52
55
  if (a.options)
53
- description = `(${a.options.join('|')}) ${description}`;
54
- return [name, description ? dim(description) : undefined];
56
+ description = `${(0, theme_1.colorize)(this.config?.theme?.flagOptions, `(${a.options.join('|')})`)} ${description}`;
57
+ return [
58
+ (0, theme_1.colorize)(this.config?.theme?.flag, name),
59
+ description ? (0, theme_1.colorize)(this.config?.theme?.sectionDescription, description) : undefined,
60
+ ];
55
61
  });
56
62
  }
57
63
  defaultUsage() {
@@ -125,8 +131,7 @@ class CommandHelp extends formatter_1.HelpFormatter {
125
131
  let label = flag.helpLabel;
126
132
  if (!label) {
127
133
  const labels = [];
128
- if (flag.char)
129
- labels.push(`-${flag.char[0]}`);
134
+ labels.push(flag.char ? `-${flag.char[0]}` : ' ');
130
135
  if (flag.name) {
131
136
  if (flag.type === 'boolean' && flag.allowNo) {
132
137
  labels.push(`--[no-]${flag.name.trim()}`);
@@ -135,7 +140,7 @@ class CommandHelp extends formatter_1.HelpFormatter {
135
140
  labels.push(`--${flag.name.trim()}`);
136
141
  }
137
142
  }
138
- label = labels.join(', ');
143
+ label = labels.join((0, theme_1.colorize)(this.config?.theme?.flagSeparator, flag.char ? ', ' : ' '));
139
144
  }
140
145
  if (flag.type === 'option') {
141
146
  let value = flag.helpValue || (this.opts.showFlagNameInTitle ? flag.name : '<value>');
@@ -153,18 +158,21 @@ class CommandHelp extends formatter_1.HelpFormatter {
153
158
  flags(flags) {
154
159
  if (flags.length === 0)
155
160
  return;
161
+ const noChar = flags.reduce((previous, current) => previous && current.char === undefined, true);
156
162
  return flags.map((flag) => {
157
- const left = this.flagHelpLabel(flag);
163
+ let left = (0, theme_1.colorize)(this.config?.theme?.flag, this.flagHelpLabel(flag));
164
+ if (noChar)
165
+ left = left.replace(' ', '');
158
166
  let right = flag.summary || flag.description || '';
159
167
  if (flag.type === 'option' && flag.default) {
160
- right = `[default: ${flag.default}] ${right}`;
168
+ right = `${(0, theme_1.colorize)(this.config?.theme?.flagDefaultValue, `[default: ${flag.default}]`)} ${right}`;
161
169
  }
162
170
  if (flag.required)
163
- right = `(required) ${right}`;
171
+ right = `${(0, theme_1.colorize)(this.config?.theme?.flagRequired, '(required)')} ${right}`;
164
172
  if (flag.type === 'option' && flag.options && !flag.helpValue && !this.opts.showFlagOptionsInTitle) {
165
- right += `\n<options: ${flag.options.join('|')}>`;
173
+ right += (0, theme_1.colorize)(this.config?.theme?.flagOptions, `\n<options: ${flag.options.join('|')}>`);
166
174
  }
167
- return [left, dim(right.trim())];
175
+ return [left, (0, theme_1.colorize)(this.config?.theme?.sectionDescription, right.trim())];
168
176
  });
169
177
  }
170
178
  flagsDescriptions(flags) {
@@ -176,6 +184,8 @@ class CommandHelp extends formatter_1.HelpFormatter {
176
184
  // Guaranteed to be set because of the filter above, but make ts happy
177
185
  const summary = flag.summary || '';
178
186
  let flagHelp = this.flagHelpLabel(flag, true);
187
+ if (!flag.char)
188
+ flagHelp = flagHelp.replace(' ', '');
179
189
  flagHelp +=
180
190
  flagHelp.length + summary.length + 2 < this.opts.maxWidth
181
191
  ? ' ' + summary
@@ -270,11 +280,16 @@ class CommandHelp extends formatter_1.HelpFormatter {
270
280
  ];
271
281
  }
272
282
  usage() {
273
- const { usage } = this.command;
283
+ const { id, usage } = this.command;
284
+ const standardId = (0, ids_1.toStandardizedId)(id, this.config);
274
285
  const body = (usage ? (0, util_1.castArray)(usage) : [this.defaultUsage()])
275
286
  .map((u) => {
276
287
  const allowedSpacing = this.opts.maxWidth - this.indentSpacing;
277
- const line = `$ ${this.config.bin} ${u}`.trim();
288
+ const dollarSign = (0, theme_1.colorize)(this.config?.theme?.dollarSign, '$');
289
+ const bin = (0, theme_1.colorize)(this.config?.theme?.bin, this.config.bin);
290
+ const command = (0, theme_1.colorize)(this.config?.theme?.command, '<%= command.id %>');
291
+ const commandDescription = (0, theme_1.colorize)(this.config?.theme?.sectionDescription, u.replace('<%= command.id %>', '').replace(standardId, '').trim());
292
+ const line = `${dollarSign} ${bin} ${command} ${commandDescription}`.trim();
278
293
  if (line.length > allowedSpacing) {
279
294
  const splitIndex = line.slice(0, Math.max(0, allowedSpacing)).lastIndexOf(' ');
280
295
  return (line.slice(0, Math.max(0, splitIndex)) +
@@ -288,14 +303,15 @@ class CommandHelp extends formatter_1.HelpFormatter {
288
303
  }
289
304
  formatIfCommand(example) {
290
305
  example = this.render(example);
306
+ const dollarSign = (0, theme_1.colorize)(this.config?.theme?.dollarSign, '$');
291
307
  if (example.startsWith(this.config.bin))
292
- return dim(`$ ${example}`);
308
+ return `${dollarSign} ${example}`;
293
309
  if (example.startsWith(`$ ${this.config.bin}`))
294
- return dim(example);
310
+ return `${dollarSign}${example.replace(`$`, '')}`;
295
311
  return example;
296
312
  }
297
313
  isCommand(example) {
298
- return (0, strip_ansi_1.default)(this.formatIfCommand(example)).startsWith(`$ ${this.config.bin}`);
314
+ return (0, strip_ansi_1.default)(this.formatIfCommand(example)).startsWith(`${(0, theme_1.colorize)(this.config?.theme?.dollarSign, '$')} ${this.config.bin}`);
299
315
  }
300
316
  }
301
317
  exports.CommandHelp = CommandHelp;
@@ -10,6 +10,7 @@ const string_width_1 = __importDefault(require("string-width"));
10
10
  const strip_ansi_1 = __importDefault(require("strip-ansi"));
11
11
  const widest_line_1 = __importDefault(require("widest-line"));
12
12
  const wrap_ansi_1 = __importDefault(require("wrap-ansi"));
13
+ const theme_1 = require("../cli-ux/theme");
13
14
  const screen_1 = require("../screen");
14
15
  const util_1 = require("./util");
15
16
  class HelpFormatter {
@@ -154,8 +155,8 @@ class HelpFormatter {
154
155
  .map(([left, right]) => [this.render(left), right && this.render(right)]);
155
156
  }
156
157
  const output = [
157
- chalk_1.default.bold(header),
158
- this.indent(Array.isArray(newBody) ? this.renderList(newBody, { indentation: 2, stripAnsi: this.opts.stripAnsi }) : newBody),
158
+ (0, theme_1.colorize)(this.config?.theme?.sectionHeader, chalk_1.default.bold(header)),
159
+ (0, theme_1.colorize)(this.config?.theme?.sectionDescription, this.indent(Array.isArray(newBody) ? this.renderList(newBody, { indentation: 2, stripAnsi: this.opts.stripAnsi }) : newBody)),
159
160
  ].join('\n');
160
161
  return this.opts.stripAnsi ? (0, strip_ansi_1.default)(output) : output;
161
162
  }
package/lib/help/index.js CHANGED
@@ -6,10 +6,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.loadHelpClass = exports.Help = exports.HelpBase = exports.standardizeIDFromArgv = exports.normalizeArgv = exports.getHelpFlagAdditions = exports.CommandHelp = void 0;
7
7
  const node_util_1 = require("node:util");
8
8
  const strip_ansi_1 = __importDefault(require("strip-ansi"));
9
+ const theme_1 = require("../cli-ux/theme");
9
10
  const write_1 = __importDefault(require("../cli-ux/write"));
10
11
  const errors_1 = require("../errors");
11
12
  const module_loader_1 = require("../module-loader");
12
13
  const cache_default_value_1 = require("../util/cache-default-value");
14
+ const ids_1 = require("../util/ids");
13
15
  const util_1 = require("../util/util");
14
16
  const command_1 = require("./command");
15
17
  const formatter_1 = require("./formatter");
@@ -87,7 +89,11 @@ class Help extends HelpBase {
87
89
  .map((c) => {
88
90
  if (this.config.topicSeparator !== ':')
89
91
  c.id = c.id.replaceAll(':', this.config.topicSeparator);
90
- return [c.id, this.summary(c)];
92
+ const summary = this.summary(c);
93
+ return [
94
+ (0, theme_1.colorize)(this.config?.theme?.command, c.id),
95
+ summary && (0, theme_1.colorize)(this.config?.theme?.sectionDescription, (0, strip_ansi_1.default)(summary)),
96
+ ];
91
97
  }), {
92
98
  indentation: 2,
93
99
  spacer: '\n',
@@ -107,9 +113,10 @@ class Help extends HelpBase {
107
113
  if (this.config.topicSeparator !== ':')
108
114
  topicID = topicID.replaceAll(':', this.config.topicSeparator);
109
115
  let output = (0, util_1.compact)([
110
- summary,
111
- this.section(this.opts.usageHeader || 'USAGE', `$ ${this.config.bin} ${topicID}`),
112
- description && this.section('DESCRIPTION', this.wrap(description)),
116
+ (0, theme_1.colorize)(this.config?.theme?.commandSummary, summary),
117
+ this.section(this.opts.usageHeader || 'USAGE', `${(0, theme_1.colorize)(this.config?.theme?.dollarSign, '$')} ${(0, theme_1.colorize)(this.config?.theme?.bin, this.config.bin)} ${topicID}`),
118
+ description &&
119
+ this.section('DESCRIPTION', this.wrap((0, theme_1.colorize)(this.config?.theme?.sectionDescription, description))),
113
120
  ]).join('\n\n');
114
121
  if (this.opts.stripAnsi)
115
122
  output = (0, strip_ansi_1.default)(output);
@@ -121,7 +128,10 @@ class Help extends HelpBase {
121
128
  const body = this.renderList(topics.map((c) => {
122
129
  if (this.config.topicSeparator !== ':')
123
130
  c.name = c.name.replaceAll(':', this.config.topicSeparator);
124
- return [c.name, c.description && this.render(c.description.split('\n')[0])];
131
+ return [
132
+ (0, theme_1.colorize)(this.config?.theme?.topic, c.name),
133
+ c.description && this.render((0, theme_1.colorize)(this.config?.theme?.sectionDescription, c.description.split('\n')[0])),
134
+ ];
125
135
  }), {
126
136
  indentation: 2,
127
137
  spacer: '\n',
@@ -144,13 +154,13 @@ class Help extends HelpBase {
144
154
  const state = this.config.pjson?.oclif?.state || plugin?.pjson?.oclif?.state || command.state;
145
155
  if (state) {
146
156
  this.log(state === 'deprecated'
147
- ? `${(0, util_2.formatCommandDeprecationWarning)((0, util_2.toConfiguredId)(name, this.config), command.deprecationOptions)}\n`
157
+ ? `${(0, util_2.formatCommandDeprecationWarning)((0, ids_1.toConfiguredId)(name, this.config), command.deprecationOptions)}\n`
148
158
  : `This command is in ${state}.\n`);
149
159
  }
150
160
  if (command.deprecateAliases && command.aliases.includes(name)) {
151
161
  const actualCmd = this.config.commands.find((c) => c.aliases.includes(name));
152
162
  const opts = { ...command.deprecationOptions, ...(actualCmd ? { to: actualCmd.id } : {}) };
153
- this.log(`${(0, util_2.formatCommandDeprecationWarning)((0, util_2.toConfiguredId)(name, this.config), opts)}\n`);
163
+ this.log(`${(0, util_2.formatCommandDeprecationWarning)((0, ids_1.toConfiguredId)(name, this.config), opts)}\n`);
154
164
  }
155
165
  const summary = this.summary(command);
156
166
  if (summary) {
@@ -274,8 +284,8 @@ class Help extends HelpBase {
274
284
  }
275
285
  summary(c) {
276
286
  if (c.summary)
277
- return this.render(c.summary.split('\n')[0]);
278
- return c.description && this.render(c.description).split('\n')[0];
287
+ return (0, theme_1.colorize)(this.config?.theme?.commandSummary, this.render(c.summary.split('\n')[0]));
288
+ return c.description && (0, theme_1.colorize)(this.config?.theme?.commandSummary, this.render(c.description).split('\n')[0]);
279
289
  }
280
290
  /*
281
291
  * _topics is to work around Interfaces.topics mistakenly including commands that do
package/lib/help/root.js CHANGED
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const strip_ansi_1 = __importDefault(require("strip-ansi"));
7
+ const theme_1 = require("../cli-ux/theme");
7
8
  const util_1 = require("../util/util");
8
9
  const formatter_1 = require("./formatter");
9
10
  class RootHelp extends formatter_1.HelpFormatter {
@@ -20,22 +21,27 @@ class RootHelp extends formatter_1.HelpFormatter {
20
21
  description = description.split('\n').slice(1).join('\n');
21
22
  if (!description)
22
23
  return;
23
- return this.section('DESCRIPTION', this.wrap(description));
24
+ return this.section('DESCRIPTION', this.wrap((0, theme_1.colorize)(this.config?.theme?.sectionDescription, description)));
24
25
  }
25
26
  root() {
26
27
  let description = this.config.pjson.oclif.description || this.config.pjson.description || '';
27
28
  description = this.render(description);
28
29
  description = description.split('\n')[0];
29
- let output = (0, util_1.compact)([description, this.version(), this.usage(), this.description()]).join('\n\n');
30
+ let output = (0, util_1.compact)([
31
+ (0, theme_1.colorize)(this.config?.theme?.commandSummary, description),
32
+ this.version(),
33
+ this.usage(),
34
+ this.description(),
35
+ ]).join('\n\n');
30
36
  if (this.opts.stripAnsi)
31
37
  output = (0, strip_ansi_1.default)(output);
32
38
  return output;
33
39
  }
34
40
  usage() {
35
- return this.section(this.opts.usageHeader || 'USAGE', this.wrap(`$ ${this.config.bin} [COMMAND]`));
41
+ return this.section(this.opts.usageHeader || 'USAGE', this.wrap(`${(0, theme_1.colorize)(this.config?.theme?.dollarSign, '$')} ${(0, theme_1.colorize)(this.config?.theme?.bin, this.config.bin)} ${(0, theme_1.colorize)(this.config?.theme?.sectionDescription, '[COMMAND]')}`));
36
42
  }
37
43
  version() {
38
- return this.section('VERSION', this.wrap(this.config.userAgent));
44
+ return this.section('VERSION', this.wrap((0, theme_1.colorize)(this.config?.theme?.version, this.config.userAgent)));
39
45
  }
40
46
  }
41
47
  exports.default = RootHelp;
@@ -1,7 +1,5 @@
1
1
  import { Deprecation, Config as IConfig } from '../interfaces';
2
2
  export declare function template(context: any): (t: string) => string;
3
- export declare function toStandardizedId(commandID: string, config: IConfig): string;
4
- export declare function toConfiguredId(commandID: string, config: IConfig): string;
5
3
  export declare function standardizeIDFromArgv(argv: string[], config: IConfig): string[];
6
4
  export declare function getHelpFlagAdditions(config: IConfig): string[];
7
5
  export declare function formatFlagDeprecationWarning(flag: string, opts: Deprecation | true): string;
package/lib/help/util.js CHANGED
@@ -23,9 +23,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.normalizeArgv = exports.formatCommandDeprecationWarning = exports.formatFlagDeprecationWarning = exports.getHelpFlagAdditions = exports.standardizeIDFromArgv = exports.toConfiguredId = exports.toStandardizedId = exports.template = void 0;
26
+ exports.normalizeArgv = exports.formatCommandDeprecationWarning = exports.formatFlagDeprecationWarning = exports.getHelpFlagAdditions = exports.standardizeIDFromArgv = exports.template = void 0;
27
27
  const ejs = __importStar(require("ejs"));
28
28
  const util_1 = require("../config/util");
29
+ const ids_1 = require("../util/ids");
29
30
  function template(context) {
30
31
  function render(t) {
31
32
  return ejs.render(t, context);
@@ -69,22 +70,13 @@ function collateSpacedCmdIDFromArgs(argv, config) {
69
70
  }
70
71
  return argv; // ID is argv[0]
71
72
  }
72
- function toStandardizedId(commandID, config) {
73
- return commandID.replaceAll(new RegExp(config.topicSeparator, 'g'), ':');
74
- }
75
- exports.toStandardizedId = toStandardizedId;
76
- function toConfiguredId(commandID, config) {
77
- const defaultTopicSeparator = ':';
78
- return commandID.replaceAll(new RegExp(defaultTopicSeparator, 'g'), config.topicSeparator || defaultTopicSeparator);
79
- }
80
- exports.toConfiguredId = toConfiguredId;
81
73
  function standardizeIDFromArgv(argv, config) {
82
74
  if (argv.length === 0)
83
75
  return argv;
84
76
  if (config.topicSeparator === ' ')
85
77
  argv = collateSpacedCmdIDFromArgs(argv, config);
86
78
  else if (config.topicSeparator !== ':')
87
- argv[0] = toStandardizedId(argv[0], config);
79
+ argv[0] = (0, ids_1.toStandardizedId)(argv[0], config);
88
80
  return argv;
89
81
  }
90
82
  exports.standardizeIDFromArgv = standardizeIDFromArgv;
package/lib/index.d.ts CHANGED
@@ -10,7 +10,6 @@ export { execute } from './execute';
10
10
  export * as Flags from './flags';
11
11
  export { CommandHelp, Help, HelpBase, loadHelpClass } from './help';
12
12
  export { HelpSection, HelpSectionKeyValueTable, HelpSectionRenderer } from './help/formatter';
13
- export { toConfiguredId, toStandardizedId } from './help/util';
14
13
  export * as Interfaces from './interfaces';
15
14
  export { Hook } from './interfaces/hooks';
16
15
  export { run } from './main';
@@ -18,3 +17,4 @@ export * as ModuleLoader from './module-loader';
18
17
  export * as Parser from './parser';
19
18
  export { Performance } from './performance';
20
19
  export { Settings, settings } from './settings';
20
+ export { toConfiguredId, toStandardizedId } from './util/ids';
package/lib/index.js CHANGED
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.settings = exports.Performance = exports.Parser = exports.ModuleLoader = exports.run = exports.Interfaces = exports.toStandardizedId = exports.toConfiguredId = exports.loadHelpClass = exports.HelpBase = exports.Help = exports.CommandHelp = exports.Flags = exports.execute = exports.handle = exports.Errors = exports.Plugin = exports.Config = exports.Command = exports.stdout = exports.stderr = exports.flush = exports.ux = exports.Args = void 0;
29
+ exports.toStandardizedId = exports.toConfiguredId = exports.settings = exports.Performance = exports.Parser = exports.ModuleLoader = exports.run = exports.Interfaces = exports.loadHelpClass = exports.HelpBase = exports.Help = exports.CommandHelp = exports.Flags = exports.execute = exports.handle = exports.Errors = exports.Plugin = exports.Config = exports.Command = exports.stdout = exports.stderr = exports.flush = exports.ux = exports.Args = void 0;
30
30
  const write_1 = __importDefault(require("./cli-ux/write"));
31
31
  function checkCWD() {
32
32
  try {
@@ -43,8 +43,7 @@ exports.Args = __importStar(require("./args"));
43
43
  exports.ux = __importStar(require("./cli-ux"));
44
44
  var flush_1 = require("./cli-ux/flush");
45
45
  Object.defineProperty(exports, "flush", { enumerable: true, get: function () { return flush_1.flush; } });
46
- // Remove these in the next major version
47
- var stream_1 = require("./cli-ux/stream");
46
+ var stream_1 = require("./cli-ux/stream"); // Remove these in the next major version
48
47
  Object.defineProperty(exports, "stderr", { enumerable: true, get: function () { return stream_1.stderr; } });
49
48
  Object.defineProperty(exports, "stdout", { enumerable: true, get: function () { return stream_1.stdout; } });
50
49
  var command_1 = require("./command");
@@ -63,9 +62,6 @@ Object.defineProperty(exports, "CommandHelp", { enumerable: true, get: function
63
62
  Object.defineProperty(exports, "Help", { enumerable: true, get: function () { return help_1.Help; } });
64
63
  Object.defineProperty(exports, "HelpBase", { enumerable: true, get: function () { return help_1.HelpBase; } });
65
64
  Object.defineProperty(exports, "loadHelpClass", { enumerable: true, get: function () { return help_1.loadHelpClass; } });
66
- var util_1 = require("./help/util");
67
- Object.defineProperty(exports, "toConfiguredId", { enumerable: true, get: function () { return util_1.toConfiguredId; } });
68
- Object.defineProperty(exports, "toStandardizedId", { enumerable: true, get: function () { return util_1.toStandardizedId; } });
69
65
  exports.Interfaces = __importStar(require("./interfaces"));
70
66
  var main_1 = require("./main");
71
67
  Object.defineProperty(exports, "run", { enumerable: true, get: function () { return main_1.run; } });
@@ -75,3 +71,6 @@ var performance_1 = require("./performance");
75
71
  Object.defineProperty(exports, "Performance", { enumerable: true, get: function () { return performance_1.Performance; } });
76
72
  var settings_1 = require("./settings");
77
73
  Object.defineProperty(exports, "settings", { enumerable: true, get: function () { return settings_1.settings; } });
74
+ var ids_1 = require("./util/ids");
75
+ Object.defineProperty(exports, "toConfiguredId", { enumerable: true, get: function () { return ids_1.toConfiguredId; } });
76
+ Object.defineProperty(exports, "toStandardizedId", { enumerable: true, get: function () { return ids_1.toStandardizedId; } });
@@ -3,6 +3,7 @@ import { Command } from '../command';
3
3
  import { Hook, Hooks } from './hooks';
4
4
  import { PJSON } from './pjson';
5
5
  import { Options, Plugin } from './plugin';
6
+ import { Theme } from './theme';
6
7
  import { Topic } from './topic';
7
8
  export type LoadOptions = Config | Options | string | undefined;
8
9
  export type PlatformTypes = 'wsl' | NodeJS.Platform;
@@ -121,6 +122,7 @@ export interface Config {
121
122
  * active shell
122
123
  */
123
124
  readonly shell: string;
125
+ readonly theme?: Theme;
124
126
  topicSeparator: ' ' | ':';
125
127
  readonly topics: Topic[];
126
128
  /**
@@ -10,5 +10,6 @@ export type { Arg, BooleanFlag, CustomOptions, Deprecation, Flag, FlagDefinition
10
10
  export type { PJSON } from './pjson';
11
11
  export type { Options, Plugin, PluginOptions } from './plugin';
12
12
  export type { S3Manifest } from './s3-manifest';
13
+ export type { Theme, Themes } from './theme';
13
14
  export type { Topic } from './topic';
14
15
  export type { TSConfig } from './ts-config';
@@ -49,6 +49,7 @@ export declare namespace PJSON {
49
49
  repositoryPrefix?: string;
50
50
  schema?: number;
51
51
  state?: 'beta' | 'deprecated' | string;
52
+ themesFile?: string;
52
53
  topicSeparator?: ' ' | ':';
53
54
  topics?: {
54
55
  [k: string]: {
@@ -0,0 +1,27 @@
1
+ import * as Color from 'color';
2
+ export declare const STANDARD_CHALK: readonly ["white", "black", "blue", "yellow", "green", "red", "magenta", "cyan", "gray", "blackBright", "redBright", "greenBright", "yellowBright", "blueBright", "magentaBright", "cyanBright", "whiteBright", "bgBlack", "bgRed", "bgGreen", "bgYellow", "bgBlue", "bgMagenta", "bgCyan", "bgWhite", "bgGray", "bgBlackBright", "bgRedBright", "bgGreenBright", "bgYellowBright", "bgBlueBright", "bgMagentaBright", "bgCyanBright", "bgWhiteBright", "bold", "underline", "dim", "italic", "strikethrough"];
3
+ export type StandardChalk = (typeof STANDARD_CHALK)[number];
4
+ export declare const THEME_KEYS: readonly ["alias", "bin", "command", "commandSummary", "dollarSign", "flag", "flagDefaultValue", "flagOptions", "flagRequired", "flagSeparator", "flagType", "sectionDescription", "sectionHeader", "topic", "version"];
5
+ export type ThemeKey = (typeof THEME_KEYS)[number];
6
+ export type Theme = {
7
+ [key: string | ThemeKey]: Color | StandardChalk | undefined;
8
+ alias?: Color | StandardChalk;
9
+ bin?: Color | StandardChalk;
10
+ command?: Color | StandardChalk;
11
+ commandSummary?: Color | StandardChalk;
12
+ dollarSign?: Color | StandardChalk;
13
+ flag?: Color | StandardChalk;
14
+ flagDefaultValue?: Color | StandardChalk;
15
+ flagOptions?: Color | StandardChalk;
16
+ flagRequired?: Color | StandardChalk;
17
+ flagSeparator?: Color | StandardChalk;
18
+ flagType?: Color | StandardChalk;
19
+ sectionDescription?: Color | StandardChalk;
20
+ sectionHeader?: Color | StandardChalk;
21
+ topic?: Color | StandardChalk;
22
+ version?: Color | StandardChalk;
23
+ };
24
+ export type Themes = {
25
+ selected?: string;
26
+ themes?: Record<string, Record<string, string>>;
27
+ };
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.THEME_KEYS = exports.STANDARD_CHALK = void 0;
4
+ // chalk doesn't export a list of standard colors, so we have to supply our own
5
+ exports.STANDARD_CHALK = [
6
+ 'white',
7
+ 'black',
8
+ 'blue',
9
+ 'yellow',
10
+ 'green',
11
+ 'red',
12
+ 'magenta',
13
+ 'cyan',
14
+ 'gray',
15
+ 'blackBright',
16
+ 'redBright',
17
+ 'greenBright',
18
+ 'yellowBright',
19
+ 'blueBright',
20
+ 'magentaBright',
21
+ 'cyanBright',
22
+ 'whiteBright',
23
+ 'bgBlack',
24
+ 'bgRed',
25
+ 'bgGreen',
26
+ 'bgYellow',
27
+ 'bgBlue',
28
+ 'bgMagenta',
29
+ 'bgCyan',
30
+ 'bgWhite',
31
+ 'bgGray',
32
+ 'bgBlackBright',
33
+ 'bgRedBright',
34
+ 'bgGreenBright',
35
+ 'bgYellowBright',
36
+ 'bgBlueBright',
37
+ 'bgMagentaBright',
38
+ 'bgCyanBright',
39
+ 'bgWhiteBright',
40
+ 'bold',
41
+ 'underline',
42
+ 'dim',
43
+ 'italic',
44
+ 'strikethrough',
45
+ ];
46
+ exports.THEME_KEYS = [
47
+ 'alias',
48
+ 'bin',
49
+ 'command',
50
+ 'commandSummary',
51
+ 'dollarSign',
52
+ 'flag',
53
+ 'flagDefaultValue',
54
+ 'flagOptions',
55
+ 'flagRequired',
56
+ 'flagSeparator',
57
+ 'flagType',
58
+ 'sectionDescription',
59
+ 'sectionHeader',
60
+ 'topic',
61
+ 'version',
62
+ ];
@@ -0,0 +1,3 @@
1
+ import { Config } from '../interfaces';
2
+ export declare function toStandardizedId(commandID: string, config: Config): string;
3
+ export declare function toConfiguredId(commandID: string, config: Config): string;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toConfiguredId = exports.toStandardizedId = void 0;
4
+ function toStandardizedId(commandID, config) {
5
+ return commandID.replaceAll(new RegExp(config.topicSeparator, 'g'), ':');
6
+ }
7
+ exports.toStandardizedId = toStandardizedId;
8
+ function toConfiguredId(commandID, config) {
9
+ const defaultTopicSeparator = ':';
10
+ return commandID.replaceAll(new RegExp(defaultTopicSeparator, 'g'), config.topicSeparator || defaultTopicSeparator);
11
+ }
12
+ exports.toConfiguredId = toConfiguredId;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oclif/core",
3
3
  "description": "base library for oclif CLIs",
4
- "version": "3.10.8",
4
+ "version": "3.11.1-dev.0",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/core/issues",
7
7
  "dependencies": {
@@ -11,6 +11,7 @@
11
11
  "chalk": "^4.1.2",
12
12
  "clean-stack": "^3.0.1",
13
13
  "cli-progress": "^3.12.0",
14
+ "color": "^4.2.3",
14
15
  "debug": "^4.3.4",
15
16
  "ejs": "^3.1.9",
16
17
  "get-package-type": "^0.1.0",
@@ -34,16 +35,17 @@
34
35
  },
35
36
  "devDependencies": {
36
37
  "@commitlint/config-conventional": "^17.7.0",
37
- "@oclif/plugin-help": "^5.2.8",
38
+ "@oclif/plugin-help": "^5.2.20",
38
39
  "@oclif/plugin-plugins": "^3.3.0",
39
40
  "@oclif/prettier-config": "^0.2.1",
40
41
  "@oclif/test": "^3.0.3",
41
42
  "@types/ansi-styles": "^3.2.1",
42
43
  "@types/benchmark": "^2.1.2",
43
- "@types/chai": "^4.3.8",
44
- "@types/chai-as-promised": "^7.1.5",
44
+ "@types/chai": "^4.3.10",
45
+ "@types/chai-as-promised": "^7.1.8",
45
46
  "@types/clean-stack": "^2.1.1",
46
47
  "@types/cli-progress": "^3.11.0",
48
+ "@types/color": "^3.0.5",
47
49
  "@types/debug": "^4.1.10",
48
50
  "@types/ejs": "^3.1.3",
49
51
  "@types/indent-string": "^4.0.1",
@@ -107,6 +109,7 @@
107
109
  "access": "public"
108
110
  },
109
111
  "scripts": {
112
+ "build:dev": "shx rm -rf lib && tsc --sourceMap",
110
113
  "build": "shx rm -rf lib && tsc",
111
114
  "commitlint": "commitlint",
112
115
  "compile": "tsc",
@@ -117,9 +120,11 @@
117
120
  "prepare": "husky install",
118
121
  "pretest": "yarn build && tsc -p test --noEmit --skipLibCheck",
119
122
  "test:circular-deps": "madge lib/ -c",
123
+ "test:debug": "nyc mocha --debug-brk --inspect \"test/**/*.test.ts\"",
120
124
  "test:e2e": "mocha --forbid-only \"test/**/*.e2e.ts\" --parallel --timeout 1200000",
121
125
  "test:esm-cjs": "cross-env DEBUG=e2e:* ts-node test/integration/esm-cjs.ts",
122
126
  "test:perf": "ts-node test/perf/parser.perf.ts",
127
+ "test:dev": "nyc mocha \"test/**/*.test.ts\"",
123
128
  "test": "nyc mocha --forbid-only \"test/**/*.test.ts\""
124
129
  },
125
130
  "types": "lib/index.d.ts"