22#include < iostream>
33#include " Util/format.h"
44
5- void CommandLine::AddTarget (const std::string& name)
5+ CommandLineTargetOptions::CommandLineTargetOptions ()
6+ : _enableRestArgs(false )
67{
7- _targets.insert (name);
88}
99
10- std::string CommandLine::GetTarget () const noexcept
10+ CommandLineTargetOptions& CommandLineTargetOptions::EnableKeyValueArgs ()
11+ {
12+ _enableRestArgs = true ;
13+ return *this ;
14+ }
15+
16+ bool CommandLineTargetOptions::HasOption (std::string_view name)
17+ {
18+ auto it = _args.find (name);
19+ if (it == _args.end ())
20+ {
21+ return false ;
22+ }
23+
24+ return it->second .HasOption ;
25+ }
26+
27+ CommandLine::CommandLine ()
28+ : _options(nullptr )
29+ {
30+ }
31+
32+ bool CommandLine::HasOption (std::string_view name)
33+ {
34+ if (!_options)
35+ {
36+ return false ;
37+ }
38+
39+ return _options->HasOption (name);
40+ }
41+
42+ CommandLineTargetOptions& CommandLine::AddTarget (std::string_view name)
43+ {
44+ auto it = _targets.insert ({std::string (name), CommandLineTargetOptions ()});
45+ return it.first ->second ;
46+ }
47+
48+ std::string_view CommandLine::GetTarget () const noexcept
1149{
1250 return _currentTarget;
1351}
1452
15- std::string CommandLine::GetArg (int index) const noexcept
53+ std::string_view CommandLine::GetArg (int index) const noexcept
1654{
1755 if (static_cast <std::size_t >(index) < _argvs.size ())
1856 {
@@ -24,6 +62,11 @@ std::string CommandLine::GetArg(int index) const noexcept
2462 }
2563}
2664
65+ std::map<std::string, std::string, std::less<>>& CommandLine::GetKeyValueOptions ()
66+ {
67+ return _options->_restArgs ;
68+ }
69+
2770bool CommandLine::Parse (int argc, char ** argv)
2871{
2972 if (argc < 2 )
@@ -37,6 +80,8 @@ bool CommandLine::Parse(int argc, char** argv)
3780 return false ;
3881 }
3982
83+ _options = &_targets[_currentTarget];
84+
4085 _argvs.reserve (argc);
4186 for (int i = 0 ; i != argc; i++)
4287 {
@@ -47,22 +92,35 @@ bool CommandLine::Parse(int argc, char** argv)
4792 // index = 1 的参数时target
4893 for (int index = 2 ; index < argc; index++)
4994 {
50- std::string& current = _argvs[index];
95+ std::string_view current = _argvs[index];
5196 if (current.empty ())
5297 {
5398 continue ;
5499 }
55100
56- std::string option;
101+ std::string_view option;
57102
58- // 其实应该用start_with
59103 if (current.starts_with (" --" ))
60104 {
61105 option = current.substr (2 );
62106 if (option == " help" )
63107 {
64108 return false ;
65109 }
110+
111+ auto eqPos = option.find_first_of (' =' );
112+ if (eqPos != std::string_view::npos)
113+ {
114+ if (!_options->_enableRestArgs )
115+ {
116+ _errors.emplace_back (format (" Unknown option {} ,please enable key=value options" , current));
117+ return false ;
118+ }
119+ std::string_view value = option.substr (eqPos + 1 );
120+ option = option.substr (0 , eqPos);
121+ _options->_restArgs .insert ({std::string (option), std::string (value)});
122+ continue ;
123+ }
66124 }
67125 else if (current.starts_with (" -" ))
68126 {
@@ -73,13 +131,12 @@ bool CommandLine::Parse(int argc, char** argv)
73131 return false ;
74132 }
75133
76- if (! _shortMap.count (shortOption))
134+ if (_options-> _shortMap .count (shortOption) == 0 )
77135 {
78136 _errors.emplace_back (format (" Unknown Option {}" , current));
79137 return false ;
80138 }
81-
82- option = _shortMap[shortOption];
139+ option = _options->_shortMap .find (shortOption)->second ;
83140 }
84141 else
85142 {
@@ -88,7 +145,21 @@ bool CommandLine::Parse(int argc, char** argv)
88145
89146 if (index < argc - 1 )
90147 {
91- _args[option].Value = _argvs[++index];
148+ auto & commandOption = _options->_args .find (option)->second ;
149+ if (_argvs[index + 1 ].starts_with (" -" ))
150+ {
151+ if (commandOption.Type == CommandLineValueType::Boolean)
152+ {
153+ commandOption.Value = " true" ;
154+ commandOption.HasOption = true ;
155+ continue ;
156+ }
157+ _errors.emplace_back (format (" Option {} has not value" , current));
158+ return false ;
159+ }
160+
161+ commandOption.Value = _argvs[++index];
162+ commandOption.HasOption = true ;
92163 }
93164 }
94165 return true ;
@@ -105,18 +176,17 @@ void CommandLine::PrintUsage()
105176 std::cerr << " first param must be target:" << std::endl;
106177 for (auto & target : _targets)
107178 {
108- std::cerr << format (" {}" , target) << std::endl;
109- }
110-
111- std::cerr << std::endl;
112-
113- for (auto & it : _shortMap)
114- {
115- auto & shortName = it.first ;
116- auto & name = it.second ;
117- auto & option = _args[name];
179+ std::cerr << format (" {}:" , target.first ) << std::endl;
180+ auto & options = target.second ;
181+ for (auto & it : options._shortMap )
182+ {
183+ auto & shortName = it.first ;
184+ auto & name = it.second ;
185+ auto & option = options._args [name];
118186
119- std::cerr << format (" -{} --{} {}" ,
120- shortName, name, option.Description ) << std::endl;
187+ std::cerr << format (" -{} --{} {}" ,
188+ shortName, name, option.Description ) << std::endl;
189+ std::cerr << std::endl;
190+ }
121191 }
122192}
0 commit comments