Improve CLI tab completion feature

For example, if there are 3 commands: "gethelp", "get_account" and "get_account_name",
input "ge" then press TAB, the command will be completed to "get";
press TAB again, a list with all 3 commands will show;
input "get_ac" then press TAB, the command will be completed to "get_account";
press TAB again, a list with "get_account" and "get_account_name" will show.
This commit is contained in:
abitmore 2019-05-02 21:42:17 -04:00
parent 3655fe148b
commit a71893adba

View file

@ -137,36 +137,52 @@ void cli::run()
*/ */
static char *my_rl_complete(char *token, int *match) static char *my_rl_complete(char *token, int *match)
{ {
bool have_one = false; const auto& cmds = cli_commands();
std::string method_name;
auto& cmd = cli_commands();
const size_t partlen = strlen (token); /* Part of token */ const size_t partlen = strlen (token); /* Part of token */
for (const std::string& it : cmd) std::vector<std::reference_wrapper<const std::string>> matched_cmds;
for( const std::string& it : cmds )
{ {
if (it.compare(0, partlen, token) == 0) if( it.compare(0, partlen, token) == 0 )
{ {
if (have_one) { matched_cmds.push_back( it );
// we can only have 1, but we found a second
return NULL;
}
else
{
method_name = it;
have_one = true;
}
} }
} }
if (have_one) if( matched_cmds.size() == 0 )
return NULL;
const std::string& first_matched_cmd = matched_cmds[0];
if( matched_cmds.size() == 1 )
{ {
*match = 1; *match = 1;
method_name += " "; std::string matched_cmd = first_matched_cmd + " ";
return strdup (method_name.c_str() + partlen); return strdup( matched_cmd.c_str() + partlen );
} }
return NULL; size_t first_cmd_len = first_matched_cmd.size();
size_t matched_len = partlen;
for( ; matched_len < first_cmd_len; ++matched_len )
{
char next_char = first_matched_cmd[matched_len];
bool end = false;
for( const std::string& s : matched_cmds )
{
if( s.size() <= matched_len || s[matched_len] != next_char )
{
end = true;
break;
}
}
if( end )
break;
}
if( matched_len == partlen )
return NULL;
std::string matched_cmd_part = first_matched_cmd.substr( partlen, matched_len - partlen );
return strdup( matched_cmd_part.c_str() );
} }
/*** /***