26static File resolveFilename (
const String& name)
31static File checkFileExists (
const File& f)
39static File checkFolderExists (
const File& f)
41 if (! f.isDirectory())
47static 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);
65 return checkFileExists (resolveAsFile());
70 auto f = resolveAsFile();
72 if (! f.isDirectory())
78static bool isShortOptionFormat (
StringRef s) {
return s[0] ==
'-' && s[1] !=
'-'; }
79static bool isLongOptionFormat (
StringRef s) {
return s[0] ==
'-' && s[1] ==
'-' && s[2] !=
'-'; }
80static bool isOptionFormat (StringRef s) {
return s[0] ==
'-'; }
88 if (! isLongOptionFormat (option))
90 jassert (! isShortOptionFormat (option));
94 return text.upToFirstOccurrenceOf (
"=",
false,
false) == option;
104 return text.substring (equalsIndex + 1);
112 jassert (option !=
'-');
114 return isShortOption() && text.containsChar (
String (option)[0]);
124 if (isShortOptionFormat (o) && o.length() == 2 && isShortOption ((
char) o[1]))
127 if (isLongOptionFormat (o) && isLongOption (o))
162 if (
size() < expectedMinNumberOfArgs)
168 jassert (option ==
String (option).trim());
170 for (
int i = 0; i <
arguments.size(); ++i)
171 if (
arguments.getReference (i) == option)
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();
290struct 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];
338 if (
auto c =
findCommand (args, optionMustBeFirstArg))
341 fail (
"Unrecognised arguments");
354 commands.emplace_back (std::move (c));
359 commandIfNoOthersRecognised = (int) commands.size();
365 Command c { arg, arg,
"Prints the list of commands", {},
368 std::cout << helpMessage << std::endl;
372 if (makeDefaultCommand)
380 addCommand ({ arg, arg,
"Prints the current version number", {},
383 std::cout << versionText << std::endl;
400static void printCommandDescription (
const ArgumentList& args,
const ConsoleApplication::Command& command,
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);
410 std::cout << command.shortDescription << std::endl;
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));
File getChildFile(StringRef relativeOrAbsolutePath) const
static File getCurrentWorkingDirectory()
void removeEmptyStrings(bool removeWhitespaceStrings=true)
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
int indexOfChar(juce_wchar characterToLookFor) const noexcept
int length() const noexcept
String fromLastOccurrenceOf(StringRef substringToFind, bool includeSubStringInResult, bool ignoreCase) const
bool isNotEmpty() const noexcept
bool operator!=(StringRef stringToCompare) const
File resolveAsExistingFile() const
bool isLongOption() const
bool isLongOption(const String &optionRoot) const
File resolveAsExistingFolder() const
bool isShortOption() const
File resolveAsFile() const
bool operator==(StringRef stringToCompare) const
String getLongOptionValue() const
File getExistingFileForOptionAndRemove(StringRef option)
String removeValueForOption(StringRef option)
File getExistingFileForOption(StringRef option) const
bool removeOptionIfFound(StringRef option)
File getExistingFolderForOption(StringRef option) const
int indexOfOption(StringRef option) const
File getFileForOption(StringRef option) const
void failIfOptionIsMissing(StringRef option) const
Array< Argument > arguments
bool containsOption(StringRef option) const
void checkMinNumArguments(int expectedMinNumberOfArgs) const
String getValueForOption(StringRef option) const
Argument operator[](int index) const
ArgumentList(String executable, StringArray arguments)
File getFileForOptionAndRemove(StringRef option)
File getExistingFolderForOptionAndRemove(StringRef option)
void printCommandDetails(const ArgumentList &, const Command &) const
int findAndRunCommand(const ArgumentList &, bool optionMustBeFirstArg=false) const
void addDefaultCommand(Command)
String argumentDescription
void printCommandList(const ArgumentList &) const
const Command * findCommand(const ArgumentList &, bool optionMustBeFirstArg) const
static int invokeCatchingFailures(std::function< int()> &&functionToCall)
void addHelpCommand(String helpArgument, String helpMessage, bool makeDefaultCommand)
void addVersionCommand(String versionArgument, String versionText)
static void fail(String errorMessage, int returnCode=1)
const std::vector< Command > & getCommands() const