Optique 0.4.0:更好的帮助文本、丰富的文档和 Temporal 支持

洪 民憙 (Hong Minhee) @hongminhee@hackers.pub

我们很高兴宣布 Optique 0.4.0 的发布,它带来了帮助文本组织的显著改进、增强的文档功能,并引入了全面的 Temporal API 支持。

Optique 是一个为 TypeScript 设计的类型安全组合式 CLI 解析器,它使构建命令行界面变得直观且易于维护。此版本专注于使您的 CLI 应用程序更加用户友好和易于维护。

更好的帮助文本组织

Optique 0.4.0 中最明显的改进之一是增强的帮助文本组织。您现在可以更有效地标记和分组您的选项,使复杂的 CLI 对用户来说更加易于理解。

带标签的合并组

merge() 组合器现在接受一个可选的标签参数,解决了开发者必须在干净的代码结构和有组织的帮助输出之间做选择的常见痛点:

// 之前:未标记的合并选项显得分散
const config = merge(connectionOptions, performanceOptions);

// 现在:在清晰的部分下分组相关选项
const config = merge(
  "Server Configuration",  // 新的标签参数
  connectionOptions,
  performanceOptions
);

这个简单的添加对帮助文本的可读性产生了巨大的影响,特别是对于那些选项分布在多个可重用模块中的 CLI。

生成的帮助输出清晰地将选项组织在 Server Configuration 部分下:

