@@ -43,39 +43,66 @@ def __init__(self):
43
43
self .isatty = sys .stdout .isatty ()
44
44
45
45
def main (self ):
46
- arg_parser = argparse .ArgumentParser (description = 'Static Analyzer for the Clarity language from Stacks' )
47
- subparsers = arg_parser .add_subparsers (dest = "command" , help = "Commands" )
48
-
49
- lint_parser = subparsers .add_parser ("lint" , help = "Run detectors in a given contract or contracts directory" )
50
- lint_parser .add_argument ("path" , type = str , help = "Path" )
51
- lint_parser .add_argument ("--filter" , nargs = "+" , type = str , help = "Comma-separated list of detector names to use" )
52
- lint_parser .add_argument ("--exclude" , nargs = "+" , type = str ,
53
- help = "Comma-separated list of detector names to exclude" )
54
- list_detectors = subparsers .add_parser ("detectors" , help = "List detectors" )
55
- lint_parser .add_argument ("-A" , nargs = "+" , type = int ,
56
- help = "Print A lines of trailing context after findings." )
57
- lint_parser .add_argument ("-B" , nargs = "+" , type = int ,
58
- help = "Print B lines of leading context before findings." )
59
- lint_parser .add_argument ("-C" , nargs = "+" , type = int ,
60
- help = "Print C lines of leading and trailing context after and before findings. Takes precedence over -A and -B" )
46
+ def comma_separated_list (value ):
47
+ return value .split (',' )
48
+
49
+ class StacyParser (argparse .ArgumentParser ):
50
+ def format_help (self ):
51
+ formatter = self ._get_formatter ()
52
+ formatter .add_text (self .description )
53
+ formatter .add_usage (self .usage , self ._actions ,
54
+ self ._mutually_exclusive_groups )
55
+ formatter .add_text (self .epilog )
56
+
57
+ # Add subparsers help
58
+ subparsers_actions = [
59
+ action for action in self ._actions
60
+ if isinstance (action , argparse ._SubParsersAction )]
61
+ for subparsers_action in subparsers_actions :
62
+ for choice , subparser in subparsers_action .choices .items ():
63
+ formatter .start_section (f"{ choice } subcommand" )
64
+ formatter .add_text (subparser .description )
65
+ formatter .add_arguments (subparser ._actions )
66
+ formatter .end_section ()
67
+
68
+ return formatter .format_help ()
69
+
70
+ arg_parser = StacyParser (description = 'Static Analyzer for the Clarity language from Stacks' )
71
+ subparsers = arg_parser .add_subparsers (dest = "command" , help = "Available commands" )
72
+
73
+ lint_parser = subparsers .add_parser ("lint" , help = "Run detectors on a given contract or contracts directory" )
74
+ lint_parser .add_argument ("path" , type = str , help = "Path to the contract file or directory" )
75
+ lint_parser .add_argument ("--filter" , type = comma_separated_list , metavar = "lint1,lint2,..." ,
76
+ help = "List of detector names to use" )
77
+ lint_parser .add_argument ("--exclude" , type = comma_separated_list , metavar = "lint1,lint2,..." ,
78
+ help = "List of detector names to exclude" )
79
+ lint_parser .add_argument ("-A" , type = int , metavar = "x" ,
80
+ help = "Print x lines of trailing context after findings" )
81
+ lint_parser .add_argument ("-B" , type = int , metavar = "x" ,
82
+ help = "Print x lines of leading context before findings" )
83
+ lint_parser .add_argument ("-C" , type = int , metavar = "x" ,
84
+ help = "Print x lines of leading and trailing context (overrides -A and -B)" )
85
+
86
+ list_detectors = subparsers .add_parser ("detectors" , help = "List available detectors" )
87
+
61
88
user_args = arg_parser .parse_args ()
62
89
if user_args .command == "lint" :
63
90
64
91
tc = 0
65
92
lc = 0
66
93
67
94
if user_args .A is not None :
68
- tc = user_args .A [ 0 ]
95
+ tc = user_args .A
69
96
70
97
if user_args .B is not None :
71
- lc = user_args .B [ 0 ]
98
+ lc = user_args .B
72
99
73
100
if user_args .C is not None :
74
- tc = user_args .C [ 0 ]
75
- lc = user_args .C [ 0 ]
101
+ tc = user_args .C
102
+ lc = user_args .C
76
103
77
- filters = list (self .DETECTOR_MAP .keys ()) if user_args .filter is None else user_args .filter [ 0 ]. split ( ',' )
78
- excludes = [] if user_args .exclude is None else user_args .exclude [ 0 ]. split ( ',' )
104
+ filters = list (self .DETECTOR_MAP .keys ()) if user_args .filter is None else user_args .filter
105
+ excludes = [] if user_args .exclude is None else user_args .exclude
79
106
detectors = self .get_detectors (filters , excludes )
80
107
path = user_args .path
81
108
if path .endswith (".clar" ):
0 commit comments