The CommandNode instatiation for this resolver.
Defines a command sentence.
Attempts to resolve a range of words/a sentence into a CommandNode.
Peforms the same task as CommandResolver.resolve, except that it will also advance the given parser to the next unparsed argument.
Notes: While the returned array is mutable, the nodes stored in this array are *not* the same nodes stored in the actual search tree. This means that any changes made to this array will not be reflected by the results of resolve and resolveAndAdvance.
User-provided data for each command (CommandNodes of type CommandNodeType.finalWord).
Description: In essence, this class is just an abstraction around a basic tree structure (CommandNode), to make it easy to both define and search the tree.
First of all, JCLI supports commands having multiple "words" within them, such as "build all libs"; "remote get-url", etc. This entire collection of "words" is referred to as a "sentence".
The tree for the resolver consists of words pointing to any following words (CommandNodeType.partialWord), ultimately ending each branch with the final command word (CommandNodeType.finalWord).
For example, if we had the following commands "build libs"; "build apps", and "test libs", the tree would look like the following.
1 import std.algorithm : map, equal; 2 3 // Define UserData as a struct containing an execution method. Define a UserData which toggles a value. 4 static struct UserData 5 { 6 void delegate() @safe execute; 7 } 8 9 bool executeValue; 10 void toggleValue() @safe 11 { 12 executeValue = !executeValue; 13 } 14 15 auto userData = UserData(&toggleValue); 16 17 // Create the resolver and define three command paths: "toggle", "please toggle", and "please tog". 18 // Tree should look like: 19 // [root] 20 // / \ 21 // toggle please 22 // / \ 23 // toggle tog 24 auto resolver = new CommandResolver!UserData; 25 resolver.define("toggle", userData); 26 resolver.define("please toggle", userData); 27 resolver.define("please tog", userData); 28 29 // Resolve 'toggle' and call its execute function. 30 auto result = resolver.resolve("toggle"); 31 assert(result.success); 32 assert(result.value.word == "toggle"); 33 assert(result.value.sentence == "toggle"); 34 assert(result.value.type == CommandNodeType.finalWord); 35 assert(result.value.userData.execute !is null); 36 result.value.userData.execute(); 37 assert(executeValue == true); 38 39 // Resolve 'please' and confirm that it's only a partial match. 40 result = resolver.resolve("please"); 41 assert(result.success); 42 assert(result.value.word == "please"); 43 assert(result.value.sentence is null); 44 assert(result.value.type == CommandNodeType.partialWord); 45 assert(result.value.children.length == 2); 46 assert(result.value.userData == UserData.init); 47 48 // Resolve 'please toggle' and call its execute function. 49 result = resolver.resolve("please toggle"); 50 assert(result.success); 51 assert(result.value.word == "toggle"); 52 assert(result.value.sentence == "please toggle"); 53 assert(result.value.type == CommandNodeType.finalWord); 54 result.value.userData.execute(); 55 assert(executeValue == false); 56 57 // Resolve 'please tog' and call its execute function. (to test nodes with multiple children). 58 result = resolver.resolve("please tog"); 59 assert(result.success); 60 assert(result.value.word == "tog"); 61 assert(result.value.sentence == "please tog"); 62 assert(result.value.type == CommandNodeType.finalWord); 63 result.value.userData.execute(); 64 assert(executeValue == true); 65 66 // Resolve a few non-existing command sentences, and ensure that they were unsuccessful. 67 assert(!resolver.resolve(null).success); 68 assert(!resolver.resolve("toggle please").success); 69 assert(!resolver.resolve("He she we, wombo.").success); 70 71 // Test that final words are properly tracked. 72 assert(resolver.finalWords.map!(w => w.word).equal(["toggle", "toggle", "tog"])); 73 assert(resolver.root.finalWords.equal(resolver.finalWords)); 74 75 auto node = resolver.resolve("please").value; 76 assert(node.finalWords().map!(w => w.word).equal(["toggle", "tog"]));
A helper class where you can define command "sentences", and then resolve (either partially or fully) commands from "sentences" provided by the user.