# # # patch "cmd_automate.cc" # from [a8202aed4b5200453cfd3a4fc14845ccef0c183d] # to [832a5b18b9f858b3523f21c048902c1f2625f0a6] # # patch "commands.cc" # from [09c0a2860ca0dcf1219b0df0e181c157ec6038af] # to [66871a867361d99c48ed1e5c51ef9aa9b7960101] # # patch "tests/automate_stdio/__driver__.lua" # from [62848c822df8dbc34347246a92f2d67c74da7ce7] # to [9c50b741496b9bcb989ffb813eec19ef5827dcd6] # ============================================================ --- cmd_automate.cc a8202aed4b5200453cfd3a4fc14845ccef0c183d +++ cmd_automate.cc 832a5b18b9f858b3523f21c048902c1f2625f0a6 @@ -358,8 +358,16 @@ CMD_AUTOMATE(stdio, "", set< command_id > matches = CMD_REF(automate)->complete_command(id); - N(matches.size() == 1, - F("invalid automation specified")); + + if (matches.size() == 0) + { + N(false, F("no completions for this command")); + } + else if (matches.size() > 1) + { + N(false, F("multiple completions possible for this command")); + } + id = *matches.begin(); I(args.size() >= id.size()); ============================================================ --- commands.cc 09c0a2860ca0dcf1219b0df0e181c157ec6038af +++ commands.cc 66871a867361d99c48ed1e5c51ef9aa9b7960101 @@ -328,11 +328,25 @@ namespace commands { { command_id caux = completed; caux.push_back(*iter2); + + // If one of the command names was an exact match, + // do not try to find other possible completions. + // This would eventually hinder us to ever call a command + // whose name is also the prefix for another command in the + // same group (f.e. mtn automate cert and mtn automate certs) if (prefix == *iter2) - matches[caux] = child; - else if (!child->hidden() && - prefix().length() < (*iter2)().length()) { + // since the command children are not sorted, we + // need to ensure that no other partial completed + // commands matched + matches.clear(); + matches[caux] = child; + return matches; + } + + if (!child->hidden() && + prefix().length() < (*iter2)().length()) + { string temp((*iter2)(), 0, prefix().length()); utf8 p(temp); if (prefix == p) @@ -911,7 +925,8 @@ CMD_GROUP(top, "top", "", CMD_REF(__root CMD_GROUP(top, "top", "", CMD_REF(__root__), "", ""); - +CMD(test, "test", "", CMD_REF(top), + "", "", "", options::opts::none) {} CMD(test1, "test1", "alias1", CMD_REF(top), "", "", "", options::opts::none) {} CMD(test2, "test2", "alias2", CMD_REF(top), @@ -1009,12 +1024,13 @@ UNIT_TEST(commands, command_complete_com UNIT_TEST_REQUIRE(matches.size() == 0); } - // Single-word identifier with one match. + // Single-word identifier with one match. Exact matches are found + // before any possible completions. { - command_id id = make_command_id("test1"); + command_id id = make_command_id("test"); set< command_id > matches = CMD_REF(top)->complete_command(id); UNIT_TEST_REQUIRE(matches.size() == 1); - UNIT_TEST_CHECK(*matches.begin() == make_command_id("test1")); + UNIT_TEST_CHECK(*matches.begin() == make_command_id("test")); } // Single-word identifier with one match, non-primary name. @@ -1025,13 +1041,14 @@ UNIT_TEST(commands, command_complete_com UNIT_TEST_CHECK(*matches.begin() == make_command_id("alias1")); } - // Single-word identifier with multiple matches. + // Single-word identifier with multiple matches. { - command_id id = make_command_id("test"); + command_id id = make_command_id("tes"); set< command_id > matches = CMD_REF(top)->complete_command(id); - UNIT_TEST_REQUIRE(matches.size() == 3); + UNIT_TEST_REQUIRE(matches.size() == 4); set< command_id > expected; + expected.insert(make_command_id("test")); expected.insert(make_command_id("test1")); expected.insert(make_command_id("test2")); expected.insert(make_command_id("testg")); @@ -1076,11 +1093,12 @@ UNIT_TEST(commands, command_complete_com // Multi-word identifier with multiple matches at different levels. { - command_id id = make_command_id("test testg1"); + command_id id = make_command_id("tes testg1"); set< command_id > matches = CMD_REF(top)->complete_command(id); - UNIT_TEST_REQUIRE(matches.size() == 3); + UNIT_TEST_REQUIRE(matches.size() == 4); set< command_id > expected; + expected.insert(make_command_id("test")); expected.insert(make_command_id("test1")); expected.insert(make_command_id("test2")); expected.insert(make_command_id("testg testg1")); @@ -1121,7 +1139,7 @@ UNIT_TEST(commands, command_find_command // Single-word identifier that could be completed. { - command_id id = make_command_id("test"); + command_id id = make_command_id("tes"); command * cmd = CMD_REF(top)->find_command(id); UNIT_TEST_CHECK(cmd == NULL); } ============================================================ --- tests/automate_stdio/__driver__.lua 62848c822df8dbc34347246a92f2d67c74da7ce7 +++ tests/automate_stdio/__driver__.lua 9c50b741496b9bcb989ffb813eec19ef5827dcd6 @@ -16,15 +16,6 @@ check(mtn("automate", "stdio"), 0, false check(mtn("automate", "stdio"), 0, false, false, "o3:key0:el6:leavese") check(mtn("automate", "stdio"), 0, false, false, "o3:key0:e l6:leavese") --- check if stdio's command finding code doesn't get confused with --- equal named commands from other groups (f.e. mtn cert vs mtn automate cert) --- mtn automate cert here will fail -addfile("foo", "stuff"); -commit() -R = base_revision(); -check(mtn("automate", "stdio"), 0, true, false, "l4:cert40:" .. R .. "3:foo3:bare"); -check(readfile("stdout") == "0:0:l:0") - function parse_stdio(dat, which) local got = {} while true do