CliOutput.ts
CliOutput.ts overview
Section titled “CliOutput.ts overview”Formats CLI help and errors as text.
This module turns help documents, CLI errors, grouped errors, and version
information into strings. It does not write those strings to the terminal
itself. It includes the Formatter interface, the formatter service, a layer
for custom formatters, and the default formatter with configurable color
support.
Since v4.0.0
Exports Grouped by Category
Section titled “Exports Grouped by Category”constructors
Section titled “constructors”defaultFormatter
Section titled “defaultFormatter”Creates a default formatter with configurable options.
Example (Creating default formatters)
import { Effect } from "effect"import { CliError, CliOutput } from "effect/unstable/cli"
// Create a formatter without colors for tests or CI environmentsconst noColorFormatter = CliOutput.defaultFormatter({ colors: false })
// Create a formatter with colors forced onconst colorFormatter = CliOutput.defaultFormatter({ colors: true })
// Auto-detect colors based on terminal support (default behavior)const autoFormatter = CliOutput.defaultFormatter()
const program = Effect.gen(function* () { const formatter = colorFormatter
// Format an error with proper styling const error = new CliError.InvalidValue({ option: "foo", value: "bar", expected: "baz", kind: "flag" }) const errorText = formatter.formatError(error) console.log(errorText)
// Format version information const versionText = formatter.formatVersion("my-tool", "1.2.3") console.log(versionText)})Signature
declare const defaultFormatter: (options?: { colors?: boolean }) => FormatterSince v4.0.0
layers
Section titled “layers”Creates a Layer that provides a custom Formatter implementation.
Example (Providing a custom formatter)
import { Console, Effect } from "effect"import { CliOutput } from "effect/unstable/cli"
// Create a custom formatter without colorsconst noColorFormatter = CliOutput.defaultFormatter({ colors: false })const NoColorLayer = CliOutput.layer(noColorFormatter)
// Create a program that uses the custom formatterconst program = Effect.gen(function* () { const formatter = yield* CliOutput.Formatter const versionText = formatter.formatVersion("my-cli", "1.0.0") yield* Console.log(`Using custom formatter: ${versionText}`)}).pipe(Effect.provide(NoColorLayer))
// You can also create completely custom formattersconst jsonFormatter: CliOutput.Formatter = { formatHelpDoc: (doc) => JSON.stringify(doc, null, 2), formatCliError: (error) => JSON.stringify({ error: error.message }), formatError: (error) => JSON.stringify({ type: "error", message: error.message }), formatVersion: (name, version) => JSON.stringify({ name, version }), formatErrors: (errors) => JSON.stringify(errors.map((error) => error.message))}const JsonLayer = CliOutput.layer(jsonFormatter)Signature
declare const layer: (formatter: Formatter) => Layer.Layer<never>Since v4.0.0
models
Section titled “models”Formatter (interface)
Section titled “Formatter (interface)”Defines the service interface for formatting CLI output including help, errors, and version info. This allows customization of output formatting, including color support.
Example (Customizing CLI output formatting)
import { Effect } from "effect"import { CliOutput } from "effect/unstable/cli"
// Create a custom formatter implementationconst customFormatter: CliOutput.Formatter = { formatHelpDoc: (doc) => `Custom Help: ${doc.usage}`, formatCliError: (error) => `Error: ${error.message}`, formatError: (error) => `[ERROR] ${error.message}`, formatVersion: (name, version) => `${name} (${version})`, formatErrors: (errors) => errors.map((error) => error.message).join("\\n")}
// Use the custom formatter in a programconst program = Effect.gen(function* () { const formatter = yield* CliOutput.Formatter const helpText = formatter.formatVersion("myapp", "1.0.0") console.log(helpText)}).pipe(Effect.provide(CliOutput.layer(customFormatter)))Signature
export interface Formatter { /** * Formats a HelpDoc structure into a readable string format. * * **Example** (Formatting help documents) * * ```ts * import { Option as O } from "effect" * import { CliOutput } from "effect/unstable/cli" * import type { HelpDoc } from "effect/unstable/cli" * * const helpDoc: HelpDoc = { * usage: "myapp [options] <file>", * description: "Process files with various options", * flags: [ * { * name: "verbose", * aliases: ["-v"], * type: "boolean", * description: O.some("Enable verbose output"), * required: false * } * ], * args: [ * { * name: "file", * type: "string", * description: O.some("Input file to process"), * required: true, * variadic: false * } * ] * } * * const formatter = CliOutput.defaultFormatter() * const helpText = formatter.formatHelpDoc(helpDoc) * console.log(helpText) * // Outputs formatted help with sections: DESCRIPTION, USAGE, ARGUMENTS, FLAGS * ``` * * @since 4.0.0 */ readonly formatHelpDoc: (doc: HelpDoc) => string
/** * Formats a CLI error for display. Default implementation mirrors the error message. * * **Example** (Formatting CLI errors) * * ```ts * import { Data } from "effect" * import { CliOutput } from "effect/unstable/cli" * * class InvalidOption extends Data.TaggedError("InvalidOption")<{ * readonly message: string * }> {} * * const formatter = CliOutput.defaultFormatter() * const error = new InvalidOption({ message: "Unknown flag '--invalid'" }) * const errorMessage = formatter.formatCliError(error) * console.log(errorMessage) // "Unknown flag '--invalid'" * ``` * * @since 4.0.0 */ readonly formatCliError: (error: CliError.CliError) => string
/** * Formats an error section with proper styling and color reset. * * **Example** (Formatting error sections) * * ```ts * import { Data } from "effect" * import { CliOutput } from "effect/unstable/cli" * * class ValidationError extends Data.TaggedError("ValidationError")<{ * readonly message: string * }> {} * * const colorFormatter = CliOutput.defaultFormatter({ colors: true }) * const noColorFormatter = CliOutput.defaultFormatter({ colors: false }) * * const error = new ValidationError({ message: "Value must be positive" }) * * const coloredError = colorFormatter.formatError(error) * console.log(coloredError) // "\n\x1b[1m\x1b[31mERROR\x1b[0m\n Value must be positive\x1b[0m" * * const plainError = noColorFormatter.formatError(error) * console.log(plainError) // "\nERROR\n Value must be positive" * ``` * * @since 4.0.0 */ readonly formatError: (error: CliError.CliError) => string
/** * Formats version output for display. * * **Example** (Formatting version output) * * ```ts * import { CliOutput } from "effect/unstable/cli" * * const colorFormatter = CliOutput.defaultFormatter({ colors: true }) * const noColorFormatter = CliOutput.defaultFormatter({ colors: false }) * * const appName = "my-awesome-tool" * const version = "1.2.3" * * const coloredVersion = colorFormatter.formatVersion(appName, version) * console.log(coloredVersion) // "\x1b[1mmy-awesome-tool\x1b[0m \x1b[2mv\x1b[0m\x1b[1m1.2.3\x1b[0m" * * const plainVersion = noColorFormatter.formatVersion(appName, version) * console.log(plainVersion) // "my-awesome-tool v1.2.3" * ``` * * @since 4.0.0 */ readonly formatVersion: (name: string, version: string) => string
/** * Formats multiple CLI errors for display, grouping by error type. * * **Example** (Formatting grouped errors) * * ```ts * import { CliError, CliOutput } from "effect/unstable/cli" * * const formatter = CliOutput.defaultFormatter({ colors: false }) * * const errors = [ * new CliError.UnrecognizedOption({ * option: "--foo", * suggestions: ["--force"] * }), * new CliError.UnrecognizedOption({ option: "--bar", suggestions: [] }), * new CliError.MissingOption({ option: "--required" }) * ] * * const output = formatter.formatErrors(errors) * // Groups errors by type and displays all at once * ``` * * @since 4.0.0 */ readonly formatErrors: (errors: ReadonlyArray<CliError.CliError>) => string}Since v4.0.0
services
Section titled “services”Formatter
Section titled “Formatter”Service reference for the CLI output formatter. Provides a default implementation that can be overridden for custom formatting or testing.
Example (Accessing the output formatter)
import { Effect } from "effect"import { CliOutput } from "effect/unstable/cli"
// Access the formatter serviceconst program = Effect.gen(function* () { const formatter = yield* CliOutput.Formatter
// Format version information const versionText = formatter.formatVersion("my-cli", "2.1.0") console.log(versionText) // "my-cli v2.1.0" (with colors if supported)
return versionText})
// Run with default formatterconst result = Effect.runSync(program)Signature
declare const Formatter: Context.Reference<Formatter>Since v4.0.0