@thi.ng/args 2.3.71 → 2.5.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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2025-06-09T17:24:08Z
3
+ - **Last updated**: 2025-06-27T13:16:16Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -11,6 +11,23 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
11
11
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
12
12
  and/or version bumps of transitive dependencies.
13
13
 
14
+ ## [2.5.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/args@2.5.0) (2025-06-27)
15
+
16
+ #### 🚀 Features
17
+
18
+ - update ColorTheme, add color support for cmd list ([75b1ef1](https://github.com/thi-ng/umbrella/commit/75b1ef1))
19
+ - add `ColorTheme.command` option
20
+ - migrate internal formatting helpers to own file
21
+ - refactor cliApp() & usage() internals
22
+ - add thi.ng logo header tpl ([838e417](https://github.com/thi-ng/umbrella/commit/838e417))
23
+
24
+ ## [2.4.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/args@2.4.0) (2025-06-27)
25
+
26
+ #### 🚀 Features
27
+
28
+ - add word-wrapping for command descriptions ([46a73a3](https://github.com/thi-ng/umbrella/commit/46a73a3))
29
+ - refactor usage internals for better re-use
30
+
14
31
  ### [2.3.34](https://github.com/thi-ng/umbrella/tree/@thi.ng/args@2.3.34) (2024-06-21)
15
32
 
16
33
  #### ♻️ Refactoring
package/README.md CHANGED
@@ -27,7 +27,7 @@
27
27
 
28
28
  ## About
29
29
 
30
- Declarative, functional & typechecked CLI argument/options parser, value coercions etc..
30
+ Declarative, functional CLI argument/options parser, value coercions, sub-commands etc..
31
31
 
32
32
  Includes built-in support for the following argument types (of course custom arg types are supported too):
33
33
 
@@ -71,7 +71,7 @@ For Node.js REPL:
71
71
  const args = await import("@thi.ng/args");
72
72
  ```
73
73
 
74
- Package sizes (brotli'd, pre-treeshake): ESM: 2.75 KB
74
+ Package sizes (brotli'd, pre-treeshake): ESM: 2.80 KB
75
75
 
76
76
  ## Dependencies
77
77
 
@@ -243,7 +243,7 @@ can be disabled (see
243
243
  [`UsageOpts`](https://docs.thi.ng/umbrella/args/interfaces/UsageOpts.html)).
244
244
 
245
245
  ```text
246
- ts-node index.ts --help
246
+ bun index.ts --help
247
247
 
248
248
  -f, --force Force operation
249
249
 
@@ -266,7 +266,7 @@ represented in the result. Parsing stops with the first non-argument value (here
266
266
  result object.
267
267
 
268
268
  ```bash
269
- ts-node index.ts \
269
+ bun index.ts \
270
270
  -f -t png --bg ff00ff --size 640x480 \
271
271
  -D author=toxi -D date=2018-03-24 \
272
272
  --xtra '{"foo": [23]}' \
package/api.d.ts CHANGED
@@ -164,6 +164,7 @@ export interface UsageOpts {
164
164
  */
165
165
  export interface ColorTheme {
166
166
  default: number;
167
+ command: number;
167
168
  hint: number;
168
169
  multi: number;
169
170
  param: number;
@@ -227,7 +228,7 @@ export interface CLIAppConfig<OPTS extends object, CTX extends CommandCtx<OPTS,
227
228
  }
228
229
  export interface Command<OPTS extends BASE, BASE extends object, CTX extends CommandCtx<OPTS, BASE> = CommandCtx<OPTS, BASE>> {
229
230
  /**
230
- * Command description (short, single line)
231
+ * Command description (any length, will be word wrapped if needed)
231
232
  */
232
233
  desc: string;
233
234
  /**
package/api.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const DEFAULT_THEME = {
2
2
  default: 95,
3
+ command: 92,
3
4
  hint: 90,
4
5
  multi: 90,
5
6
  param: 96,
package/cli.js CHANGED
@@ -1,9 +1,14 @@
1
1
  import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
2
2
  import { StreamLogger } from "@thi.ng/logger/stream";
3
- import { padRight } from "@thi.ng/strings/pad-right";
4
3
  import { PRESET_ANSI16, PRESET_NONE } from "@thi.ng/text-format/presets";
5
4
  import { parse } from "./parse.js";
6
5
  import { usage } from "./usage.js";
6
+ import {
7
+ __ansi,
8
+ __colorTheme,
9
+ __padRightAnsi,
10
+ __wrapWithIndent
11
+ } from "./utils.js";
7
12
  const cliApp = async (config) => {
8
13
  const argv = config.argv || process.argv;
9
14
  const isColor = !process.env.NO_COLOR;
@@ -23,7 +28,7 @@ const cliApp = async (config) => {
23
28
  } else {
24
29
  cmdID = argv[start];
25
30
  cmd = config.commands[cmdID];
26
- usageOpts.prefix += __descriptions(config.commands);
31
+ usageOpts.prefix += __descriptions(config.commands, usageOpts);
27
32
  if (!cmd) __usageAndExit(config, usageOpts);
28
33
  start++;
29
34
  }
@@ -62,13 +67,25 @@ const __usageAndExit = (config, usageOpts) => {
62
67
  process.stderr.write(usage(config.opts, usageOpts));
63
68
  process.exit(1);
64
69
  };
65
- const __descriptions = (commands) => [
66
- "\nAvailable commands:\n",
67
- ...Object.keys(commands).map(
68
- (x) => `${padRight(16)(x)}: ${commands[x].desc}`
69
- ),
70
- "\n"
71
- ].join("\n");
70
+ const __descriptions = (commands, { color, lineWidth = 80 } = {}) => {
71
+ const names = Object.keys(commands);
72
+ const maxLength = Math.max(...names.map((x) => x.length));
73
+ const theme = __colorTheme(color);
74
+ return [
75
+ "\nAvailable commands:\n",
76
+ ...names.map(
77
+ (x) => `${__padRightAnsi(
78
+ __ansi(x, theme.command),
79
+ maxLength
80
+ )} : ${__wrapWithIndent(
81
+ commands[x].desc,
82
+ maxLength + 3,
83
+ lineWidth
84
+ )}`
85
+ ),
86
+ "\n"
87
+ ].join("\n");
88
+ };
72
89
  export {
73
90
  cliApp
74
91
  };
package/header.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Re-usable logo header for various thi.ng CLI tools.
3
+ *
4
+ * @param name
5
+ * @param version
6
+ * @param desc
7
+ *
8
+ * @internal
9
+ */
10
+ export declare const THING_HEADER: (name: string, version: string, desc: string) => string;
11
+ //# sourceMappingURL=header.d.ts.map
package/header.js ADDED
@@ -0,0 +1,10 @@
1
+ const THING_HEADER = (name, version, desc) => `
2
+ \u2588 \u2588 \u2588 \u2502
3
+ \u2588\u2588 \u2588 \u2502
4
+ \u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2502 ${name} v${version}
5
+ \u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2502 ${desc}
6
+ \u2588 \u2502
7
+ \u2588 \u2588 \u2502`;
8
+ export {
9
+ THING_HEADER
10
+ };
package/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from "./api.js";
2
2
  export * from "./args.js";
3
3
  export * from "./cli.js";
4
4
  export * from "./coerce.js";
5
+ export * from "./header.js";
5
6
  export * from "./parse.js";
6
7
  export * from "./usage.js";
7
8
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -2,5 +2,6 @@ export * from "./api.js";
2
2
  export * from "./args.js";
3
3
  export * from "./cli.js";
4
4
  export * from "./coerce.js";
5
+ export * from "./header.js";
5
6
  export * from "./parse.js";
6
7
  export * from "./usage.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@thi.ng/args",
3
- "version": "2.3.71",
4
- "description": "Declarative, functional & typechecked CLI argument/options parser, value coercions etc.",
3
+ "version": "2.5.0",
4
+ "description": "Declarative, functional CLI argument/options parser, value coercions, sub-commands etc.",
5
5
  "type": "module",
6
6
  "module": "./index.js",
7
7
  "typings": "./index.d.ts",
@@ -96,6 +96,9 @@
96
96
  "./coerce": {
97
97
  "default": "./coerce.js"
98
98
  },
99
+ "./header": {
100
+ "default": "./header.js"
101
+ },
99
102
  "./parse": {
100
103
  "default": "./parse.js"
101
104
  },
@@ -107,5 +110,5 @@
107
110
  "tag": "cli",
108
111
  "year": 2018
109
112
  },
110
- "gitHead": "b076434a497b291ad33e81b1a15f6a71e2c82cc2\n"
113
+ "gitHead": "71294b20c04b6ee35db08d30b43b292b07af0d1b\n"
111
114
  }
package/usage.js CHANGED
@@ -1,13 +1,14 @@
1
- import { isPlainObject } from "@thi.ng/checks/is-plain-object";
2
- import { lengthAnsi } from "@thi.ng/strings/ansi";
3
1
  import { capitalize, kebab } from "@thi.ng/strings/case";
4
- import { padRight } from "@thi.ng/strings/pad-right";
5
- import { repeat } from "@thi.ng/strings/repeat";
6
2
  import { stringify } from "@thi.ng/strings/stringify";
7
- import { SPLIT_ANSI, wordWrapLines } from "@thi.ng/strings/word-wrap";
8
3
  import {
9
- DEFAULT_THEME
10
4
  } from "./api.js";
5
+ import {
6
+ __ansi,
7
+ __colorTheme,
8
+ __padRightAnsi,
9
+ __wrap,
10
+ __wrapWithIndent
11
+ } from "./utils.js";
11
12
  const usage = (specs, opts = {}) => {
12
13
  opts = {
13
14
  lineWidth: 80,
@@ -18,9 +19,10 @@ const usage = (specs, opts = {}) => {
18
19
  groups: ["flags", "main"],
19
20
  ...opts
20
21
  };
21
- const theme = isPlainObject(opts.color) ? { ...DEFAULT_THEME, ...opts.color } : opts.color ? DEFAULT_THEME : {};
22
- const indent = repeat(" ", opts.paramWidth);
23
- const format = (ids) => ids.map((id) => __argUsage(id, specs[id], opts, theme, indent));
22
+ const theme = __colorTheme(opts.color);
23
+ const format = (ids) => ids.map(
24
+ (id) => __argUsage(id, specs[id], opts, theme, opts.paramWidth)
25
+ );
24
26
  const sortedIDs = Object.keys(specs).sort();
25
27
  const groups = opts.groups ? opts.groups.map(
26
28
  (gid) => [
@@ -51,7 +53,7 @@ const __argUsage = (id, spec, opts, theme, indent) => {
51
53
  isRequired && prefixes.push("required");
52
54
  spec.multi && prefixes.push("multiple");
53
55
  const body = __argPrefix(prefixes, theme, isRequired) + (spec.desc || "") + __argDefault(spec, opts, theme);
54
- return padRight(opts.paramWidth)(params, lengthAnsi(params)) + __wrap(body, opts.lineWidth - opts.paramWidth).map((l, i) => i > 0 ? indent + l : l).join("\n");
56
+ return __padRightAnsi(params, opts.paramWidth) + __wrapWithIndent(body, indent, opts.lineWidth);
55
57
  };
56
58
  const __argHint = (spec, theme) => spec.hint ? __ansi(" " + spec.hint, theme.hint) : "";
57
59
  const __argAlias = (spec, theme, hint) => spec.alias ? `${__ansi("-" + spec.alias, theme.param)}${hint}, ` : "";
@@ -65,12 +67,6 @@ const __argDefault = (spec, opts, theme) => opts.showDefaults && spec.default !=
65
67
  )})`,
66
68
  theme.default
67
69
  ) : "";
68
- const __ansi = (x, col) => col != null ? `\x1B[${col}m${x}\x1B[0m` : x;
69
- const __wrap = (str, width) => str ? wordWrapLines(str, {
70
- width,
71
- splitter: SPLIT_ANSI,
72
- hard: false
73
- }) : [];
74
70
  export {
75
71
  usage
76
72
  };
package/utils.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { Maybe } from "@thi.ng/api";
2
+ import { type ColorTheme } from "./api.js";
3
+ /** @internal */
4
+ export declare const __ansi: (x: string, col: number) => string;
5
+ /** @internal */
6
+ export declare const __padRightAnsi: (x: string, width: number) => string;
7
+ /** @internal */
8
+ export declare const __wrap: (str: Maybe<string>, width: number) => import("@thi.ng/strings/word-wrap").Line[];
9
+ /** @internal */
10
+ export declare const __wrapWithIndent: (body: string, indent: number, width: number) => string;
11
+ /** @internal */
12
+ export declare const __colorTheme: (color?: boolean | Partial<ColorTheme>) => ColorTheme;
13
+ //# sourceMappingURL=utils.d.ts.map
package/utils.js ADDED
@@ -0,0 +1,25 @@
1
+ import { isPlainObject } from "@thi.ng/checks/is-plain-object";
2
+ import { repeat } from "@thi.ng/strings/repeat";
3
+ import { SPLIT_ANSI, wordWrapLines } from "@thi.ng/strings/word-wrap";
4
+ import { DEFAULT_THEME } from "./api.js";
5
+ import { lengthAnsi } from "@thi.ng/strings/ansi";
6
+ import { padRight } from "@thi.ng/strings/pad-right";
7
+ const __ansi = (x, col) => col != null ? `\x1B[${col}m${x}\x1B[0m` : x;
8
+ const __padRightAnsi = (x, width) => padRight(width)(x, lengthAnsi(x));
9
+ const __wrap = (str, width) => str ? wordWrapLines(str, {
10
+ width,
11
+ splitter: SPLIT_ANSI,
12
+ hard: false
13
+ }) : [];
14
+ const __wrapWithIndent = (body, indent, width) => {
15
+ const prefix = repeat(" ", indent);
16
+ return __wrap(body, width - indent).map((l, i) => i ? prefix + l : l).join("\n");
17
+ };
18
+ const __colorTheme = (color) => isPlainObject(color) ? { ...DEFAULT_THEME, ...color } : color ? DEFAULT_THEME : {};
19
+ export {
20
+ __ansi,
21
+ __colorTheme,
22
+ __padRightAnsi,
23
+ __wrap,
24
+ __wrapWithIndent
25
+ };