Lots of progress on the CommandAlias refactoring

This cleans things up such CommandAlias essentially can work as its own object; the aliases still live in a separate map, but are now just full-fledged CommandObjectSPs
This patch also cleans up help generation for aliases, allows aliases to vend their own help, and adds a tweak such that "dash-dash aliases", such as po, don't show the list of options for their underlying command, since those can't be provided anyway

I plan to fix up a few more things here, and then add a test case and proclaim victory

llvm-svn: 263499
This commit is contained in:
Enrico Granata 2016-03-14 22:17:04 +00:00
parent 2414c5d46b
commit bef55ac8f5
7 changed files with 305 additions and 142 deletions

View File

@ -51,9 +51,43 @@ public:
bool
WantsRawCommandString() override;
bool
WantsCompletion() override;
int
HandleCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
int match_start_point,
int max_return_elements,
bool &word_complete,
StringList &matches) override;
int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
OptionElementVector &opt_element_vector,
int match_start_point,
int max_return_elements,
bool &word_complete,
StringList &matches) override;
Options*
GetOptions() override;
bool
IsAlias () override { return true; }
bool
IsDashDashCommand () override;
const char*
GetHelp () override;
const char*
GetHelpLong () override;
bool
Execute(const char *args_string, CommandReturnObject &result) override;
@ -63,6 +97,7 @@ public:
private:
lldb::CommandObjectSP m_underlying_command_sp;
OptionArgVectorSP m_option_args_sp ;
LazyBool m_is_dashdash_alias;
};
} // namespace lldb_private

View File

