Skip to content

Commit

Permalink
dynamic flags POC
Browse files Browse the repository at this point in the history
  • Loading branch information
TanklesXL committed Jul 28, 2023
1 parent bdd4098 commit 44640b7
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/glint/flag.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import snag.{Result, Snag}
import gleam/option.{None, Option, Some}
import gleam/function.{apply1}
import glint/flag/constraint.{Constraint}
import gleam/dynamic.{Dynamic}
import gleam

/// Flag inputs must start with this prefix
///
Expand Down Expand Up @@ -49,6 +51,10 @@ pub type Value {
/// List(String) flags, to be passed in as `--flag=hello,world`
///
LS(Internal(List(String)))

/// Dynamic flags
///
D(fn(String) -> snag.Result(Dynamic), Internal(Dynamic))
}

/// ValueBuilder is a conveniency type to describe the constructors of the Value type.
Expand Down Expand Up @@ -208,6 +214,12 @@ fn compute_flag(
S(internal) -> parse_string(name, input, internal)
LS(internal) -> parse_string_list(name, input, internal)
B(internal) -> parse_bool(name, input, internal)
D(parser, internal) as d -> {
use val <- result.try(parser(input))

apply_constraints(name, val, internal.constraints)
|> result.replace(D(parser, Internal(..internal, value: Some(val))))
}
}
}

Expand Down Expand Up @@ -316,6 +328,7 @@ pub fn flag_type_help(flag: #(String, Flag)) {
LI(_) -> "INT_LIST"
LS(_) -> "STRING_LIST"
S(_) -> "STRING"
D(..) -> "DYNAMIC"
}

prefix <> name <> delimiter <> "<" <> kind <> ">"
Expand Down Expand Up @@ -462,3 +475,39 @@ pub fn get_floats(from flags: Map, for name: String) -> Result(List(Float)) {
use value <- result.try(access(flags, name))
get_floats_value(#(name, value))
}

/// Gets the current value for the associated floats flag
///
pub fn get_dynamic(from flags: Map, for name: String) -> Result(Dynamic) {
use value <- result.try(access(flags, name))
get_dynamic_value(#(name, value))
}

/// Gets the current value for the provided floats flag
///
pub fn get_dynamic_value(from flag: #(String, Flag)) -> Result(Dynamic) {
case { flag.1 }.value {
D(_, Internal(value: Some(val), ..)) -> Ok(val)
D(_, Internal(value: None, ..)) -> flag_not_provided_error(flag.0)
_ -> access_type_error(flag.0, "dynamic")
}
}

/// Gets and decodes the current value for the associated dynamic flag
pub fn decode_dynamic(
from flags: Map,
for name: String,
with decoder: fn(Dynamic) -> gleam.Result(a, List(dynamic.DecodeError)),
) -> Result(a) {
use value <- result.try(get_dynamic(flags, name))
use errs <- result.map_error(decoder(value))
{
use acc, err <- list.fold(
errs,
snag.new("failed to decode dynamic flag data"),
)
err
|> string.inspect
|> snag.layer(acc, _)
}
}
62 changes: 62 additions & 0 deletions test/glint/flag_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -485,3 +485,65 @@ pub fn flags_help_test() {
"--s=<STRING>\t\ta string flag",
])
}

import gleam/int
import gleam/dynamic
import gleam/result
import snag

pub fn flag_test() {
let flag = #(
"d",
flag.D(
fn(s) {
use i <- result.try(
int.parse(s)
|> result.replace_error(snag.new("")),
)
Ok(dynamic.from(i))
},
_,
)
|> flag.new()
|> flag.default(dynamic.from(0))
|> flag.description("a dynamic flag"),
)

glint.new()
|> glint.add(
[],
glint.command(fn(in: CommandInput) {
flag.decode_dynamic(in.flags, "d", dynamic.int)
// default value
|> should.equal(Ok(0))
})
|> glint.flag_tuple(flag),
)
|> glint.execute([])
|> should.be_ok()

glint.new()
|> glint.add(
[],
glint.command(fn(in: CommandInput) {
flag.decode_dynamic(in.flags, "d", dynamic.int)
|> should.equal(Ok(1))
})
|> glint.flag_tuple(flag),
)
|> glint.execute(["--d=1"])
|> should.be_ok()

glint.new()
|> glint.add(
[],
glint.command(fn(in: CommandInput) {
// the flag is set as int, we are asking for a float, which will fail
flag.decode_dynamic(in.flags, "d", dynamic.float)
|> should.be_error()
})
|> glint.flag_tuple(flag),
)
|> glint.execute(["--d=1"])
|> should.be_ok()
}

0 comments on commit 44640b7

Please sign in to comment.