11import argparse
2- from typing import Any , Dict , Optional
2+ import sys
3+ from typing import Any , Dict , NoReturn
34
4- from strictdoc .cli .command_parser_builder import (
5- COMMAND_REGISTRY ,
6- CommandParserBuilder ,
7- )
5+ from strictdoc import __version__
86from strictdoc .helpers .cast import assert_cast
97from strictdoc .helpers .parallelizer import Parallelizer
108
119
10+ def formatter (prog : str ) -> argparse .RawTextHelpFormatter :
11+ return argparse .RawTextHelpFormatter (
12+ prog , indent_increment = 2 , max_help_position = 4 , width = 80
13+ )
14+
15+
16+ class SDocArgumentParser (argparse .ArgumentParser ):
17+ def error (self , message : str ) -> NoReturn :
18+ self .print_usage (sys .stderr )
19+ print (f"{ self .prog } : error: { message } " , file = sys .stderr ) # noqa: T201
20+ print ("" ) # noqa: T201
21+ print ("Further help:" ) # noqa: T201
22+ print ( # noqa: T201
23+ "'strictdoc -h/--help' provides a general overview of available commands."
24+ )
25+ print ( # noqa: T201
26+ "'strictdoc <command> -h/--help' provides command-specific help."
27+ )
28+ sys .exit (2 )
29+
30+
1231class SDocArgsParser :
32+ @classmethod
33+ def create_sdoc_args_parser (
34+ cls , registry : Dict [str , Any ]
35+ ) -> "SDocArgsParser" :
36+ parser = cls .build_argparse (registry )
37+ args = parser .parse_args ()
38+ return cls (args , registry )
39+
1340 def __init__ (self , args : argparse .Namespace , registry : Dict [str , Any ]):
1441 self .args : argparse .Namespace = args
1542 self .registry : Dict [str , Any ] = registry
@@ -31,13 +58,61 @@ def run(self, parallelizer: Parallelizer) -> bool:
3158
3259 return True
3360
61+ @classmethod
62+ def build_argparse (cls , registry : Dict [str , Any ]) -> SDocArgumentParser :
63+ # https://stackoverflow.com/a/19476216/598057
64+ main_parser = SDocArgumentParser (
65+ prog = "strictdoc" ,
66+ add_help = True ,
67+ epilog = (
68+ """
69+ Further help: https://strictdoc.readthedocs.io/en/stable/
70+ """
71+ ),
72+ )
3473
35- def create_sdoc_args_parser (
36- testing_args : Optional [argparse .Namespace ] = None ,
37- ) -> SDocArgsParser :
38- args = testing_args
39- if not args :
40- builder = CommandParserBuilder ()
41- parser = builder .build ()
42- args = parser .parse_args ()
43- return SDocArgsParser (args , COMMAND_REGISTRY )
74+ # The -v/--version has a special behavior that it still works when all
75+ # commands are required == True.
76+ # https://stackoverflow.com/a/12123598/598057
77+ main_parser .add_argument (
78+ "-v" , "--version" , action = "version" , version = __version__
79+ )
80+
81+ main_parser .add_argument (
82+ "--debug" ,
83+ action = "store_true" ,
84+ default = False ,
85+ help = "Enable more verbose printing of errors when they are encountered." ,
86+ )
87+
88+ command_subparsers = main_parser .add_subparsers (
89+ title = "command" , dest = "command"
90+ )
91+ command_subparsers .required = True
92+
93+ # Dynamically add subcommands
94+ for name , cmd in registry .items ():
95+ if isinstance (cmd , dict ): # command family
96+ family_parser = command_subparsers .add_parser (name )
97+ family_subparsers = family_parser .add_subparsers (
98+ dest = "subcommand"
99+ )
100+ family_subparsers .required = True
101+ for subname , subcmd in cmd .items ():
102+ sub_parser = family_subparsers .add_parser (
103+ subname ,
104+ help = subcmd .HELP ,
105+ description = subcmd .DETAILED_HELP ,
106+ formatter_class = formatter ,
107+ )
108+ subcmd .add_arguments (sub_parser )
109+ else :
110+ cmd_parser = command_subparsers .add_parser (
111+ name ,
112+ help = cmd .HELP ,
113+ description = cmd .DETAILED_HELP ,
114+ formatter_class = formatter ,
115+ )
116+ cmd .add_arguments (cmd_parser )
117+
118+ return main_parser
0 commit comments