@k8ts/instruments
Version:
A collection of utilities and core components for k8ts.
96 lines (82 loc) • 2.86 kB
text/typescript
import { List, Map } from "immutable"
import { defaultsDeep, merge } from "lodash"
import { displayers } from "../displayers"
import {
CliFlag,
CliOptionValue,
VerbatimTerm,
type CliTerm,
type ValueTermJoiner
} from "./cli-term"
import type { CliArgsMapping, CliKey } from "./types"
export interface CliCommandBuilderOptions {
joiner: ValueTermJoiner
}
({
simple: s => s.string
})
export class CmdBuilder {
protected constructor(
readonly executable: string,
private readonly _terms: List<CliTerm>,
private readonly _options: CliCommandBuilderOptions
) {}
private _withArgs(f: (args: List<CliTerm>) => List<CliTerm>) {
return new CmdBuilder(this.executable, f(this._terms), this._options)
}
private _withOptions(f: (options: CliCommandBuilderOptions) => CliCommandBuilderOptions) {
return new CmdBuilder(this.executable, this._terms, f(this._options))
}
flag(...flags: CliKey[]) {
const flagTerms = flags.map(flag => new CliFlag(flag))
return this._withArgs(terms => terms.concat(flagTerms))
}
verbatim(...values: string[]) {
const verbatimTerms = values.map(value => new VerbatimTerm(value))
return this._withArgs(terms => terms.concat(verbatimTerms))
}
option(args: CliArgsMapping) {
const map = Map(args)
const optionTerms = map.entrySeq().map(([key, value]) => {
let joiner: string | undefined
const lastChar = key.at(-1)
if (lastChar === "=") {
joiner = "="
key = key.slice(0, -1) as CliKey
} else if (lastChar === " ") {
joiner = " "
key = key.slice(0, -1) as CliKey
}
return new CliOptionValue(key, joiner, value)
})
return this._withArgs(terms => terms.concat(optionTerms))
}
joiner(joiner: ValueTermJoiner) {
return this._withOptions(options => merge({}, options, { joiner: joiner }))
}
toArray() {
const terms = this._terms
.filter(x => !x.isMissing)
.flatMap(term => {
return term.arr(this._options.joiner)
})
.toArray()
if (this.executable !== "") {
terms.unshift(this.executable)
}
return terms
}
get string() {
return this.toArray().join(" ")
}
static make(executable: string, options: CliCommandBuilderOptions) {
return new CmdBuilder(executable, List(), options)
}
}
const defaultOptions: CliCommandBuilderOptions = {
joiner: " "
}
export function Cmd(executable: string, options?: Partial<CliCommandBuilderOptions>) {
options = defaultsDeep({}, options, defaultOptions)
return CmdBuilder.make(executable, options as any)
}