# # # patch "commands.cc" # from [2ed5778eea2db2a9550c017b15273df0c1937b77] # to [e01629d98b749ee08ea2a1791e1797e9967144a8] # # patch "monotone.cc" # from [0412eca9b37f0e931c92ef71d128d760f4f98eb6] # to [e0a08b79c1ec487acaec9b77dd1b38df2d9bcc96] # ============================================================ --- commands.cc 2ed5778eea2db2a9550c017b15273df0c1937b77 +++ commands.cc e01629d98b749ee08ea2a1791e1797e9967144a8 @@ -427,6 +427,17 @@ namespace commands if (matches.empty()) { + command::children_set const & cs = CMD_REF(__root__)->children(); + for (command::children_set::const_iterator iter = cs.begin(); + iter != cs.end(); iter++) + { + set< command_id > m2 = (*iter)->complete_command(id); + matches.insert(m2.begin(), m2.end()); + } + } + + if (matches.empty()) + { N(false, F("could not match '%s' to any command") % join_words(id)()); } @@ -987,12 +998,42 @@ CMD_HIDDEN(testg3, "", CMD_REF(testg), " CMD(testg2, "", CMD_REF(testg), "", "", "", options::opts::none) {} CMD_HIDDEN(testg3, "", CMD_REF(testg), "", "", "", options::opts::none) {} +static args_vector +mkargs(const char *words) +{ + return split_into_words(arg_type(words)); +} + static commands::command_id mkid(const char *path) { return split_into_words(utf8(path)); } +UNIT_TEST(commands, complete_command) +{ + using commands::command_id; + using commands::complete_command; + + // Single-word identifier. + { + command_id id = complete_command(mkargs("testg")); + BOOST_CHECK(id == mkid("testg")); + } + + // Multi-word identifier. + { + command_id id = complete_command(mkargs("testg testg1")); + BOOST_CHECK(id == mkid("testg testg1")); + } + + // Single-word identifier, one level deep. + { + command_id id = complete_command(mkargs("testg1")); + BOOST_CHECK(id == mkid("testg testg1")); + } +} + UNIT_TEST(commands, command_complete_command) { using commands::command_id; ============================================================ --- monotone.cc 0412eca9b37f0e931c92ef71d128d760f4f98eb6 +++ monotone.cc e0a08b79c1ec487acaec9b77dd1b38df2d9bcc96 @@ -152,9 +152,22 @@ commands::command_id read_options(option if (!opts.args.empty()) { - I(opts.args.size() >= cmd.size()); - for (args_vector::size_type i = 0; i < cmd.size(); i++) - opts.args.erase(opts.args.begin()); + // Remove the command name from the arguments. It is important to + // note that the first component of the identifier is always optional, + // so we must take care about that here. + I(opts.args[0]() != cmd[0]() || opts.args.size() >= cmd.size()); + I(opts.args[0]() == cmd[0]() || opts.args.size() >= cmd.size() - 1); + + commands::command_id cmd2 = cmd; + + if (opts.args[0]() != cmd[0]()) + cmd2.erase(cmd2.begin()); + + for (args_vector::size_type i = 0; i < cmd2.size(); i++) + { + I(cmd2[i]().find(opts.args[i]()) == 0); + opts.args.erase(opts.args.begin()); + } } return cmd;