ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
cli.cpp
1namespace alib::app {
2
3//##################################################################################################
4// CommandLine Constructor
5//##################################################################################################
6
7void CommandLine::Init( resources::ResourcePool* resourcePool, NCString resCategory ) {
8 ALIB_ASSERT_ERROR(Resources==nullptr, "CLI", "CommandLine::Init already called.")
9 Resources = resourcePool;
10 ResourceCategory= resCategory;
11
12 ArgStrings.reserve( size_t(ARG_C) );
13 ArgsLeft .reserve( size_t(ARG_C) );
14
15 #if !ALIB_CHARACTERS_WIDE
16 if( ARG_VN ) {
17 for ( int i= 1; i < ARG_C ; ++i ) {
18 ArgStrings.emplace_back( ARG_VN[i] );
19 ArgsLeft .emplace_back( i -1 );
20 }
21 } else {
22 // convert wide to narrow strings
23 NString1K converter;
25
26 for ( int i= 1; i < ARG_C ; ++i ) {
27 converter.Reset() << ARG_VW[i];
28 ArgStrings.emplace_back( String( allocator, converter) );
29 ArgsLeft .emplace_back( i - 1 );
30 } }
31 #else
32 #if ALIB_CHARACTERS_NATIVE_WCHAR // use original strings only if alib::wchar == wchar_t
33 if( ARG_VW ) {
34 for ( int i= 1; i < ARG_C ; ++i ) {
35 ArgStrings.emplace_back( ARG_VW[i] );
36 ArgsLeft .emplace_back( i - 1 );
37 } }
38 else
39 #endif
40 {
41 // convert narrow to wide strings (or "wrong" wide width to width)
42 String1K converter;
44
45 for ( int i= 1; i < ARG_C ; ++i ) {
46 converter.Reset() << ARG_VN[i];
47 ArgStrings.emplace_back( String(allocator, converter) );
48 ArgsLeft .emplace_back( i -1 );
49 } }
50 #endif
51}
52
53//##################################################################################################
54// Interface
55//##################################################################################################
56
58 // loop over all arg indices in ArgsLeft
59 integer argIdx= 0;
60 while( argIdx < integer(ArgsLeft.size()) ) {
61 // get arg number and string once
62 auto argNo= ArgsLeft[size_t(argIdx)];
63 String arg = GetArg(argNo);
64
65 SHORTCUT_JUMP:
66
67 // ignore non-option args
68 if( arg.CharAtStart() != '-' ) {
69 ++argIdx;
70 continue;
71 }
72
73 // create an option object and search decl with the actual argument
74 {
75 Option* option= allocator().New<Option>(this);
76
77 auto optionDeclIt= OptionDecls.begin();
78 try
79 {
80 while( optionDeclIt != OptionDecls.end() ) {
81 if( option->Read( **optionDeclIt, arg, argNo ) )
82 break;
83 ++optionDeclIt;
84 } }
85 catch ( Exception& e )
86 {
88 (*optionDeclIt)->HelpUsageLine() );
89 throw;
90 }
91
92 // found a declaration?
93 if( option->ConsumedArguments > 0 ) {
94 // shortcut to another option?
95 OptionDecl& decl= *option->Declaration;
97 arg= decl.ShortcutReplacementString();
98 goto SHORTCUT_JUMP;
99 }
100
101 // delete args and continue
102 ArgsLeft.erase( ArgsLeft.begin() + argIdx,
103 ArgsLeft.begin() + argIdx + option->ConsumedArguments );
104
105 // move local option into the monotonic memory add to the list for this option type.
106 Options.push_back( option );
107 continue;
108 }
109
110
111 // erase args that start with '-' and put them into field OptionsIgnored.
112 if( ArgsLeft.size() > 0 ) {
113 OptionArgsIgnored.push_back( GetArg(argNo) );
114 ArgsLeft.erase( ArgsLeft.begin() + argIdx );
115} } } }
116
118 for( auto optionIt= Options.rbegin() ; optionIt != Options.rend() ; optionIt ++ )
119 if( (*optionIt)->Declaration->Element() == element )
120 return *optionIt;
121 return nullptr;
122}
123
124
126 // loop over all arg indices in ArgsLeft
127 bool lastCommandFullyParsed= true;
128 while( lastCommandFullyParsed && ArgsLeft.size() > 0 ) {
129 // create a command object and search decl with actual argument
130 Command* command= allocator().New<Command>(this);
131 ALIB_ASSERT_ERROR( CommandDecls.size() > 0, "CLI", "No commands declared." )
132 for( auto* commandDecl : CommandDecls ) {
133 try
134 {
135 lastCommandFullyParsed= command->Read( *commandDecl );
136 }
137 catch ( Exception& e )
138 {
140 CLIUtil::GetCommandUsageFormat( *this, *commandDecl ),
141 commandDecl->HelpTextShort() );
142 throw;
143 }
144
145 if( command->ConsumedArguments > 0 ) {
146 CommandsParsed.push_back( command );
147 if( NextCommandIt == CommandsParsed.end() )
149 break;
150} } } }
151
153 if( NextCommandIt == CommandsParsed.end() )
155 if( NextCommandIt == CommandsParsed.end() )
156 return nullptr;
157
158 auto* result= *NextCommandIt;
160 return result;
161}
162
163
165 if( ArgsLeft.size() == 0)
166 return NULL_STRING;
167
168 String result= GetArg(ArgsLeft[0]);
169 ArgsLeft.erase( ArgsLeft.begin() );
170 return result;
171}
172
174 for( auto it= ArgsLeft.begin() ; it != ArgsLeft.end() ; ++it )
175 if( *it == argNo ) {
176 ArgsLeft.erase( it );
177 return true;
178 }
179 return false;
180}
181} // namespace alib::app
182
#define ALIB_CALLER_NULLED
#define ALIB_ASSERT_ERROR(cond, domain,...)
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
static AString GetCommandUsageFormat(CommandLine &cmdLine, CommandDecl &commandDecl)
Definition cliutil.cpp:32
ListMA< Command * > CommandsParsed
A list of commands actually parsed. Filled with method #"ReadNextCommands".
Definition cli.hpp:107
ListMA< Command * >::iterator NextCommandIt
The next command in #"CommandsParsed" to be processed. Used with method #"NextCommand".
Definition cli.hpp:110
virtual String PopArg()
Definition cli.cpp:164
NCString ResourceCategory
The resource category to fetch CLI resources within field #"Resources".
Definition cli.hpp:128
MonoAllocator allocator
Definition cli.hpp:52
ListMA< CommandDecl * > CommandDecls
Commands defined.
Definition cli.hpp:84
Option * GetOption(Enum element)
Definition cli.cpp:117
ListMA< OptionDecl * > OptionDecls
Possible Options.
Definition cli.hpp:87
resources::ResourcePool * Resources
Definition cli.hpp:125
void Init(camp::Camp *resModule)
Definition cli.hpp:193
virtual void ReadOptions()
Definition cli.cpp:57
virtual String GetArg(integer idx)
Definition cli.hpp:455
ListMA< String, Recycling::Shared > OptionArgsIgnored
Definition cli.hpp:104
bool RemoveArg(integer argNo)
Definition cli.cpp:173
virtual Command * NextCommand()
Definition cli.cpp:152
virtual void ReadNextCommands()
Definition cli.cpp:125
StdVectorMA< integer > ArgsLeft
Definition cli.hpp:80
StdVectorMA< String > ArgStrings
Definition cli.hpp:75
ListMA< Option * > Options
The options parsed in the order of their appearance.
Definition cli.hpp:98
const String & ShortcutReplacementString()
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
void DbgDisableBufferReplacementWarning()
Definition tastring.hpp:236
TChar CharAtStart() const
Definition string.hpp:417
constexpr bool IsNotEmpty() const
Definition string.hpp:353
@ ParsingOptions
General option parse error. Adds option help text.
@ ParsingCommand
General parameter parse error. Adds command help text.
constexpr String NULL_STRING
A nulled string of the default character type.
Definition string.hpp:2247
strings::TCString< nchar > NCString
Type alias in namespace #"%alib".
Definition cstring.hpp:408
NLocalString< 1024 > NString1K
Type alias name for #"TLocalString;TLocalString<nchar,1024>".
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
const wchar_t ** ARG_VW
Definition mainargs.cpp:4
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
LocalString< 1024 > String1K
Type alias name for #"TLocalString;TLocalString<character,1024>".
exceptions::Exception Exception
Type alias in namespace #"%alib".
int ARG_C
Definition mainargs.cpp:2
const char ** ARG_VN
Definition mainargs.cpp:3
boxing::Enum Enum
Type alias in namespace #"%alib".
Definition enum.hpp:210
A command argument of the command-line.
bool Read(CommandDecl &decl)
bool Read(OptionDecl &decl, String &arg, const integer argNo)
OptionDecl * Declaration
The declaration struct.
integer ConsumedArguments