Demo app showcasing labeled merge groups
Usage: [1mdemo-merge.ts[0m [3m--host[0m [4m[2mSTRING[0m [3m--port[0m [4m[2mINTEGER[0m [3m--timeout[0m [4m[2mINTEGER[0m [3m--retries[0m
       [4m[2mINTEGER[0m

Server Configuration:
  [3m--host[0m [4m[2mSTRING[0m               Server hostname or IP address
  [3m--port[0m [4m[2mINTEGER[0m              Port number for the connection
  [3m--timeout[0m [4m[2mINTEGER[0m           Connection timeout in seconds
  [3m--retries[0m [4m[2mINTEGER[0m           Number of retry attempts

新的 group() 组合器

对于 merge() 不适用的情况,新的 group() 组合器允许您用文档标签包装任何解析器:

// 在清晰的部分下分组互斥选项
const outputFormat = group(
  "Output Format",
  or(
    map(flag("--json"), () => "json"),
    map(flag("--yaml"), () => "yaml"),
    map(flag("--xml"), () => "xml"),
  )
);

这对于组织互斥标志、多个输入或任何不原生支持标记的解析器特别有用。生成的帮助文本变得更加易于浏览和用户友好。

以下是分组的输出格式选项在帮助文本中的显示方式:

Demo app showcasing group combinator
Usage: [1mdemo-group.ts[0m [3m--json[0m
       [1mdemo-group.ts[0m [3m--yaml[0m
       [1mdemo-group.ts[0m [3m--xml[0m

Output Format:
  [3m--json[0m                      Output in JSON format
  [3m--yaml[0m                      Output in YAML format
  [3m--xml[0m                       Output in XML format

丰富的文档支持

Optique 0.4.0 引入了全面的文档字段,可以直接通过 run() 函数添加,无需为文档目的修改解析器定义。

简要描述、详细说明和页脚

@optique/core/facade@optique/run 现在都通过 run() 函数支持 briefdescriptionfooter 选项:

import { run } from "@optique/run";
import { message } from "@optique/core/message";

const result = run(parser, {
  brief: message`A powerful data processing tool`,
  description: message`This tool provides comprehensive data processing capabilities with support for multiple formats and transformations. It can handle JSON, YAML, and CSV files with automatic format detection.`,
  footer: message`Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs`,
  help: "option"
});

这些文档字段出现在帮助输出和错误消息中(当配置时),在 CLI 的用户体验中提供一致的上下文。

完整的帮助输出展示了丰富的文档功能,包括简要描述、详细说明、选项描述、默认值和页脚信息:

A powerful data processing tool
Usage: [1mdemo-rich-docs.ts[0m [2m[[0m[3m--port[0m [4m[2mINTEGER[0m[2m][0m [2m[[0m[3m--format[0m [4m[2mSTRING[0m[2m][0m [3m--verbose[0m [4m[2mSTRING[0m

This tool provides comprehensive data processing capabilities with support for
multiple formats and transformations. It can handle JSON, YAML, and CSV files
with automatic format detection.

  [3m--port[0m [4m[2mINTEGER[0m              Server port number[2m [3000][0m
  [3m--format[0m [4m[2mSTRING[0m             Output format[2m [json][0m
  [3m--verbose[0m [4m[2mSTRING[0m            Verbosity level

Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs

这些文档字段出现在帮助输出和错误消息中(当配置时),在 CLI 的用户体验中提供一致的上下文。

显示默认值

一个经常被请求的功能现在可用了:直接在帮助文本中显示默认值。使用 withDefault() 时,通过新的 showDefault 选项启用此功能:

const parser = object({
  port: withDefault(
    option("--port", integer(), { description: message`Server port number` }),
    3000,
  ),
  format: withDefault(
    option("--format", string(), { description: message`Output format` }),
    "json",
  ),
});

run(parser, { showDefault: true });

// 或者使用自定义格式:
run(parser, {
  showDefault: {
    prefix: " (default: ",
    suffix: ")"
  }  // 显示:--port (default: 3000)
});

当启用颜色时,默认值会自动变暗,使它们在视觉上与众不同,同时保持可读性。

帮助输出清晰地在每个选项旁边标记默认值:

Usage: [1mdemo-defaults.ts[0m [2m[[0m[3m--port[0m [4m[2mINTEGER[0m[2m][0m [2m[[0m[3m--format[0m [4m[2mSTRING[0m[2m][0m

  [3m--port[0m [4m[2mINTEGER[0m              Server port number[2m [3000][0m
  [3m--format[0m [4m[2mSTRING[0m             Output format[2m [json][0m

Temporal API 支持

Optique 0.4.0 引入了一个新的包,@optique/temporal,为现代 Temporal API 提供全面支持。这带来了对日期、时间、持续时间和时区的类型安全解析:

import { instant, duration, zonedDateTime } from "@optique/temporal";
import { option } from "@optique/core/parser";

const parser = object({
  // 解析 ISO 8601 时间戳
  timestamp: option("--at", instant()),

  // 解析持续时间,如 "PT30M" 或 "P1DT2H"
  timeout: option("--timeout", duration()),

  // 解析带时区信息的日期时间
  meeting: option("--meeting", zonedDateTime()),
});

时间解析器返回具有完整功能的原生 Temporal 对象:

const result = parse(timestampArg, ["2023-12-25T10:30:00Z"]);
if (result.success) {
  const instant = result.value;
  console.log(`UTC: ${instant.toString()}`);
  console.log(`Seoul: ${instant.toZonedDateTimeISO("Asia/Seoul")}`);
}

使用以下命令安装新包:

npm add @optique/temporal

改进的类型推断

merge() 组合器现在支持最多 10 个解析器(之前为 5 个),而 tuple() 解析器使用 TypeScript 的 const 类型参数改进了类型推断。这些增强功能使更复杂的 CLI 结构成为可能,同时保持完美的类型安全。

破坏性变更

虽然我们为大多数 API 保持了向后兼容性,但有一些变更需要注意:

  • Parser.getDocFragments() 方法现在使用 DocState<TState> 而不是直接的状态值(仅影响自定义解析器实现)
  • merge() 组合器现在在编译时强制执行更严格的类型约束,拒绝非对象生成的解析器

了解更多

有关变更、错误修复和改进的完整列表,请参阅完整的变更日志

查看更新的文档:

安装

升级到 Optique 0.4.0:

npm update @optique/core @optique/run
# 或
deno add jsr:@optique/core@^0.4.0 jsr:@optique/run@^0.4.0

添加时间支持(可选):

npm add @optique/temporal
# 或
deno add jsr:@optique/temporal

我们希望这些改进能让使用 Optique 构建 CLI 应用程序变得更加愉快。一如既往,我们欢迎您在 GitHub 上提供反馈和贡献。

1

No comments

If you have a fediverse account, you can comment on this article from your own instance. Search https://hackers.pub/ap/articles/01991aa2-edea-797e-aad6-2f1ece168909 on your instance and reply to it.