Skip to content

Commit

Permalink
Fix CLI -h to display default values (#4400) (#4402)
Browse files Browse the repository at this point in the history
  • Loading branch information
Delusion2056 authored Feb 6, 2025
1 parent e30f132 commit 3e56745
Show file tree
Hide file tree
Showing 11 changed files with 293 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/quiet-boats-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/cli": patch
---

Fix CLI help output to correctly display default values
8 changes: 7 additions & 1 deletion packages/cli/src/internal/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import * as Console from "effect/Console"
import * as Effect from "effect/Effect"
import * as Either from "effect/Either"
import { dual, pipe } from "effect/Function"
import * as Inspectable from "effect/Inspectable"
import * as Option from "effect/Option"
import * as ParseResult from "effect/ParseResult"
import { pipeArguments } from "effect/Pipeable"
import * as Predicate from "effect/Predicate"
import type * as Redacted from "effect/Redacted"
import * as Ref from "effect/Ref"
import type * as Schema from "effect/Schema"
Expand Down Expand Up @@ -536,7 +538,11 @@ const getHelpInternal = (self: Instruction): HelpDoc.HelpDoc => {
const optionalDescription = Option.isOption(self.fallback)
? Option.match(self.fallback, {
onNone: () => InternalHelpDoc.p("This setting is optional."),
onSome: () => InternalHelpDoc.p(`This setting is optional. Defaults to: ${self.fallback}`)
onSome: (fallbackValue) => {
const inspectableValue = Predicate.isObject(fallbackValue) ? fallbackValue : String(fallbackValue)
const displayValue = Inspectable.toStringUnknown(inspectableValue, 0)
return InternalHelpDoc.p(`This setting is optional. Defaults to: ${displayValue}`)
}
})
: InternalHelpDoc.p("This setting is optional.")
return [span, InternalHelpDoc.sequence(block, optionalDescription)]
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/internal/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as Effect from "effect/Effect"
import * as Either from "effect/Either"
import { dual, pipe } from "effect/Function"
import * as HashMap from "effect/HashMap"
import * as Inspectable from "effect/Inspectable"
import * as Option from "effect/Option"
import * as Order from "effect/Order"
import * as ParseResult from "effect/ParseResult"
Expand Down Expand Up @@ -791,7 +792,11 @@ const getHelpInternal = (self: Instruction): HelpDoc.HelpDoc => {
const optionalDescription = Option.isOption(self.fallback)
? Option.match(self.fallback, {
onNone: () => InternalHelpDoc.p("This setting is optional."),
onSome: () => InternalHelpDoc.p(`This setting is optional. Defaults to: ${self.fallback}`)
onSome: (fallbackValue) => {
const inspectableValue = Predicate.isObject(fallbackValue) ? fallbackValue : String(fallbackValue)
const displayValue = Inspectable.toStringUnknown(inspectableValue, 0)
return InternalHelpDoc.p(`This setting is optional. Defaults to: ${displayValue}`)
}
})
: InternalHelpDoc.p("This setting is optional.")
return [span, InternalHelpDoc.sequence(block, optionalDescription)]
Expand Down
28 changes: 28 additions & 0 deletions packages/cli/test/Args.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,32 @@ describe("Args", () => {
)
expect(result).toEqual([Array.empty(), Array.of(content)])
}).pipe(runEffect))

it("displays default value in help when default wrapped in Option.Some (primitive)", () =>
Effect.gen(function*(_) {
const option = Args.withDefault(Args.integer({ name: "value" }), Option.some(123))
const helpDoc = Args.getHelp(option)
yield* _(
Effect.promise(() => expect(helpDoc).toMatchFileSnapshot("./snapshots/help-output/args-default-primitive"))
)
}).pipe(runEffect))

it("displays default value in help when default wrapped in Option.Some (object)", () =>
Effect.gen(function*(_) {
const defaultObject = { key: "value", number: 456 }
const option = Args.withDefault(Args.text({ name: "config" }), Option.some(defaultObject))
const helpDoc = Args.getHelp(option)
yield* _(
Effect.promise(() => expect(helpDoc).toMatchFileSnapshot("./snapshots/help-output/args-default-object"))
)
}).pipe(runEffect))

it("displays no default value in help when default is not Option.Some", () =>
Effect.gen(function*(_) {
const option = Args.withDefault(Args.text({ name: "name" }), Option.none())
const helpDoc = Args.getHelp(option)
yield* _(
Effect.promise(() => expect(helpDoc).toMatchFileSnapshot("./snapshots/help-output/args-no-default"))
)
}).pipe(runEffect))
})
28 changes: 28 additions & 0 deletions packages/cli/test/Options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -705,4 +705,32 @@ describe("Options", () => {
const content = yield* _(fs.readFileString(jsonPath), Effect.map(JSON.parse))
assert.deepStrictEqual(result, [[], content])
}).pipe(runEffect))

