26 static inline File resolveFilename (
const String& name)
31 static inline File checkFileExists (
const File& f)
39 static inline File checkFolderExists (
const File& f)
41 if (! f.isDirectory())
47 static inline File resolveFilenameForOption (
const ArgumentList& args, StringRef option,
const String& filename)
49 if (filename.isEmpty())
51 args.failIfOptionIsMissing (option);
55 return resolveFilename (filename);
60 return resolveFilename (
text);
72 if (! f.isDirectory())
78 static inline bool isShortOptionFormat (
StringRef s) {
return s[0] ==
'-' && s[1] !=
'-'; }
79 static inline bool isLongOptionFormat (
StringRef s) {
return s[0] ==
'-' && s[1] ==
'-' && s[2] !=
'-'; }
80 static inline bool isOptionFormat (
StringRef s) {
return s[0] ==
'-'; }
88 if (! isLongOptionFormat (option))
90 jassert (! isShortOptionFormat (option));
112 jassert (option !=
'-');
124 if (isShortOptionFormat (o) && o.length() == 2 &&
isShortOption ((
char) o[1]))
162 if (
size() < expectedMinNumberOfArgs)
168 jassert (option ==
String (option).trim());
170 for (
int i = 0; i <
arguments.size(); ++i)
200 jassert (isOptionFormat (option));
202 for (
int i = 0; i <
arguments.size(); ++i)
208 if (arg.isShortOption())
211 return arguments.getReference (i + 1).text;
216 if (arg.isLongOption())
217 return arg.getLongOptionValue();
226 jassert (isOptionFormat (option));
228 for (
int i = 0; i <
arguments.size(); ++i)
234 if (arg.isShortOption())
238 auto result =
arguments.getReference (i + 1).text;
247 if (arg.isLongOption())
249 auto result = arg.getLongOptionValue();
290 struct ConsoleAppFailureCode
298 throw ConsoleAppFailureCode { std::move (errorMessage), returnCode };
309 catch (
const ConsoleAppFailureCode& error)
311 std::cerr << error.errorMessage << std::endl;
312 returnCode = error.returnCode;
320 for (
auto& c : commands)
324 if (optionMustBeFirstArg ? (index == 0) : (index >= 0))
328 if (commandIfNoOthersRecognised >= 0)
329 return &commands[(size_t) commandIfNoOthersRecognised];
336 return invokeCatchingFailures ([&args, optionMustBeFirstArg,
this]
338 if (
auto c = findCommand (args, optionMustBeFirstArg))
341 fail (
"Unrecognised arguments");
354 commands.emplace_back (std::move (c));
359 commandIfNoOthersRecognised = (int) commands.size();
360 addCommand (std::move (c));
365 Command c { arg, arg,
"Prints the list of commands", {},
368 std::cout << helpMessage << std::endl;
369 printCommandList (args);
372 if (makeDefaultCommand)
373 addDefaultCommand (std::move (c));
375 addCommand (std::move (c));
380 addCommand ({ arg, arg,
"Prints the current version number", {},
383 std::cout << versionText << std::endl;
401 int descriptionIndent)
403 auto nameAndArgs = getExeNameAndArgs (args, command);
405 if (nameAndArgs.length() > descriptionIndent)
406 std::cout << nameAndArgs << std::endl <<
String().
paddedRight (
' ', descriptionIndent);
408 std::cout << nameAndArgs.
paddedRight (
' ', descriptionIndent);
415 int descriptionIndent = 0;
417 for (
auto& c : commands)
418 descriptionIndent = std::max (descriptionIndent, getExeNameAndArgs (args, c).length());
420 descriptionIndent = std::min (descriptionIndent + 2, 40);
422 for (
auto& c : commands)
423 printCommandDescription (args, c, descriptionIndent);
425 std::cout << std::endl;
430 auto len = getExeNameAndArgs (args, command).
length();
432 printCommandDescription (args, command, std::min (len + 3, 40));
Array< Argument > arguments
String getLongOptionValue() const
ArgumentList(String executable, StringArray arguments)
bool isShortOption() const
int findAndRunCommand(const ArgumentList &, bool optionMustBeFirstArg=false) const
bool isNotEmpty() const noexcept
String getValueForOption(StringRef option) const
bool removeOptionIfFound(StringRef option)
String removeValueForOption(StringRef option)
int indexOfOption(StringRef option) const
void printCommandDetails(const ArgumentList &, const Command &) const
void removeEmptyStrings(bool removeWhitespaceStrings=true)
static void fail(String errorMessage, int returnCode=1)
File getFileForOption(StringRef option) const
bool containsChar(juce_wchar character) const noexcept
File getExistingFileForOptionAndRemove(StringRef option)
File getChildFile(StringRef relativeOrAbsolutePath) const
const Command * findCommand(const ArgumentList &, bool optionMustBeFirstArg) const
File getFileForOptionAndRemove(StringRef option)
String fromLastOccurrenceOf(StringRef substringToFind, bool includeSubStringInResult, bool ignoreCase) const
String paddedRight(juce_wchar padCharacter, int minimumLength) const
String substring(int startIndex, int endIndex) const
String argumentDescription
void addDefaultCommand(Command)
Argument operator[](int index) const
bool operator!=(StringRef stringToCompare) const
File resolveAsExistingFolder() const
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
const std::vector< Command > & getCommands() const
File resolveAsFile() const
File resolveAsExistingFile() const
File getExistingFileForOption(StringRef option) const
void checkMinNumArguments(int expectedMinNumberOfArgs) const
void addHelpCommand(String helpArgument, String helpMessage, bool makeDefaultCommand)
String upToFirstOccurrenceOf(StringRef substringToEndWith, bool includeSubStringInResult, bool ignoreCase) const
void printCommandList(const ArgumentList &) const
bool operator==(StringRef stringToCompare) const
bool isLongOption(const String &optionRoot) const
void failIfOptionIsMissing(StringRef option) const
File getExistingFolderForOptionAndRemove(StringRef option)
bool isLongOption() const
int indexOfChar(juce_wchar characterToLookFor) const noexcept
static File getCurrentWorkingDirectory()
static int invokeCatchingFailures(std::function< int()> &&functionToCall)
int length() const noexcept
File getExistingFolderForOption(StringRef option) const
bool containsOption(StringRef option) const
void addVersionCommand(String versionArgument, String versionText)