307 lines
13 KiB
C++
307 lines
13 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library.
|
|
Copyright (c) 2017 - ROLI Ltd.
|
|
|
|
JUCE is an open source library subject to commercial or open-source
|
|
licensing.
|
|
|
|
The code included in this file is provided under the terms of the ISC license
|
|
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
|
|
To use, copy, modify, and/or distribute this software for any purpose with or
|
|
without fee is hereby granted provided that the above copyright notice and
|
|
this permission notice appear in all copies.
|
|
|
|
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
|
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
|
DISCLAIMED.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
namespace juce
|
|
{
|
|
|
|
//==============================================================================
|
|
/**
|
|
Holds a list of command-line arguments, and provides useful methods for searching
|
|
and operating on them.
|
|
|
|
You can create an ArgumentList manually, or give it some argv/argc values from a
|
|
main() function to parse.
|
|
|
|
@see ConsoleApplication
|
|
*/
|
|
struct ArgumentList
|
|
{
|
|
/** Creates an argument list for a given executable. */
|
|
ArgumentList (String executable, StringArray arguments);
|
|
|
|
/** Parses a standard argv/argc pair to create an argument list. */
|
|
ArgumentList (int argc, char* argv[]);
|
|
|
|
/** Tokenises a string containing all the arguments to create an argument list. */
|
|
ArgumentList (const String& executable, const String& arguments);
|
|
|
|
ArgumentList (const ArgumentList&) = default;
|
|
ArgumentList& operator= (const ArgumentList&) = default;
|
|
|
|
//==============================================================================
|
|
/**
|
|
One of the arguments in an ArgumentList.
|
|
*/
|
|
struct Argument
|
|
{
|
|
/** The original text of this argument. */
|
|
String text;
|
|
|
|
/** Resolves this argument as an absolute File, using the current working
|
|
directory as a base for resolving relative paths, and stripping quotes, etc.
|
|
*/
|
|
File resolveAsFile() const;
|
|
|
|
/** Resolves this argument as an absolute File, using the current working
|
|
directory as a base for resolving relative paths, and also doing a check to
|
|
make sure the file exists.
|
|
If the file doesn't exist, this will call fail() with a suitable error.
|
|
@see resolveAsFile, resolveAsExistingFolder
|
|
*/
|
|
File resolveAsExistingFile() const;
|
|
|
|
/** Resolves a user-supplied folder name into an absolute File, using the current working
|
|
directory as a base for resolving relative paths, and also doing a check to make
|
|
sure the folder exists.
|
|
If the folder doesn't exist, this will call fail() with a suitable error.
|
|
@see resolveAsFile, resolveAsExistingFile
|
|
*/
|
|
File resolveAsExistingFolder() const;
|
|
|
|
/** Returns true if this argument starts with a double dash. */
|
|
bool isLongOption() const;
|
|
|
|
/** Returns true if this argument starts with a single dash. */
|
|
bool isShortOption() const;
|
|
|
|
/** Returns true if this argument starts with a double dash, followed by the given string. */
|
|
bool isLongOption (const String& optionRoot) const;
|
|
|
|
/** If this argument is a long option with a value, this returns the value.
|
|
e.g. for "--foo=bar", this would return 'bar'.
|
|
*/
|
|
String getLongOptionValue() const;
|
|
|
|
/** Returns true if this argument starts with a single dash and then contains the given character somewhere inside it. */
|
|
bool isShortOption (char shortOptionCharacter) const;
|
|
|
|
/** Returns true if this argument starts with one or more dashes. */
|
|
bool isOption() const;
|
|
|
|
/** Compares this argument against a string.
|
|
The string may be a pipe-separated list of options, e.g. "--help|-h"
|
|
*/
|
|
bool operator== (StringRef stringToCompare) const;
|
|
|
|
/** Compares this argument against a string.
|
|
The string may be a pipe-separated list of options, e.g. "--help|-h"
|
|
*/
|
|
bool operator!= (StringRef stringToCompare) const;
|
|
};
|
|
|
|
//==============================================================================
|
|
/** Returns the number of arguments in the list. */
|
|
int size() const;
|
|
|
|
/** Returns one of the arguments */
|
|
Argument operator[] (int index) const;
|
|
|
|
/** Throws an error unless there are at least the given number of arguments. */
|
|
void checkMinNumArguments (int expectedMinNumberOfArgs) const;
|
|
|
|
/** Returns true if the given string matches one of the arguments.
|
|
The option can also be a list of different versions separated by pipes, e.g. "--help|-h"
|
|
*/
|
|
bool containsOption (StringRef option) const;
|
|
|
|
/** Returns the index of the given string if it matches one of the arguments, or -1 if it doesn't.
|
|
The option can also be a list of different versions separated by pipes, e.g. "--help|-h"
|
|
*/
|
|
int indexOfOption (StringRef option) const;
|
|
|
|
/** Throws an error unless the given option is found in the argument list. */
|
|
void failIfOptionIsMissing (StringRef option) const;
|
|
|
|
/** Looks for a given argument and returns either its assigned value (for long options) or the
|
|
string that follows it (for short options).
|
|
The option can also be a list of different versions separated by pipes, e.g. "--help|-h"
|
|
If it finds a long option, it will look for an assignment with a '=' sign, e.g. "--file=foo.txt",
|
|
and will return the string following the '='. If there's no '=', it will return an empty string.
|
|
If it finds a short option, it will attempt to return the argument that follows it, unless
|
|
it's another option.
|
|
If the argument isn't found, this returns an empty string.
|
|
*/
|
|
String getValueForOption (StringRef option) const;
|
|
|
|
/** Looks for the value of argument using getValueForOption() and tries to parse that value
|
|
as a file.
|
|
If the option isn't found, or if the value can't be parsed as a filename, it will throw
|
|
an error.
|
|
*/
|
|
File getFileForOption (StringRef option) const;
|
|
|
|
/** Looks for a file argument using getFileForOption() and fails with a suitable error if
|
|
the file doesn't exist.
|
|
*/
|
|
File getExistingFileForOption (StringRef option) const;
|
|
|
|
/** Looks for a filename argument using getFileForOption() and fails with a suitable error if
|
|
the file isn't a folder that exists.
|
|
*/
|
|
File getExistingFolderForOption (StringRef option) const;
|
|
|
|
/** The name or path of the executable that was invoked, as it was specified on the command-line. */
|
|
String executableName;
|
|
|
|
/** The list of arguments (not including the name of the executable that was invoked). */
|
|
Array<Argument> arguments;
|
|
};
|
|
|
|
|
|
//==============================================================================
|
|
/**
|
|
Represents a the set of commands that a console app can perform, and provides
|
|
helper functions for performing them.
|
|
|
|
When using these helper classes to implement a console app, you probably want to
|
|
do something along these lines:
|
|
|
|
@code
|
|
int main (int argc, char* argv[])
|
|
{
|
|
ConsoleApplication app;
|
|
|
|
app.addHelpCommand ("--help|-h", "Usage:", true);
|
|
app.addVersionCommand ("--version|-v", "MyApp version 1.2.3");
|
|
|
|
app.addCommand ({ "--foo",
|
|
"--foo filename",
|
|
"Performs a foo operation on the given file",
|
|
[] (const auto& args) { doFoo (args); }});
|
|
|
|
return app.findAndRunCommand (argc, argv);
|
|
}
|
|
@endcode
|
|
|
|
@see ArgumentList
|
|
*/
|
|
struct ConsoleApplication
|
|
{
|
|
//==============================================================================
|
|
/**
|
|
Represents a command that can be executed if its command-line arguments are matched.
|
|
@see ConsoleApplication::addCommand(), ConsoleApplication::findAndRunCommand()
|
|
*/
|
|
struct Command
|
|
{
|
|
/** The option string that must appear in the argument list for this command to be invoked.
|
|
This can also be a list of different versions separated by pipes, e.g. "--help|-h"
|
|
*/
|
|
String commandOption;
|
|
|
|
/** A description of the command-line arguments needed for this command, which will be
|
|
printed as part of the help text.
|
|
*/
|
|
String argumentDescription;
|
|
|
|
/** A short (one line) description of this command, which can be printed by
|
|
ConsoleApplication::printCommandList().
|
|
*/
|
|
String shortDescription;
|
|
|
|
/** A longer description of this command, for use in extended help. */
|
|
String longDescription;
|
|
|
|
/** The actual command that should be invoked to perform this action. */
|
|
std::function<void(const ArgumentList&)> command;
|
|
};
|
|
|
|
//==============================================================================
|
|
/** Adds a command to the list. */
|
|
void addCommand (Command);
|
|
|
|
/** Adds a command to the list, and marks it as one which is invoked if no other
|
|
command matches.
|
|
*/
|
|
void addDefaultCommand (Command);
|
|
|
|
/** Adds a command that will print the given text in response to the "--version" option. */
|
|
void addVersionCommand (String versionArgument, String versionText);
|
|
|
|
/** Adds a help command to the list.
|
|
This command will print the user-supplied message that's passed in here as an
|
|
argument, followed by a list of all the registered commands.
|
|
*/
|
|
void addHelpCommand (String helpArgument, String helpMessage, bool makeDefaultCommand);
|
|
|
|
/** Prints out the list of commands and their short descriptions in a format that's
|
|
suitable for use as help.
|
|
*/
|
|
void printCommandList (const ArgumentList&) const;
|
|
|
|
//==============================================================================
|
|
/** Throws a failure exception to cause a command-line app to terminate.
|
|
This is intended to be called from code in a Command, so that the
|
|
exception will be automatically caught and turned into a printed error message
|
|
and a return code which will be returned from main().
|
|
@see ConsoleApplication::invokeCatchingFailures()
|
|
*/
|
|
static void fail (String errorMessage, int returnCode = 1);
|
|
|
|
/** Invokes a function, catching any fail() calls that it might trigger, and handling
|
|
them by printing their error message and returning their error code.
|
|
@see ConsoleApplication::fail()
|
|
*/
|
|
static int invokeCatchingFailures (std::function<int()>&& functionToCall);
|
|
|
|
//==============================================================================
|
|
/** Looks for the first command in the list which matches the given arguments, and
|
|
tries to invoke it.
|
|
|
|
If no command is found, and if there is no default command to run, it fails with
|
|
a suitable error message.
|
|
If the command calls the fail() function, this will throw an exception that gets
|
|
automatically caught and handled, and this method will return the error code that
|
|
was passed into the fail() call.
|
|
|
|
If optionMustBeFirstArg is true, then only the first argument will be looked at
|
|
when searching the available commands - this lets you do 'git' style commands where
|
|
the executable name is followed by a verb.
|
|
*/
|
|
int findAndRunCommand (const ArgumentList&,
|
|
bool optionMustBeFirstArg = false) const;
|
|
|
|
/** Creates an ArgumentList object from the argc and argv variablrs, and invokes
|
|
findAndRunCommand() using it.
|
|
*/
|
|
int findAndRunCommand (int argc, char* argv[]) const;
|
|
|
|
/** Looks for the first command in the list which matches the given arguments.
|
|
If none is found, this returns either the default command (if one is set)
|
|
or nullptr.
|
|
If optionMustBeFirstArg is true, then only the first argument will be looked at
|
|
when searching the available commands - this lets you do 'git' style commands where
|
|
the executable name is followed by a verb.
|
|
*/
|
|
const Command* findCommand (const ArgumentList&, bool optionMustBeFirstArg) const;
|
|
|
|
/** Gives read-only access to the list of registered commands. */
|
|
const std::vector<Command>& getCommands() const;
|
|
|
|
private:
|
|
//==============================================================================
|
|
std::vector<Command> commands;
|
|
int commandIfNoOthersRecognised = -1;
|
|
};
|
|
|
|
} // namespace juce
|