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 }