Packages
A Gleam library for writing command line tools.
Current section
Files
Jump to
Current section
Files
src/outil.gleam
import gleam/float
import gleam/int
import gleam/list
import gleam/option
import gleam/string
import outil/core.{ArgvFunction, Command, Error, NotImplemented, Opt}
/// Create a command with the given name and description, and pass it to the
/// given continuation function for further configuration.
///
/// The command gets a default implementation that returns an error.
pub fn command(
name: String,
description: String,
continue: fn(Command(a)) -> Command(a),
) -> Command(a) {
continue(Command(
name,
description,
[],
[],
fn(_) { Error(NotImplemented(name)) },
))
}
/// Add the code to evaluate when the command is executed.
pub fn implement(cmd: Command(a), run: ArgvFunction(a)) -> Command(a) {
Command(cmd.name, cmd.description, cmd.arguments, cmd.options, run)
}
/// Execute the command with the given argument vector, without the program name.
pub fn execute(cmd: Command(a), args: List(String)) -> Result(a, Error) {
cmd.run(args)
}
/// Return a string describing the usage of the given command.
pub fn usage(cmd: Command(a)) -> String {
let args =
cmd.arguments
|> list.map(fn(arg) { arg.name })
|> list.map(fn(arg) { "<" <> arg <> ">" })
|> string.join(" ")
let opts =
cmd.options
|> list.map(fn(opt) {
let Opt(long, short, desc, value) = opt
let short = option.map(short, fn(s) { "-" <> s <> ", " })
let short = option.unwrap(short, "")
let long = "--" <> long
let typ = opt_type(value)
let default = show_default(value)
let meta = "(" <> typ <> ", default: " <> default <> ")"
short <> long <> " " <> desc <> " " <> meta
})
|> list.map(fn(opt) { " " <> opt })
|> string.join("\n")
let opts = "Options:\n" <> opts <> "\n"
cmd.description <> "\n\n" <> "Usage: " <> cmd.name <> " " <> args <> "\n\n" <> opts
}
fn opt_type(value: core.OptValue) -> String {
case value {
core.BoolOpt -> "bool"
core.FloatOpt(_) -> "float"
core.IntOpt(_) -> "int"
core.StringOpt(_) -> "string"
}
}
fn show_default(value: core.OptValue) {
case value {
core.BoolOpt -> "false"
core.FloatOpt(default) -> float.to_string(default)
core.IntOpt(default) -> int.to_string(default)
core.StringOpt(default) -> "\"" <> default <> "\""
}
}