1 module cogito.arguments; 2 3 import argparse; 4 import std.algorithm; 5 import std.conv; 6 import std.format; 7 import std.range; 8 import std.traits; 9 10 // Help message. 11 private enum string returnCodes = q"HELP 12 Return codes: 13 0 Success 14 1 Command line arguments are invalid 15 2 Some source files contain errors 16 3 Function threshold violation 17 4 Aggregate threshold violation 18 5 Module threshold violation 19 HELP"; 20 21 /** 22 * Possible output formats. 23 */ 24 enum OutputFormat 25 { 26 silent, 27 flat, 28 verbose, 29 debug_, 30 } 31 32 private enum string allowedOutputFormat(OutputFormat Member) = 33 Member.to!string.strip('_'); 34 private enum string[] allowedOutputFormats = [ 35 staticMap!(allowedOutputFormat, EnumMembers!OutputFormat) 36 ]; 37 38 private OutputFormat parseOutputFormat(string input) 39 { 40 switch (input) 41 { 42 case "debug": 43 return OutputFormat.debug_; 44 case "silent": 45 return OutputFormat.silent; 46 case "flat": 47 return OutputFormat.flat; 48 case "verbose": 49 return OutputFormat.verbose; 50 default: 51 enum string validValues = allowedOutputFormats.join(','); 52 enum string errorFormat = 53 "Invalid value '%s' for argument '--format'.\nValid argument values are: %s"; 54 throw new Exception(format!errorFormat(input, validValues)); 55 } 56 } 57 58 /** 59 * Arguments supported by the CLI. 60 */ 61 @(Command("cogito").Epilog(returnCodes)) 62 struct Arguments 63 { 64 /// Input files. 65 @(PositionalArgument(0).Description("Source files").Required()) 66 string[] files = []; 67 68 /// Module threshold. 69 @(NamedArgument(["module-threshold"]) 70 .Optional() 71 .Description("Fail if the source score exceeds this threshold") 72 .Placeholder("NUMBER")) 73 uint moduleThreshold = 0; 74 75 /// Function threshold. 76 @(NamedArgument(["threshold"]) 77 .Optional() 78 .Description("Fail if a function score exceeds this threshold") 79 .Placeholder("NUMBER")) 80 uint threshold = 0; 81 82 /// Aggregate threshold. 83 @(NamedArgument(["aggregate-threshold"]) 84 .Optional() 85 .Description("Fail if an aggregate exceeds this threshold") 86 .Placeholder("NUMBER")) 87 uint aggregateThreshold = 0; 88 89 /// Output format. 90 @(NamedArgument 91 .AllowedValues!allowedOutputFormats 92 .PreValidation!((string x) => true) 93 .Parse!parseOutputFormat 94 .Validation!((OutputFormat x) => true) 95 ) 96 OutputFormat format = OutputFormat.flat; 97 }