Hide the logic for command resolution for commands, aliases & user commands behind a single
interface so everybody does it the same way. Add an "exact" lookup for internal uses. Fix up a few little cases where we weren't reporting command lookup errors correctly. Added "b" as an alias for "breakpoint" so it doesn't collide with "bt". llvm-svn: 107718
This commit is contained in:
parent
13f0260e76
commit
279a6c2669
|
@ -51,10 +51,13 @@ public:
|
|||
~CommandInterpreter ();
|
||||
|
||||
lldb::CommandObjectSP
|
||||
GetCommandSP (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL);
|
||||
GetCommandSPExact (const char *cmd, bool include_aliases);
|
||||
|
||||
CommandObject *
|
||||
GetCommandObject (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL);
|
||||
GetCommandObjectExact (const char *cmd_cstr, bool include_aliases);
|
||||
|
||||
CommandObject *
|
||||
GetCommandObject (const char *cmd, StringList *matches = NULL);
|
||||
|
||||
StateVariable *
|
||||
GetStateVariable(const char *name);
|
||||
|
@ -243,6 +246,9 @@ protected:
|
|||
void
|
||||
SetSynchronous (bool value);
|
||||
|
||||
lldb::CommandObjectSP
|
||||
GetCommandSP (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL);
|
||||
|
||||
private:
|
||||
|
||||
Debugger &m_debugger; // The debugger session that this interpreter is associated with
|
||||
|
|
|
@ -65,6 +65,12 @@ public:
|
|||
|
||||
virtual bool
|
||||
IsCrossRefObject () { return false; }
|
||||
|
||||
bool
|
||||
IsAlias () { return m_is_alias; }
|
||||
|
||||
void
|
||||
SetIsAlias (bool value) { m_is_alias = value; }
|
||||
|
||||
virtual bool
|
||||
IsMultiwordObject () { return false; }
|
||||
|
@ -252,6 +258,7 @@ protected:
|
|||
std::string m_cmd_help_short;
|
||||
std::string m_cmd_help_long;
|
||||
std::string m_cmd_syntax;
|
||||
bool m_is_alias;
|
||||
Flags m_flags;
|
||||
};
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ CommandObjectAlias::Execute
|
|||
}
|
||||
else
|
||||
{
|
||||
CommandObjectSP command_obj_sp(interpreter.GetCommandSP (actual_command.c_str()));
|
||||
CommandObjectSP command_obj_sp(interpreter.GetCommandSPExact (actual_command.c_str(), true));
|
||||
CommandObjectSP subcommand_obj_sp;
|
||||
bool use_subcommand = false;
|
||||
if (command_obj_sp.get())
|
||||
|
|
|
@ -54,12 +54,8 @@ CommandObjectHelp::Execute (CommandInterpreter &interpreter, Args& command, Comm
|
|||
else
|
||||
{
|
||||
// Get command object for the first command argument. Only search built-in command dictionary.
|
||||
cmd_obj = interpreter.GetCommandObject (command.GetArgumentAtIndex (0), false, false);
|
||||
if (cmd_obj == NULL)
|
||||
{
|
||||
// That failed, so now search in the aliases dictionary, too.
|
||||
cmd_obj = interpreter.GetCommandObject (command.GetArgumentAtIndex (0), true, false);
|
||||
}
|
||||
StringList matches;
|
||||
cmd_obj = interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches);
|
||||
|
||||
if (cmd_obj != NULL)
|
||||
{
|
||||
|
@ -123,6 +119,15 @@ CommandObjectHelp::Execute (CommandInterpreter &interpreter, Args& command, Comm
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (matches.GetSize() > 0)
|
||||
{
|
||||
Stream &output_strm = result.GetOutputStream();
|
||||
output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
|
||||
for (int i = 0; i < matches.GetSize(); i++)
|
||||
{
|
||||
output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat
|
||||
|
@ -156,7 +161,7 @@ CommandObjectHelp::HandleCompletion
|
|||
}
|
||||
else
|
||||
{
|
||||
CommandObject *cmd_obj = interpreter.GetCommandObject (input.GetArgumentAtIndex(0), true, false);
|
||||
CommandObject *cmd_obj = interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
|
||||
input.Shift();
|
||||
cursor_index--;
|
||||
return cmd_obj->HandleCompletion (interpreter, input, cursor_index, cursor_char_position, match_start_point,
|
||||
|
|
|
@ -91,6 +91,7 @@ CommandInterpreter::Initialize ()
|
|||
result.Clear(); HandleCommand ("alias continue process continue", false, result);
|
||||
result.Clear(); HandleCommand ("alias expr expression", false, result);
|
||||
result.Clear(); HandleCommand ("alias exit quit", false, result);
|
||||
result.Clear(); HandleCommand ("alias b breakpoint", false, result);
|
||||
result.Clear(); HandleCommand ("alias bt thread backtrace", false, result);
|
||||
result.Clear(); HandleCommand ("alias si thread step-inst", false, result);
|
||||
result.Clear(); HandleCommand ("alias step thread step-in", false, result);
|
||||
|
@ -296,13 +297,21 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
|
|||
|
||||
if (!exact && ret_val == NULL)
|
||||
{
|
||||
// We will only get into here if we didn't find any exact matches.
|
||||
|
||||
CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
|
||||
|
||||
StringList local_matches;
|
||||
if (matches == NULL)
|
||||
matches = &local_matches;
|
||||
|
||||
int num_cmd_matches = 0;
|
||||
int num_alias_matches = 0;
|
||||
int num_user_matches = 0;
|
||||
unsigned int num_cmd_matches = 0;
|
||||
unsigned int num_alias_matches = 0;
|
||||
unsigned int num_user_matches = 0;
|
||||
|
||||
// Look through the command dictionaries one by one, and if we get only one match from any of
|
||||
// them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
|
||||
|
||||
if (HasCommands())
|
||||
{
|
||||
num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
|
||||
|
@ -313,7 +322,7 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
|
|||
cmd.assign(matches->GetStringAtIndex(0));
|
||||
pos = m_command_dict.find(cmd);
|
||||
if (pos != m_command_dict.end())
|
||||
ret_val = pos->second;
|
||||
real_match_sp = pos->second;
|
||||
}
|
||||
|
||||
if (include_aliases && HasAliases())
|
||||
|
@ -322,17 +331,12 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
|
|||
|
||||
}
|
||||
|
||||
if (num_alias_matches == 1 && num_cmd_matches == 0)
|
||||
if (num_alias_matches == 1)
|
||||
{
|
||||
cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
|
||||
pos = m_alias_dict.find(cmd);
|
||||
if (pos != m_alias_dict.end())
|
||||
{
|
||||
matches->Clear();
|
||||
matches->AppendString (cmd.c_str());
|
||||
|
||||
ret_val = pos->second;
|
||||
}
|
||||
alias_match_sp = pos->second;
|
||||
}
|
||||
|
||||
if (HasUserCommands())
|
||||
|
@ -340,33 +344,68 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
|
|||
num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
|
||||
}
|
||||
|
||||
if (num_user_matches == 1 && num_alias_matches == 0 && num_cmd_matches == 0)
|
||||
if (num_user_matches == 1)
|
||||
{
|
||||
cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
|
||||
|
||||
pos = m_user_dict.find (cmd);
|
||||
if (pos != m_user_dict.end())
|
||||
{
|
||||
matches->Clear();
|
||||
matches->AppendString (cmd.c_str());
|
||||
|
||||
ret_val = pos->second;
|
||||
}
|
||||
user_match_sp = pos->second;
|
||||
}
|
||||
|
||||
// If we got exactly one match, return that, otherwise return the match list.
|
||||
|
||||
if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
|
||||
{
|
||||
if (num_cmd_matches)
|
||||
return real_match_sp;
|
||||
else if (num_alias_matches)
|
||||
return alias_match_sp;
|
||||
else
|
||||
return user_match_sp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (matches)
|
||||
matches->AppendString (cmd_cstr);
|
||||
else if (matches && ret_val != NULL)
|
||||
{
|
||||
matches->AppendString (cmd_cstr);
|
||||
}
|
||||
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
CommandObject *
|
||||
CommandInterpreter::GetCommandObject (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
|
||||
CommandObjectSP
|
||||
CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
|
||||
{
|
||||
return GetCommandSP (cmd_cstr, include_aliases, exact, matches).get();
|
||||
return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
|
||||
}
|
||||
|
||||
CommandObject *
|
||||
CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
|
||||
{
|
||||
return GetCommandSPExact (cmd_cstr, include_aliases).get();
|
||||
}
|
||||
|
||||
CommandObject *
|
||||
CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
|
||||
{
|
||||
CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
|
||||
|
||||
// If we didn't find an exact match to the command string in the commands, look in
|
||||
// the aliases.
|
||||
|
||||
if (command_obj == NULL)
|
||||
{
|
||||
command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
|
||||
}
|
||||
|
||||
// Finally, if there wasn't an exact match among the aliases, look for an inexact match
|
||||
// in both the commands and the aliases.
|
||||
|
||||
if (command_obj == NULL)
|
||||
command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
|
||||
|
||||
return command_obj;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -390,6 +429,7 @@ CommandInterpreter::UserCommandExists (const char *cmd)
|
|||
void
|
||||
CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
|
||||
{
|
||||
command_obj_sp->SetIsAlias (true);
|
||||
m_alias_dict[alias_name] = command_obj_sp;
|
||||
}
|
||||
|
||||
|
@ -602,30 +642,17 @@ CommandInterpreter::HandleCommand
|
|||
|
||||
// We're looking up the command object here. So first find an exact match to the
|
||||
// command in the commands.
|
||||
|
||||
CommandObject *command_obj = GetCommandObject (command_cstr, false, true);
|
||||
|
||||
// If we didn't find an exact match to the command string in the commands, look in
|
||||
// the aliases.
|
||||
|
||||
if (command_obj == NULL)
|
||||
CommandObject *command_obj = GetCommandObject(command_cstr);
|
||||
|
||||
if (command_obj != NULL)
|
||||
{
|
||||
command_obj = GetCommandObject (command_cstr, true, true);
|
||||
if (command_obj != NULL)
|
||||
if (command_obj->IsAlias())
|
||||
{
|
||||
BuildAliasCommandArgs (command_obj, command_cstr, command_args, result);
|
||||
if (!result.Succeeded())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, if there wasn't an exact match among the aliases, look for an inexact match.
|
||||
|
||||
if (command_obj == NULL)
|
||||
command_obj = GetCommandObject(command_cstr, false, false);
|
||||
|
||||
if (command_obj)
|
||||
{
|
||||
if (command_obj->WantsRawCommandString())
|
||||
{
|
||||
const char *stripped_command = ::strstr (command_line, command_cstr);
|
||||
|
@ -649,10 +676,11 @@ CommandInterpreter::HandleCommand
|
|||
}
|
||||
else
|
||||
{
|
||||
// We didn't find the first command object, so complete the first argument.
|
||||
StringList matches;
|
||||
int num_matches;
|
||||
int cursor_index = command_args.GetArgumentCount() - 1;
|
||||
int cursor_char_position = strlen (command_args.GetArgumentAtIndex(command_args.GetArgumentCount() - 1));
|
||||
int cursor_index = 0;
|
||||
int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
|
||||
bool word_complete;
|
||||
num_matches = HandleCompletionMatches (command_args,
|
||||
cursor_index,
|
||||
|
@ -698,7 +726,6 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
|
|||
StringList &matches)
|
||||
{
|
||||
int num_command_matches = 0;
|
||||
bool include_aliases = true;
|
||||
bool look_for_subcommand = false;
|
||||
|
||||
// For any of the command completions a unique match will be a complete word.
|
||||
|
@ -707,13 +734,13 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
|
|||
if (cursor_index == -1)
|
||||
{
|
||||
// We got nothing on the command line, so return the list of commands
|
||||
bool include_aliases = true;
|
||||
num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
|
||||
}
|
||||
else if (cursor_index == 0)
|
||||
{
|
||||
// The cursor is in the first argument, so just do a lookup in the dictionary.
|
||||
CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), include_aliases, false,
|
||||
&matches);
|
||||
CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
|
||||
num_command_matches = matches.GetSize();
|
||||
|
||||
if (num_command_matches == 1
|
||||
|
@ -735,7 +762,7 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
|
|||
// We are completing further on into a commands arguments, so find the command and tell it
|
||||
// to complete the command.
|
||||
// First see if there is a matching initial command:
|
||||
CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0), include_aliases, false);
|
||||
CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
|
||||
if (command_object == NULL)
|
||||
{
|
||||
return 0;
|
||||
|
@ -910,7 +937,7 @@ CommandInterpreter::SetPrompt (const char *new_prompt)
|
|||
void
|
||||
CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
|
||||
{
|
||||
CommandObjectSP cmd_obj_sp = GetCommandSP (dest_cmd);
|
||||
CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true);
|
||||
|
||||
if (cmd_obj_sp != NULL)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,7 @@ CommandObject::CommandObject (const char *name, const char *help, const char *sy
|
|||
m_cmd_help_short (),
|
||||
m_cmd_help_long (),
|
||||
m_cmd_syntax (),
|
||||
m_is_alias (false),
|
||||
m_flags (flags)
|
||||
{
|
||||
if (help && help[0])
|
||||
|
|
Loading…
Reference in New Issue