diff options
author | Dave Reisner <dreisner@archlinux.org> | 2013-03-01 13:57:55 -0500 |
---|---|---|
committer | Dave Reisner <dreisner@archlinux.org> | 2013-03-01 14:11:36 -0500 |
commit | 6903b4975e38e29008e21222a7323d3920b804e8 (patch) | |
tree | c4b6c4113006dd371ea2cddd7840559843ae973e /ponymix.cc | |
parent | dc8588eea147bbdde8bcc69f46c3f9004954a925 (diff) | |
download | mirror-ponymix-6903b4975e38e29008e21222a7323d3920b804e8.tar.gz mirror-ponymix-6903b4975e38e29008e21222a7323d3920b804e8.tar.bz2 mirror-ponymix-6903b4975e38e29008e21222a7323d3920b804e8.zip |
allow matching commands on prefixes
Allow for invocations such as "ponymix get-v" or "ponymix -d SB set-d".
Bail when the command is ambiguous and print the possible matches.
This necessarily means changing the return type of string_to_command to
return the whole pair<> out of the action map to allow for useful errors
when we do arg checking (as we don't necessarily have the full command
name from the user).
Diffstat (limited to 'ponymix.cc')
-rw-r--r-- | ponymix.cc | 38 |
1 files changed, 30 insertions, 8 deletions
@@ -418,7 +418,9 @@ static int Kill(PulseClient& ponymix, int, char*[]) { return !ponymix.Kill(*device); } -static const Command& string_to_command(const char* str) { + +static const std::pair<const string, const Command>& string_to_command( + const char* str) { static std::map<string, const Command> actionmap = { // command name function arg min arg max { "defaults", { ShowDefaults, { 0, 0 } } }, @@ -446,11 +448,29 @@ static const Command& string_to_command(const char* str) { { "kill", { Kill, { 0, 0 } } } }; - try { - return actionmap.at(str); - } catch(std::out_of_range) { - errx(1, "error: Invalid action specified: %s", str); + const auto match = actionmap.lower_bound(str); + for (auto iter = match; iter != actionmap.end(); iter++) { + // Match on prefix, ensure only a single match + if (iter->first.find(str) != 0) { + if (iter == match) { + errx(1, "error: Invalid action specified: %s", str); + } else { + break; + } + } + if (iter != match) { + auto i = match; + string cand = i->first; + i++; + while (i->first.find(str) == 0) { + cand += ", " + i->first; + i++; + } + errx(1, "error: Ambiguous action specified: %s (%s)", str, cand.c_str()); + } } + + return *match; } static void usage() { @@ -524,10 +544,12 @@ static int CommandDispatch(PulseClient& ponymix, int argc, char *argv[]) { return 0; } - const Command& cmd = string_to_command(opt_action); - if (cmd.args.InRange(argc) != 0) error_wrong_args(cmd, opt_action); + const auto& cmd = string_to_command(opt_action); + if (cmd.second.args.InRange(argc) != 0) { + error_wrong_args(cmd.second, cmd.first.c_str()); + } - return cmd.fn(ponymix, argc, argv); + return cmd.second.fn(ponymix, argc, argv); } bool parse_options(int argc, char** argv) { |