From 8c64dd6f6ca149cd677c9f32485f4892b8074781 Mon Sep 17 00:00:00 2001 From: Robert Attard Date: Sun, 21 Apr 2024 20:56:30 -0400 Subject: [PATCH] clean up flags api --- .gitignore | 1 + examples/hello/src/hello.gleam | 24 ++++------ examples/hello/test/hello_test.gleam | 6 ++- src/glint.gleam | 65 ++++++++++++++++------------ test/flag_test.gleam | 33 +++++++------- test/glint_test.gleam | 34 +++++++-------- 6 files changed, 85 insertions(+), 78 deletions(-) diff --git a/.gitignore b/.gitignore index 8c9a6a0..457ffa2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ *.ez build erl_crash.dump +.ignore_me .ignore_me.* diff --git a/examples/hello/src/hello.gleam b/examples/hello/src/hello.gleam index ef0463f..5b0bb1e 100644 --- a/examples/hello/src/hello.gleam +++ b/examples/hello/src/hello.gleam @@ -51,27 +51,21 @@ pub fn hello( // ----- CLI SETUP ----- -/// the key for the caps flag -pub const caps = "caps" - /// a boolean flag with default False to control message capitalization. /// pub fn caps_flag() -> glint.Flag(Bool) { - glint.bool(caps) - |> glint.default(False) + glint.bool("caps") + |> glint.flag_default(False) |> glint.flag_help("Capitalize the hello message") } -/// the key for the repeat flag -pub const repeat = "repeat" - /// an int flag with default 1 to control how many times to repeat the message. /// this flag is constrained to values greater than 0. /// pub fn repeat_flag() -> glint.Flag(Int) { use n <- glint.constraint( - glint.int(repeat) - |> glint.default(1) + glint.int("repeat") + |> glint.flag_default(1) |> glint.flag_help("Repeat the message n-times"), ) case n { @@ -87,8 +81,8 @@ pub fn hello_cmd() -> glint.Command(String) { use <- glint.command_help("Prints Hello, !") use <- glint.unnamed_args(glint.MinArgs(1)) use _, args, flags <- glint.command() - let assert Ok(caps) = glint.get_bool(flags, caps) - let assert Ok(repeat) = glint.get_int(flags, repeat) + let assert Ok(caps) = glint.get_flag(flags, caps_flag()) + let assert Ok(repeat) = glint.get_flag(flags, repeat_flag()) let assert [name, ..rest] = args hello(name, rest, caps, repeat) } @@ -100,8 +94,8 @@ pub fn hello_single_cmd() -> glint.Command(String) { use <- glint.unnamed_args(glint.EqArgs(0)) use name <- glint.named_arg("name") use named_args, _, flags <- glint.command() - let assert Ok(caps) = glint.get_bool(flags, caps) - let assert Ok(repeat) = glint.get_int(flags, repeat) + let assert Ok(caps) = glint.get_flag(flags, caps_flag()) + let assert Ok(repeat) = glint.get_flag(flags, repeat_flag()) let name = name(named_args) hello(name, [], caps, repeat) } @@ -111,7 +105,7 @@ pub fn app() { // create a new glint instance glint.new() // with an app name of "hello", this is used when printing help text - |> glint.name("hello") + |> glint.with_name("hello") // show in usage text that the current app is run as a gleam module |> glint.as_module // with pretty help enabled, using the built-in colours diff --git a/examples/hello/test/hello_test.gleam b/examples/hello/test/hello_test.gleam index bb15fb7..2eb4695 100644 --- a/examples/hello/test/hello_test.gleam +++ b/examples/hello/test/hello_test.gleam @@ -39,6 +39,8 @@ pub fn hello_test() { pub fn app_test() { hello.app() - |> glint.execute(["Joe", "Gleamlins"]) - |> should.equal(Ok(glint.Out("Hello, Joe and Gleamlins!"))) + |> glint.execute(["Joe", "Gleamlins", "--repeat=2", "--caps"]) + |> should.equal( + Ok(glint.Out("HELLO, JOE AND GLEAMLINS!\nHELLO, JOE AND GLEAMLINS!")), + ) } diff --git a/src/glint.gleam b/src/glint.gleam index 5d1c43a..d4cf7cf 100644 --- a/src/glint.gleam +++ b/src/glint.gleam @@ -32,7 +32,7 @@ pub type PrettyHelp { // -- CONFIGURATION: CONSTANTS -- -/// Default config +/// default config /// const default_config = Config(pretty_help: None, name: None, as_module: False) @@ -53,7 +53,7 @@ pub fn pretty_help(glint: Glint(a), pretty: PrettyHelp) -> Glint(a) { /// Give the current glint application a name /// -pub fn name(glint: Glint(a), name: String) -> Glint(a) { +pub fn with_name(glint: Glint(a), name: String) -> Glint(a) { config(glint, Config(..glint.config, name: Some(name))) } @@ -485,7 +485,7 @@ pub fn run_and_handle( } } -/// Default pretty help heading colouring +/// default pretty help heading colouring /// mint (r: 182, g: 255, b: 234) colour for usage /// pink (r: 255, g: 175, b: 243) colour for flags /// buttercup (r: 252, g: 226, b: 174) colour for subcommands @@ -953,63 +953,63 @@ type FlagInternals(a) { type Parser(a, b) = fn(String) -> gleam.Result(a, b) -/// initialise an int flag builder +/// initialise an int flag /// pub fn int(named name: String) -> Flag(Int) { - use input <- new_builder(name, I, get_int) + use input <- new_builder(name, I, get_int_flag) input |> int.parse |> result.replace_error(cannot_parse(input, "int")) } -/// initialise an int list flag builder +/// initialise an int list flag /// pub fn ints(named name: String) -> Flag(List(Int)) { - use input <- new_builder(name, LI, get_ints) + use input <- new_builder(name, LI, get_ints_flag) input |> string.split(",") |> list.try_map(int.parse) |> result.replace_error(cannot_parse(input, "int list")) } -/// initialise a float flag builder +/// initialise a float flag /// pub fn float(named name: String) -> Flag(Float) { - use input <- new_builder(name, F, get_float) + use input <- new_builder(name, F, get_floats) input |> float.parse |> result.replace_error(cannot_parse(input, "float")) } -/// initialise a float list flag builder +/// initialise a float list flag /// pub fn floats(named name: String) -> Flag(List(Float)) { - use input <- new_builder(name, LF, get_floats) + use input <- new_builder(name, LF, get_floats_flag) input |> string.split(",") |> list.try_map(float.parse) |> result.replace_error(cannot_parse(input, "float list")) } -/// initialise a string flag builder +/// initialise a string flag /// pub fn string(named name: String) -> Flag(String) { - new_builder(name, S, get_string, fn(s) { Ok(s) }) + new_builder(name, S, get_string_flag, fn(s) { Ok(s) }) } -/// intitialise a string list flag builder +/// intitialise a string list flag /// pub fn strings(named name: String) -> Flag(List(String)) { - use input <- new_builder(name, LS, get_strings) + use input <- new_builder(name, LS, get_strings_flag) input |> string.split(",") |> Ok } -/// initialise a bool flag builder +/// initialise a bool flag /// pub fn bool(named name: String) -> Flag(Bool) { - use input <- new_builder(name, B, get_bool) + use input <- new_builder(name, B, get_bool_flag) case string.lowercase(input) { "true" | "t" -> Ok(True) "false" | "f" -> Ok(False) @@ -1044,7 +1044,7 @@ fn build_flag(fb: Flag(a)) -> FlagEntry { ) } -/// attach a constraint to a `FlagEntry` +/// attach a constraint to a flag /// pub fn constraint(builder: Flag(a), constraint: Constraint(a)) -> Flag(a) { Flag(..builder, parser: wrap_with_constraint(builder.parser, constraint)) @@ -1079,9 +1079,9 @@ pub fn flag_help(for builder: Flag(a), of description: String) -> Flag(a) { Flag(..builder, desc: description) } -/// Set the default value for a flag `Value` +/// Set the flag_default value for a flag `Value` /// -pub fn default(for builder: Flag(a), of default: a) -> Flag(a) { +pub fn flag_default(for builder: Flag(a), of default: a) -> Flag(a) { Flag(..builder, default: Some(default)) } @@ -1230,9 +1230,18 @@ fn get_value( |> snag.context("failed to retrieve value for flag '" <> key <> "'") } +/// Gets the value for the associated flag. +/// +/// This function should only ever be used when fetching flags set at the group level. +/// For local flags please use the getter functions provided when calling `glint.flag`. +/// +pub fn get_flag(from flags: Flags, for flag: Flag(a)) -> snag.Result(a) { + flag.getter(flags, flag.name) +} + /// Gets the current value for the associated int flag /// -pub fn get_int(from flags: Flags, for name: String) -> snag.Result(Int) { +fn get_int_flag(from flags: Flags, for name: String) -> snag.Result(Int) { use flag <- get_value(flags, name) case flag.value { I(FlagInternals(value: Some(val), ..)) -> Ok(val) @@ -1243,7 +1252,7 @@ pub fn get_int(from flags: Flags, for name: String) -> snag.Result(Int) { /// Gets the current value for the associated ints flag /// -pub fn get_ints(from flags: Flags, for name: String) -> snag.Result(List(Int)) { +fn get_ints_flag(from flags: Flags, for name: String) -> snag.Result(List(Int)) { use flag <- get_value(flags, name) case flag.value { LI(FlagInternals(value: Some(val), ..)) -> Ok(val) @@ -1254,7 +1263,7 @@ pub fn get_ints(from flags: Flags, for name: String) -> snag.Result(List(Int)) { /// Gets the current value for the associated bool flag /// -pub fn get_bool(from flags: Flags, for name: String) -> snag.Result(Bool) { +fn get_bool_flag(from flags: Flags, for name: String) -> snag.Result(Bool) { use flag <- get_value(flags, name) case flag.value { B(FlagInternals(Some(val), ..)) -> Ok(val) @@ -1265,7 +1274,7 @@ pub fn get_bool(from flags: Flags, for name: String) -> snag.Result(Bool) { /// Gets the current value for the associated string flag /// -pub fn get_string(from flags: Flags, for name: String) -> snag.Result(String) { +fn get_string_flag(from flags: Flags, for name: String) -> snag.Result(String) { use flag <- get_value(flags, name) case flag.value { S(FlagInternals(value: Some(val), ..)) -> Ok(val) @@ -1276,7 +1285,7 @@ pub fn get_string(from flags: Flags, for name: String) -> snag.Result(String) { /// Gets the current value for the associated strings flag /// -pub fn get_strings( +fn get_strings_flag( from flags: Flags, for name: String, ) -> snag.Result(List(String)) { @@ -1290,7 +1299,7 @@ pub fn get_strings( /// Gets the current value for the associated float flag /// -pub fn get_float(from flags: Flags, for name: String) -> snag.Result(Float) { +fn get_floats(from flags: Flags, for name: String) -> snag.Result(Float) { use flag <- get_value(flags, name) case flag.value { F(FlagInternals(value: Some(val), ..)) -> Ok(val) @@ -1299,9 +1308,9 @@ pub fn get_float(from flags: Flags, for name: String) -> snag.Result(Float) { } } -/// Gets the current value for the associated floats flag +/// Gets the current value for the associated float flag /// -pub fn get_floats( +fn get_floats_flag( from flags: Flags, for name: String, ) -> snag.Result(List(Float)) { diff --git a/test/flag_test.gleam b/test/flag_test.gleam index 8ce83b1..17fe7e1 100644 --- a/test/flag_test.gleam +++ b/test/flag_test.gleam @@ -8,7 +8,7 @@ pub fn update_flag_test() { use _bflag <- glint.flag(glint.bool("bflag")) use _sflag <- glint.flag(glint.string("sflag")) use _lsflag <- glint.flag(glint.strings("lsflag")) - use _iflag <- glint.flag(glint.int("iflag")) + use _iflag <- glint.flag(glint.ints("iflag")) use _liflag <- glint.flag(glint.ints("liflag")) use _fflag <- glint.flag(glint.float("fflag")) use _lfflag <- glint.flag(glint.floats("lfflag")) @@ -97,7 +97,7 @@ pub fn flag_default_test() { let args = ["arg1", "arg2"] let flag = glint.string("flag") - |> glint.default("default") + |> glint.flag_default("default") glint.new() |> glint.add(["cmd"], { @@ -288,16 +288,17 @@ pub fn floats_flag_test() { } pub fn global_flag_test() { + let flag = glint.floats("flag") let testcase = fn(vals: List(Float)) { use _, _, flags <- glint.command() flags - |> glint.get_floats("flag") + |> glint.get_flag(flag) |> should.equal(Ok(vals)) } // set global flag, pass in new value for flag glint.new() - |> glint.group_flag([], glint.floats("flag")) + |> glint.group_flag([], flag) |> glint.add(at: [], do: testcase([3.0, 4.0])) |> glint.execute(["--flag=3.0,4.0"]) |> should.be_ok() @@ -309,7 +310,7 @@ pub fn global_flag_test() { at: [], do: glint.flag( glint.floats("flag") - |> glint.default([1.0, 2.0]), + |> glint.flag_default([1.0, 2.0]), fn(_) { testcase([1.0, 2.0]) }, ), ) @@ -321,12 +322,12 @@ pub fn global_flag_test() { |> glint.group_flag( [], glint.floats("flag") - |> glint.default([3.0, 4.0]), + |> glint.flag_default([3.0, 4.0]), ) |> glint.add(at: [], do: { use _flag <- glint.flag( glint.floats("flag") - |> glint.default([1.0, 2.0]), + |> glint.flag_default([1.0, 2.0]), ) testcase([5.0, 6.0]) @@ -366,7 +367,7 @@ pub fn toggle_test() { |> glint.add([], { use flag <- glint.flag( glint.bool("flag") - |> glint.default(True), + |> glint.flag_default(True), ) use _, _, flags <- glint.command() flag(flags) @@ -391,7 +392,7 @@ pub fn toggle_test() { |> glint.add([], { use _flag <- glint.flag( glint.int("flag") - |> glint.default(1), + |> glint.flag_default(1), ) use _, _, _ <- glint.command() Nil @@ -405,31 +406,31 @@ pub fn getters_test() { |> glint.add([], { use bflag <- glint.flag( glint.bool("bflag") - |> glint.default(True), + |> glint.flag_default(True), ) use sflag <- glint.flag( glint.string("sflag") - |> glint.default(""), + |> glint.flag_default(""), ) use lsflag <- glint.flag( glint.strings("lsflag") - |> glint.default([]), + |> glint.flag_default([]), ) use iflag <- glint.flag( glint.int("iflag") - |> glint.default(1), + |> glint.flag_default(1), ) use liflag <- glint.flag( glint.ints("liflag") - |> glint.default([]), + |> glint.flag_default([]), ) use fflag <- glint.flag( glint.float("fflag") - |> glint.default(1.0), + |> glint.flag_default(1.0), ) use lfflag <- glint.flag( glint.floats("lfflag") - |> glint.default([]), + |> glint.flag_default([]), ) use _, _, flags <- glint.command() diff --git a/test/glint_test.gleam b/test/glint_test.gleam index 6a8089e..ea8500a 100644 --- a/test/glint_test.gleam +++ b/test/glint_test.gleam @@ -127,7 +127,7 @@ pub fn help_test() { let cli = glint.new() - |> glint.name("test") + |> glint.with_name("test") |> glint.as_module |> glint.group_flag([], global_flag) |> glint.add(at: [], do: { @@ -284,18 +284,23 @@ FLAGS: } pub fn global_and_group_flags_test() { + let flag_f = + glint.int("f") + |> glint.flag_default(2) + |> glint.flag_help("global flag example") + + let sub_group_flag = + "sub_group_flag" + |> glint.int() + |> glint.flag_default(1) + let cli = glint.new() - |> glint.group_flag( - [], - glint.int("f") - |> glint.default(2) - |> glint.flag_help("global flag example"), - ) + |> glint.group_flag([], flag_f) |> glint.add( [], glint.command(fn(_, _, flags) { - glint.get_int(flags, "f") + glint.get_flag(flags, flag_f) |> should.equal(Ok(2)) }), ) @@ -303,24 +308,19 @@ pub fn global_and_group_flags_test() { use f <- glint.flag( "f" |> glint.bool() - |> glint.default(True) + |> glint.flag_default(True) |> glint.flag_help("i decided to override the global flag"), ) use _, _, flags <- glint.command() f(flags) |> should.equal(Ok(True)) }) - |> glint.group_flag( - ["sub"], - "sub_group_flag" - |> glint.int() - |> glint.default(1), - ) + |> glint.group_flag(["sub"], sub_group_flag) |> glint.add(["sub", "sub"], { use f <- glint.flag( "f" |> glint.bool() - |> glint.default(True) + |> glint.flag_default(True) |> glint.flag_help("i decided to override the global flag"), ) use _, _, flags <- glint.command() @@ -328,7 +328,7 @@ pub fn global_and_group_flags_test() { |> should.equal(Ok(True)) flags - |> glint.get_int("sub_group_flag") + |> glint.get_flag(sub_group_flag) |> should.equal(Ok(2)) })