ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
commandline.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !DOXYGEN
11# include "alib/cli/cliutil.hpp"
13#endif // !DOXYGEN
14
15
16namespace alib::cli {
17
18// #################################################################################################
19// CommandLine Constructor
20// #################################################################################################
21
22void CommandLine::Init( ResourcePool* resourcePool, NCString resCategory )
23{
24 Resources = resourcePool;
25 ResourceCategory= resCategory;
26
27 ArgStrings.reserve( size_t(ARG_C) );
28 ArgsLeft .reserve( size_t(ARG_C) );
29
31
32 #if !ALIB_CHARACTERS_WIDE
33 if( ARG_VN )
34 {
35 for ( int i= 1; i < ARG_C ; ++i )
36 {
37 ArgStrings.emplace_back( ARG_VN[i] );
38 ArgsLeft .emplace_back( i -1 );
39 }
40 }
41 else
42 {
43 // convert wide to narrow strings
44 NString1K converter;
46
47 for ( int i= 1; i < ARG_C ; ++i )
48 {
49 converter.Reset() << ARG_VW[i];
50 ArgStrings.emplace_back( String( allocator, converter) );
51 ArgsLeft .emplace_back( i - 1 );
52 }
53 }
54 #else
55 #if ALIB_CHARACTERS_NATIVE_WCHAR // use original strings only if alib::wchar == wchar_t
56 if( ARG_VW )
57 {
58 for ( int i= 1; i < ARG_C ; ++i )
59 {
60 ArgStrings.emplace_back( ARG_VW[i] );
61 ArgsLeft .emplace_back( i - 1 );
62 }
63 }
64 else
65 #endif
66 {
67 // convert narrow to wide strings (or "wrong" wide width to width)
68 String1K converter;
70
71 for ( int i= 1; i < ARG_C ; ++i )
72 {
73 converter.Reset() << ARG_VN[i];
74 ArgStrings.emplace_back( String(allocator, converter) );
75 ArgsLeft .emplace_back( i -1 );
76 }
77 }
78 #endif
80}
81
82// #################################################################################################
83// Interface
84// #################################################################################################
85
87{
88 // loop over all arg indices in ArgsLeft
89 integer argIdx= 0;
90 while( argIdx < static_cast<integer>(ArgsLeft.size()) )
91 {
92 // get arg number and string once
93 auto argNo= ArgsLeft[size_t(argIdx)];
94 String arg = GetArg(argNo);
95
96 SHORTCUT_JUMP:
97
98 // ignore non-option args
99 if( arg.CharAtStart() != '-' )
100 {
101 ++argIdx;
102 continue;
103 }
104
105 // create an option object and search decl with the actual argument
106 {
107 Option* option= allocator().New<Option>(this);
108
109 auto optionDeclIt= OptionDecls.begin();
110 try
111 {
112 while( optionDeclIt != OptionDecls.end() )
113 {
114 if( option->Read( **optionDeclIt, arg, argNo ) )
115 break;
116 ++optionDeclIt;
117 }
118 }
119 catch ( Exception& e )
120 {
122 (*optionDeclIt)->HelpUsageLine() );
123 throw;
124 }
125
126 // found a declaration?
127 if( option->ConsumedArguments > 0 )
128 {
129 // shortcut to another option?
130 OptionDecl& decl= *option->Declaration;
132 {
133 arg= decl.ShortcutReplacementString();
134 goto SHORTCUT_JUMP;
135 }
136
137 // delete args and continue
138 ArgsLeft.erase( ArgsLeft.begin() + argIdx,
139 ArgsLeft.begin() + argIdx + option->ConsumedArguments );
140
141 // move local option into the monotonic memory add to the list for this option type.
142 Options.PushBack( option );
143 continue;
144 }
145
146
147 // erase args that start with '-' and put them into field OptionsIgnored.
148 if( ArgsLeft.size() > 0 )
149 {
150 OptionArgsIgnored.PushBack( GetArg(argNo) );
151 ArgsLeft.erase( ArgsLeft.begin() + argIdx );
152 }
153 }
154 }
155}
156
158{
159 for( auto optionIt= Options.rbegin() ; optionIt != Options.rend() ; optionIt ++ )
160 if( (*optionIt)->Declaration->Element() == element )
161 return *optionIt;
162 return nullptr;
163}
164
165
167{
168 // loop over all arg indices in ArgsLeft
169 bool lastCommandFullyParsed= true;
170 while( lastCommandFullyParsed && ArgsLeft.size() > 0 )
171 {
172 // create a command object and search decl with actual argument
173 Command* command= allocator().New<Command>(this);
174 ALIB_ASSERT_ERROR( CommandDecls.Count() > 0, "CLI", "No commands declared." )
175 for( auto* commandDecl : CommandDecls )
176 {
177 try
178 {
179 lastCommandFullyParsed= command->Read( *commandDecl );
180 }
181 catch ( Exception& e )
182 {
184 CLIUtil::GetCommandUsageFormat( *this, *commandDecl ),
185 commandDecl->HelpTextShort() );
186 throw;
187 }
188
189 if( command->ConsumedArguments > 0 )
190 {
191 CommandsParsed.PushBack( command );
192 if( NextCommandIt == CommandsParsed.end() )
194 break;
195 }
196 }
197 }
198}
199
201{
202 if( NextCommandIt == CommandsParsed.end() )
204 if( NextCommandIt == CommandsParsed.end() )
205 {
206 // check for arguments left which got not recognized
207 if( ArgsLeft.size() > 0 )
209 ArgsLeft[0], PeekArg() );
210
211 // check for no command
212 if ( CommandsParsed.IsEmpty() )
214
215 return nullptr;
216 }
217
218 auto* result= *NextCommandIt;
220 return result;
221}
222
223
225{
226 if( ArgsLeft.size() == 0)
227 return NULL_STRING;
228
229 String result= GetArg(ArgsLeft[0]);
230 ArgsLeft.erase( ArgsLeft.begin() );
231 return result;
232}
233
235{
236 for( auto it= ArgsLeft.begin() ; it != ArgsLeft.end() ; ++it )
237 if( *it == argNo )
238 {
239 ArgsLeft.erase( it );
240 return;
241 }
242 ALIB_ERROR( "CLI", "Argument number {} already removed.", argNo )
243}
244
245
246
247} // namespace alib::cli
static ALIB_API AString GetCommandUsageFormat(CommandLine &cmdLine, CommandDecl &commandDecl)
Definition cliutil.cpp:52
List< MonoAllocator, CommandDecl * > CommandDecls
Commands defined.
lang::resources::ResourcePool * Resources
void Init(lang::Camp *resModule)
virtual ALIB_API Command * NextCommand()
virtual String GetArg(integer idx)
List< MonoAllocator, Command * > CommandsParsed
A list of commands actually parsed. Filled with method ReadNextCommands.
StdVectorMono< integer > ArgsLeft
MonoAllocator allocator
NCString ResourceCategory
The resource category to fetch CLI resources within field Resources.
List< MonoAllocator, Option * > Options
The options parsed in the order of their appearance.
List< MonoAllocator, String, Recycling::Shared > OptionArgsIgnored
virtual String PeekArg()
virtual ALIB_API void ReadOptions()
virtual ALIB_API String PopArg()
ALIB_API void RemoveArg(integer argNo)
List< MonoAllocator, Command * >::Iterator NextCommandIt
The next command in CommandsParsed to be processed. Used with method NextCommand.
ALIB_API Option * GetOption(Enum element)
StdVectorMono< String > ArgStrings
List< MonoAllocator, OptionDecl * > OptionDecls
Possible Options.
virtual ALIB_API void ReadNextCommands()
const String & ShortcutReplacementString()
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
void DbgDisableBufferReplacementWarning()
Definition tastring.inl:363
constexpr bool IsNotEmpty() const
Definition string.hpp:389
TChar CharAtStart() const
Definition string.hpp:466
#define ALIB_CALLER_NULLED
Definition alib.hpp:1173
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:849
#define ALIB_ERROR(...)
Definition alib.hpp:1267
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:760
@ ParsingOptions
General option parse error. Adds option help text.
@ ParsingCommand
General parameter parse error. Adds command help text.
@ NoCommandGiven
Unknown command given.
@ UnknownCommand
Unknown command given.
lang::Exception Exception
Type alias in namespace alib.
const char ** ARG_VN
Definition alib.cpp:72
int ARG_C
Definition alib.cpp:71
strings::TString< character > String
Type alias in namespace alib.
constexpr String NULL_STRING
A nulled string of the default character type.
Definition string.hpp:2549
const wchar_t ** ARG_VW
Definition alib.cpp:73
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
A command of a ALib CLI command line.
ALIB_API bool Read(CommandDecl &decl)
OptionDecl * Declaration
The declaration struct.
ALIB_API bool Read(OptionDecl &decl, String &arg, const integer argNo)
Definition arguments.cpp:59
integer ConsumedArguments
Definition arguments.hpp:43