it("displays default value in help when default wrapped in Option.Some (primitive)", () =>
Effect.gen(function*(_) {
const option = Options.withDefault(Options.integer("value"), Option.some(123))
const helpDoc = Options.getHelp(option)
yield* _(
Effect.promise(() => expect(helpDoc).toMatchFileSnapshot("./snapshots/help-output/options-default-primitive"))
)
}).pipe(runEffect))

it("displays default value in help when default wrapped in Option.Some (object)", () =>
Effect.gen(function*(_) {
const defaultObject = { key: "value", number: 456 }
const option = Options.withDefault(Options.text("config"), Option.some(defaultObject))
const helpDoc = Options.getHelp(option)
yield* _(
Effect.promise(() => expect(helpDoc).toMatchFileSnapshot("./snapshots/help-output/options-default-object"))
)
}).pipe(runEffect))

it("displays no default value in help when default is not Option.Some", () =>
Effect.gen(function*(_) {
const option = Options.withDefault(Options.text("name"), Option.none())
const helpDoc = Options.getHelp(option)
yield* _(
Effect.promise(() => expect(helpDoc).toMatchFileSnapshot("./snapshots/help-output/options-no-default"))
)
}).pipe(runEffect))
})
31 changes: 31 additions & 0 deletions packages/cli/test/snapshots/help-output/args-default-object
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"_tag": "DescriptionList",
"definitions": [
[
{
"_tag": "Weak",
"value": {
"_tag": "Text",
"value": "<config>",
},
},
{
"_tag": "Sequence",
"left": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "A user-defined piece of text.",
},
},
"right": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "This setting is optional. Defaults to: {"key":"value","number":456}",
},
},
},
],
],
}
31 changes: 31 additions & 0 deletions packages/cli/test/snapshots/help-output/args-default-primitive
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"_tag": "DescriptionList",
"definitions": [
[
{
"_tag": "Weak",
"value": {
"_tag": "Text",
"value": "<value>",
},
},
{
"_tag": "Sequence",
"left": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "An integer.",
},
},
"right": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "This setting is optional. Defaults to: 123",
},
},
},
],
],
}
31 changes: 31 additions & 0 deletions packages/cli/test/snapshots/help-output/args-no-default
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"_tag": "DescriptionList",
"definitions": [
[
{
"_tag": "Weak",
"value": {
"_tag": "Text",
"value": "<name>",
},
},
{
"_tag": "Sequence",
"left": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "A user-defined piece of text.",
},
},
"right": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "This setting is optional.",
},
},
},
],
],
}
42 changes: 42 additions & 0 deletions packages/cli/test/snapshots/help-output/options-default-object
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"_tag": "DescriptionList",
"definitions": [
[
{
"_tag": "Sequence",
"left": {
"_tag": "Text",
"value": "--config",
},
"right": {
"_tag": "Sequence",
"left": {
"_tag": "Text",
"value": " ",
},
"right": {
"_tag": "Text",
"value": "text",
},
},
},
{
"_tag": "Sequence",
"left": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "A user-defined piece of text.",
},
},
"right": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "This setting is optional. Defaults to: {"key":"value","number":456}",
},
},
},
],
],
}
42 changes: 42 additions & 0 deletions packages/cli/test/snapshots/help-output/options-default-primitive
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"_tag": "DescriptionList",
"definitions": [
[
{
"_tag": "Sequence",
"left": {
"_tag": "Text",
"value": "--value",
},
"right": {
"_tag": "Sequence",
"left": {
"_tag": "Text",
"value": " ",
},
"right": {
"_tag": "Text",
"value": "integer",
},
},
},
{
"_tag": "Sequence",
"left": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "An integer.",
},
},
"right": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "This setting is optional. Defaults to: 123",
},
},
},
],
],
}
42 changes: 42 additions & 0 deletions packages/cli/test/snapshots/help-output/options-no-default
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"_tag": "DescriptionList",
"definitions": [
[
{
"_tag": "Sequence",
"left": {
"_tag": "Text",
"value": "--name",
},
"right": {
"_tag": "Sequence",
"left": {
"_tag": "Text",
"value": " ",
},
"right": {
"_tag": "Text",
"value": "text",
},
},
},
{
"_tag": "Sequence",
"left": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "A user-defined piece of text.",
},
},
"right": {
"_tag": "Paragraph",
"value": {
"_tag": "Text",
"value": "This setting is optional.",
},
},
},
],
],
}

0 comments on commit 3e56745

Please sign in to comment.