@ -148,7 +148,7 @@ public:
virtual const char *
GetHelpLong ();
const char *
virtual const char *
GetSyntax ();
const char *
@ -181,6 +181,12 @@ public:
virtual bool
IsAlias () { return false; }
// override this to return true if your command is somehow a "dash-dash"
// form of some other command (e.g. po is expr -O --); this is a powerful
// hint to the help system that one cannot pass options to this command
virtual bool
IsDashDashCommand () { return false; }
virtual lldb::CommandObjectSP
GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr)
{

View File

@ -128,6 +128,8 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
{
sub_command = command.GetArgumentAtIndex(i);
matches.Clear();
if (sub_cmd_obj->IsAlias())
sub_cmd_obj = ((CommandAlias*)sub_cmd_obj)->GetUnderlyingCommand().get();
if (! sub_cmd_obj->IsMultiwordObject ())
{
all_okay = false;

View File

@ -85,11 +85,18 @@ CommandAlias::CommandAlias (CommandInterpreter &interpreter,
syntax,
flags),
m_underlying_command_sp(),
m_option_args_sp(new OptionArgVector)
m_option_args_sp(new OptionArgVector),
m_is_dashdash_alias(eLazyBoolCalculate)
{
if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp))
{
m_underlying_command_sp = cmd_sp;
for (int i = 0;
auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
i++)
{
m_arguments.push_back(*cmd_entry);
}
if (!help || !help[0])
{
StreamString sstr;
@ -110,6 +117,64 @@ CommandAlias::WantsRawCommandString()
return false;
}
bool
CommandAlias::WantsCompletion()
{
if (IsValid())
return m_underlying_command_sp->WantsCompletion();
return false;
}
int
CommandAlias::HandleCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
int match_start_point,
int max_return_elements,
bool &word_complete,
StringList &matches)
{
if (IsValid())
return m_underlying_command_sp->HandleCompletion(input,
cursor_index,
cursor_char_position,
match_start_point,
max_return_elements,
word_complete,
matches);
return -1;
}
int
CommandAlias::HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
OptionElementVector &opt_element_vector,
int match_start_point,
int max_return_elements,
bool &word_complete,
StringList &matches)
{
if (IsValid())
return m_underlying_command_sp->HandleArgumentCompletion(input,
cursor_index,
cursor_char_position,
opt_element_vector,
match_start_point,
max_return_elements,
word_complete,
matches);
return -1;
}
Options*
CommandAlias::GetOptions()
{
if (IsValid())
return m_underlying_command_sp->GetOptions();
return nullptr;
}
bool
CommandAlias::Execute(const char *args_string, CommandReturnObject &result)
{
@ -149,3 +214,47 @@ CommandAlias::GetAliasExpansion (StreamString &help_string)
help_string.Printf ("'");
}
bool
CommandAlias::IsDashDashCommand ()
{
if (m_is_dashdash_alias == eLazyBoolCalculate)
{
m_is_dashdash_alias = eLazyBoolNo;
if (IsValid())
{
for (const OptionArgPair& opt_arg : *GetOptionArguments())
{
if (opt_arg.first == "<argument>" &&
opt_arg.second.second == " --")
{
m_is_dashdash_alias = eLazyBoolYes;
break;
}
}
}
}
return (m_is_dashdash_alias == eLazyBoolYes);
}
// allow CommandAlias objects to provide their own help, but fallback to the info
// for the underlying command if no customization has been provided
const char*
CommandAlias::GetHelp ()
{
if (!m_cmd_help_short.empty())
return m_cmd_help_short.c_str();
if (IsValid())
return m_underlying_command_sp->GetHelp();
return nullptr;
}
const char*
CommandAlias::GetHelpLong ()
{
if (!m_cmd_help_long.empty())
return m_cmd_help_long.c_str();
if (IsValid())
return m_underlying_command_sp->GetHelpLong();
return nullptr;
}

View File

@ -772,7 +772,7 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
{
CommandAliasMap::iterator alias_pos = m_alias_dict.find(cmd);
if (alias_pos != m_alias_dict.end())
command_sp = ((CommandAlias*)alias_pos->second.get())->GetUnderlyingCommand();
command_sp = alias_pos->second;
}
if (HasUserCommands())
@ -823,7 +823,7 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
CommandAliasMap::iterator alias_pos = m_alias_dict.find(cmd);
if (alias_pos != m_alias_dict.end())
alias_match_sp = ((CommandAlias*)alias_pos->second.get())->GetUnderlyingCommand();
alias_match_sp = alias_pos->second;
}
if (HasUserCommands())
@ -1351,15 +1351,16 @@ CommandInterpreter::BuildAliasResult (const char *alias_name,
alias_cmd_obj = GetCommandObject (alias_name);
StreamString result_str;
if (alias_cmd_obj)
if (alias_cmd_obj && alias_cmd_obj->IsAlias())
{
OptionArgVectorSP option_arg_vector_sp = ((CommandAlias*)alias_cmd_obj)->GetOptionArguments();
alias_cmd_obj = ((CommandAlias*)alias_cmd_obj)->GetUnderlyingCommand().get();
std::string alias_name_str = alias_name;
if ((cmd_args.GetArgumentCount() == 0)
|| (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
cmd_args.Unshift (alias_name);
result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
OptionArgVectorSP option_arg_vector_sp = GetAlias(alias_name)->GetOptionArguments();
if (option_arg_vector_sp.get())
{

View File

@ -88,12 +88,12 @@ CommandObject::GetSyntax ()
{
StreamString syntax_str;
syntax_str.Printf ("%s", GetCommandName());
if (GetOptions() != nullptr)
if (!IsDashDashCommand() && GetOptions() != nullptr)
syntax_str.Printf (" <cmd-options>");
if (m_arguments.size() > 0)
{
syntax_str.Printf (" ");
if (WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions())
if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions())
syntax_str.Printf("-- ");
GetFormattedCommandArguments (syntax_str);
}

View File

@ -14,6 +14,7 @@
#include <algorithm>
#include <bitset>
#include <map>
#include <set>
// Other libraries and framework includes
// Project includes
@ -477,6 +478,7 @@ Options::GenerateOptionUsage
CommandObject *cmd
)
{
const bool only_print_args = cmd->IsDashDashCommand();
const uint32_t screen_width = m_interpreter.GetDebugger().GetTerminalWidth();
const OptionDefinition *opt_defs = GetDefinitions();
@ -523,6 +525,8 @@ Options::GenerateOptionUsage
if (cmd)
cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
if (!only_print_args)
{
// First go through and print all options that take no arguments as
// a single string. If a command has "-a" "-b" and "-c", this will show
// up as [-abc]
@ -615,13 +619,16 @@ Options::GenerateOptionUsage
PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm);
}
}
}
if (args_str.GetSize() > 0)
{
if (cmd->WantsRawCommandString())
if (cmd->WantsRawCommandString() && !only_print_args)
strm.Printf(" --");
strm.Printf (" %s", args_str.GetData());
if (only_print_args)
break;
}
}
@ -636,6 +643,8 @@ Options::GenerateOptionUsage
strm.Printf ("\n\n");
if (!only_print_args)
{
// Now print out all the detailed information about the various options: long form, short form and help text:
// -short <argument> ( --long_name <argument> )
// help text
@ -707,6 +716,7 @@ Options::GenerateOptionUsage
}
strm.IndentLess (5);
}
}
// Restore the indent level
strm.SetIndentLevel (save_indent_level);