Conversation
caelunshun
left a comment
There was a problem hiding this comment.
Nice work!
My thoughts: if we remove the lifetime parameters on command structs as per my comment below, it should be possible to cache the root Command. With this done, we should implement some sort of acceleration structure (the current implementation does a linear search on all commands).
|
Still some issues left, one of the bigger one being F: for<'a> Func<
<<<(&'a mut C,) as Tuple>::HList as Combine<<P::Extract as Tuple>::HList>>::Output as HList>::Tuple
>,Such that we can use literal("foo").and(param()).exec(|ctx, n: i32| *ctx += n); |
|
Damn ugly tubofish... for some reason it cannot figure out where let root = literal("hello")
.and(literal("world"))
.exec::<_, (_,)>(|n: &mut i32| *n = 42);
let mut n = 45;
if let Some((command,)) = root.parse(&mut "hello world".into()) {
command.call((&mut n,));
}
assert_eq!(n, 42);
let command = root.parse(&mut "bar".into());
assert!(command.is_none());One way of getting around this, is not to have |
|
Alternatively, we can use a mapping, that maps "Self::Extracted -> T" let root = literal("hello")
.and(literal("world"))
.and(param())
.map(|a: i32| move |n: &mut i32| *n += a);
let mut n = 45;
if let Some((command,)) = root.parse(&mut "hello world -3".into()) {
command(&mut n)
}Async commands could be handled as let root = literal("foo")
.and(param())
.map(|a: i32| move |n: i32| async move { n + a });
if let Some((command,)) = root.parse(&mut "foo 10".into()) {
let res = smol::run(command(0));
assert_eq!(res, 10)
}We cant use |
|
There's still a few issue remaining.
Error handling and suggestionsOne way of handling suggestions is to "parse" the input and suggest have the errors contain the suggestions. This, however, would require some special handling Alternatively to the using error handling as suggestions, we could have a Guards / ProvidersIt would be nice to have some sort of guards and or providers. literal("tp").then(param()).map(|pos: Position| move |state: State, _: Permission<{"tp"}>| { ... });
literal("tp").then(param()).map(|pos: Position| move permission("tp", |state: State| { ... }));
literal("tp").then(param()).guard(permission("tp")).map(|pos: Position| move |state: State| { ... }); |
Currently, it works, but the parse tree has to be recreated each time, which is not ideal.
Still, some work left, need some way to track the depth and give an appropriate error message accordingly.
Might want swap
fnout forFuncand do someCombinesuch that the closure signature is a bit cleaner.