summaryrefslogtreecommitdiffstats
path: root/src/Configuration.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-04-04 09:27:49 +0000
committerDavid Robillard <d@drobilla.net>2015-04-04 09:27:49 +0000
commit9c5ad6b64f33ea07654435e93a8b6f726894581f (patch)
treecd83370c2a06707dff0b731c084741a737d5b972 /src/Configuration.cpp
parent52bce39f06f607dd363ca8f3b774fda658036cf4 (diff)
downloadingen-9c5ad6b64f33ea07654435e93a8b6f726894581f.tar.gz
ingen-9c5ad6b64f33ea07654435e93a8b6f726894581f.tar.bz2
ingen-9c5ad6b64f33ea07654435e93a8b6f726894581f.zip
Support GNU style long options.
Update usage output and man page to distinguish flags from options that take a value. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5660 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/Configuration.cpp')
-rw-r--r--src/Configuration.cpp110
1 files changed, 68 insertions, 42 deletions
diff --git a/src/Configuration.cpp b/src/Configuration.cpp
index 07beeea7..efcd2806 100644
--- a/src/Configuration.cpp
+++ b/src/Configuration.cpp
@@ -36,16 +36,15 @@ Configuration::Configuration(Forge& forge)
, _shortdesc("A realtime modular audio processor.")
, _desc(
"Ingen is a flexible modular system that be used in various ways.\n"
- "The engine can run as a stand-alone server controlled via network protocol,\n"
- "or internal to another process (e.g. the GUI). The GUI, or other clients,\n"
- "can communicate with the engine via any supported protocol, or run in the\n"
- "same process. Many clients can connect to an engine at once.\n\n"
+ "The engine can run as a server controlled via a network protocol,\n"
+ "as an LV2 plugin, or in a monolithic process with a GUI. The GUI\n"
+ "may be run separate to control a remote engine, and many clients\n"
+ "may connect to an engine at once.\n\n"
"Examples:\n"
- " ingen -e # Run an engine, listen for connections\n"
- " ingen -g # Run a GUI, connect to running engine\n"
- " ingen -eg # Run an engine and a GUI in one process\n"
- " ingen -egl foo.ttl # Run an engine and a GUI and load a graph\n"
- " ingen -egl foo.ingen # Run an engine and a GUI and load a graph")
+ " ingen -e # Run engine, listen for connections\n"
+ " ingen -g # Run GUI, connect to running engine\n"
+ " ingen -eg # Run engine and GUI in one process\n"
+ " ingen -eg foo.ingen # Run engine and GUI and load a graph")
, _max_name_length(0)
{
add("clientPort", "client-port", 'C', "Client port", SESSION, forge.Int, Atom());
@@ -88,22 +87,34 @@ Configuration::add(const std::string& key,
return *this;
}
+std::string
+Configuration::variable_string(LV2_URID type) const
+{
+ if (type == _forge.String) {
+ return "=STRING";
+ } else if (type == _forge.Int) {
+ return "=INT";
+ }
+ return "";
+}
+
void
Configuration::print_usage(const std::string& program, std::ostream& os)
{
- os << "Usage: " << program << " [OPTION]..." << std::endl;
+ os << "Usage: " << program << " [OPTION]... [GRAPH]" << std::endl;
os << _shortdesc << std::endl << std::endl;
os << _desc << std::endl << std::endl;
os << "Options:" << std::endl;
- for (auto o : _options) {
- Option& option = o.second;
+ for (const auto& o : _options) {
+ const Option& option = o.second;
os << " ";
if (option.letter != '\0')
os << "-" << option.letter << ", ";
else
os << " ";
- os.width(_max_name_length + 4);
- os << std::left << (std::string("--") + o.first);
+ os.width(_max_name_length + 11);
+ os << std::left;
+ os << (std::string("--") + o.first + variable_string(option.type));
os << option.desc << std::endl;
}
}
@@ -120,7 +131,7 @@ Configuration::set_value_from_string(Configuration::Option& option,
option.value = _forge.make(intval);
} else {
throw OptionError(
- (fmt("option `%1%' has non-integer value `%2%'")
+ (fmt("Option `%1%' has non-integer value `%2%'")
% option.name % value).str());
}
} else if (option.type == _forge.String) {
@@ -131,7 +142,7 @@ Configuration::set_value_from_string(Configuration::Option& option,
assert(option.value.type() == _forge.Bool);
} else {
throw OptionError(
- (fmt("bad option type `%1%'") % option.name).str());
+ (fmt("Bad option type `%1%'") % option.name).str());
}
return EXIT_SUCCESS;
}
@@ -142,45 +153,60 @@ Configuration::parse(int argc, char** argv) throw (Configuration::OptionError)
{
for (int i = 1; i < argc; ++i) {
if (argv[i][0] != '-' || !strcmp(argv[i], "-")) {
- _files.push_back(argv[i]);
+ // File argument
+ const Options::iterator o = _options.find("load");
+ if (!o->second.value.is_valid()) {
+ _options.find("load")->second.value = _forge.alloc(argv[i]);
+ } else {
+ throw OptionError("Multiple graphs specified");
+ }
} else if (argv[i][1] == '-') {
- const std::string name = std::string(argv[i]).substr(2);
- Options::iterator o = _options.find(name);
+ // Long option
+ std::string name = std::string(argv[i]).substr(2);
+ const char* equals = strchr(argv[i], '=');
+ if (equals) {
+ name = name.substr(0, name.find('='));
+ }
+
+ const Options::iterator o = _options.find(name);
if (o == _options.end()) {
throw OptionError(
- (fmt("unrecognized option `%1%'") % name).str());
- }
- if (o->second.type == _forge.Bool) {
+ (fmt("Unrecognized option `%1%'") % name).str());
+ } else if (o->second.type == _forge.Bool) { // --flag
o->second.value = _forge.make(true);
- } else {
- if (++i >= argc)
- throw OptionError(
- (fmt("missing value for `%1%'") % name).str());
+ } else if (equals) { // --opt=val
+ set_value_from_string(o->second, equals + 1);
+ } else if (++i < argc) { // --opt val
set_value_from_string(o->second, argv[i]);
+ } else {
+ throw OptionError(
+ (fmt("Missing value for `%1%'") % name).str());
}
} else {
+ // Short option
const size_t len = strlen(argv[i]);
for (size_t j = 1; j < len; ++j) {
- char letter = argv[i][j];
- ShortNames::iterator n = _short_names.find(letter);
- if (n == _short_names.end())
+ const char letter = argv[i][j];
+ const ShortNames::iterator n = _short_names.find(letter);
+ if (n == _short_names.end()) {
throw OptionError(
- (fmt("unrecognized option `%1%'") % letter).str());
- Options::iterator o = _options.find(n->second);
- if (j < len - 1) {
- if (o->second.type != _forge.Bool)
+ (fmt("Unrecognized option `%1%'") % letter).str());
+ }
+
+ const Options::iterator o = _options.find(n->second);
+ if (j < len - 1) { // Non-final POSIX style flag
+ if (o->second.type != _forge.Bool) {
throw OptionError(
- (fmt("missing value for `%1%'") % letter).str());
+ (fmt("Missing value for `%1%'") % letter).str());
+ }
+ o->second.value = _forge.make(true);
+ } else if (o->second.type == _forge.Bool) { // -f
o->second.value = _forge.make(true);
+ } else if (++i < argc) { // -v val
+ set_value_from_string(o->second, argv[i]);
} else {
- if (o->second.type == _forge.Bool) {
- o->second.value = _forge.make(true);
- } else {
- if (++i >= argc)
- throw OptionError(
- (fmt("missing value for `%1%'") % letter).str());
- set_value_from_string(o->second, argv[i]);
- }
+ throw OptionError(
+ (fmt("Missing value for `%1%'") % letter).str());
}
}
}