DRAFT: cli: shared and global flags can't be listed in the root command's help only

クローズ
#8,642 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

関連するプルリクエストがすでにマージされています。

  • #9276 @okarin1511 による — マージ済み

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
活発
技術スタック
node.js, typescript
領域
cli

調査の方向性

Start with packages/effect/src/cli/internal/help.ts:99-132 and :152-183, then reproduce the root and deploy help output from the issue. Compare the flag-level and CliConfig directions with related issue #6376 and confirm the intended inheritance behavior. Done should include an agreed help-layout design that preserves parsing and covers shared, global, and built-in flags.

索引モデルが issue の本文から書いたものです。

説明

We build multi-command CLIs on effect/cli, and we're asking whether a help-layout option would fit.

What we observed

A flag declared at the root with Command.withSharedFlags or Command.withGlobalFlags is listed again in every subcommand's --help, and the built-in global flags are too. For a tool with a handful of such flags and many subcommands, every subcommand page repeats the same block, and the flags specific to that subcommand get lost in it. Flag.withHidden is the only other option, and it hides the flag from the root's help too.

We haven't found a way to say "list this flag in the root's help only; still accept and parse it everywhere".

Environment: [email protected] (tag [email protected], ad61db8) and @effect/[email protected], on Node 26.10.0 and macOS. From reading the source, the same lines are unchanged on main at 8b0eac6 (packages/effect/src/cli/internal/help.ts:99-132, :152-183).

Reproduction
import * as NodeRuntime from "@effect/platform-node/NodeRuntime"
import * as NodeServices from "@effect/platform-node/NodeServices"
import { Effect } from "effect"
import { Command, Flag, GlobalFlag } from "effect/cli"

const Color = GlobalFlag.Setting("color")({
  flag: Flag.Boolean("color").pipe(Flag.withDescription("Colour the output"), Flag.withDefault(true))
})

const deploy = Command.make("deploy", { target: Flag.String("target") }, () => Effect.void)
const status = Command.make("status", {}, () => Effect.void)

const app = Command.make("app").pipe(
  Command.withSharedFlags({
    profile: Flag.String("profile").pipe(
      Flag.withDescription("Profile to use"),
      Flag.withDefault("default"),
      (flag) => process.env.HIDE === "1" ? Flag.withHidden(flag) : flag
    )
  }),
  Command.withGlobalFlags([Color]),
  Command.withSubcommands([deploy, status])
)

Command.run(app, { version: "0.0.0" }).pipe(Effect.provide(NodeServices.layer), NodeRuntime.runMain)

The output, captured live:

$ node app.ts --help
USAGE
  app <subcommand> [flags]

FLAGS
  --profile string    Profile to use

GLOBAL FLAGS
  --help, -h                                                          Show help information
  --version, -v                                                       Show version information
  --wizard                                                            Start wizard mode for a command
  --completions <bash|zsh|fish|sh>                                    Print shell completion script (choices: bash, zsh, fish, sh)
  --log-level <all|trace|debug|info|warn|warning|error|fatal|none>    Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none)
  --color                                                             Colour the output

SUBCOMMANDS
  deploy    
  status    

$ node app.ts deploy --help
USAGE
  app deploy [flags]

FLAGS
  --profile string    Profile to use
  --target string     

GLOBAL FLAGS
  --help, -h                                                          Show help information
  --version, -v                                                       Show version information
  --wizard                                                            Start wizard mode for a command
  --completions <bash|zsh|fish|sh>                                    Print shell completion script (choices: bash, zsh, fish, sh)
  --log-level <all|trace|debug|info|warn|warning|error|fatal|none>    Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none)
  --color                                                             Colour the output

With Flag.withHidden, the shared flag leaves the root's help as well, although it still parses (the unchanged built-in lines are elided as …):

$ HIDE=1 node app.ts --help
USAGE
  app <subcommand> [flags]

GLOBAL FLAGS
  --help, -h                                                          Show help information
  …
  --color                                                             Colour the output

SUBCOMMANDS
  deploy    
  status    

$ HIDE=1 node app.ts deploy --profile staging --target prod; echo "exit=$?"
exit=0
Where it happens
  • help.ts:99-132: getSharedFlagsForCommandPath copies every non-hidden ancestor flag into the subcommand's FLAGS section.
  • help.ts:152-183: getHelpForCommandPath lists every global flag active on the path, built-ins included, under GLOBAL FLAGS. single.hidden is the only thing that removes a flag from either section, so a hidden flag disappears from every level.
Would an option fit?

Is there already a way to do this that we missed? If not, one possible direction is a flag-level marker, next to withHidden, that keeps a flag in the help of the command that declares it and leaves it out of descendants' help. Another is a CliConfig option for how subcommand help treats inherited and global flags: listed in full, or replaced with one line pointing at the root's --help. The second would also cover the built-ins.

Related
  • #6376 (open) asks for public control over the built-in global flags' help rendering. It's adjacent to this, though it doesn't cover where inherited flags appear.
主要言語
TypeScript
スター
16.7k
フォーク
808
平均マージ
11時間 31分
マージ済み PR(30日)
834

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

Effect-TS/effect のほかの issue

Effect-TS/effect の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。