1 module jcli.commandgraph.wrapper;
2
3 import jcli.commandgraph;
4 import jcli.commandgraph.internal;
5
6 private alias State = MatchAndExecuteState;
7
8 struct MatchAndParseContextWrapper(
9 alias CommandTypeContext,
10 // Either pointer to MatchAndExecuteContext, or that itself
11 ContextType = MatchAndExecuteContext)
12 {
13 ContextType _context;
14 alias _context this;
15
16 pure nothrow @nogc:
17
18 auto contextPointer() inout
19 {
20 static if (is(ContextType : T*, T))
21 return _context;
22 else
23 return &_context;
24 }
25
26 auto command(int typeIndex)()
27 {
28 return IndexHelper!(typeIndex, CommandTypeContext)(contextPointer);
29 }
30
31 auto command(CommandType)()
32 {
33 enum index = CommandTypeContext.indexOf!CommandType;
34 return IndexHelper!(index, CommandTypeContext)(contextPointer);
35 }
36
37 SpecialThings specialThing() const
38 {
39 assert(_context._state == State.specialThing);
40 return _context._specialThing;
41 }
42
43 inout(ExecuteCommandResult) executeCommandResult() inout
44 {
45 assert(_context._state == State.intermediateExecutionResult
46 || _context._state == State.finalExecutionResult);
47 return _context._executeCommandResult;
48 }
49
50 string matchedName() const
51 {
52 assert(_context._state == State.matchedNextCommand
53 || _context._state == State.matchedRootCommand);
54 return _context._matchedName;
55 }
56
57 string notMatchedName() const
58 {
59 assert(_context._state == State.notMatchedNextCommand
60 || _context._state == State.notMatchedRootCommand);
61 return _context._notMatchedName;
62 }
63
64 State state() const @safe { return _state; }
65
66 // SumType-like match, maybe?
67 // template match();
68 }
69
70 auto wrapContext(Types)(scope ref MatchAndExecuteContext context) return
71 {
72 return *cast(MatchAndParseContextWrapper!Types*) &context;
73 }
74
75 // This is kind of what I mean by a type-safe wrapper, but it also needs getters for everything
76 // that would assert if the state is right and stuff like that.
77 // Currently, this one is only used for tests.
78 struct SimpleMatchAndExecuteHelper(alias Graph)
79 {
80 alias bindArgument = jcli.argbinder.bindArgument!();
81 alias _CommandTypeContext = CommandTypeContext!(Graph);
82 alias TypeContext = MatchAndExecuteTypeContext!(bindArgument, _CommandTypeContext);
83
84 MatchAndParseContextWrapper!_CommandTypeContext context;
85 TypeContext.ParsingContext parsingContext;
86 ArgTokenizer!(string[]) tokenizer;
87 ErrorCodeHandler errorHandler;
88
89
90 this(string[] args)
91 {
92 tokenizer = argTokenizer(args);
93 parsingContext = TypeContext.ParsingContext();
94 context = MatchAndParseContextWrapper!_CommandTypeContext();
95 errorHandler = createErrorCodeHandler();
96 }
97
98 void advance()
99 {
100 TypeContext.advanceState(context, parsingContext, tokenizer, errorHandler);
101 }
102 }