<rdar://problem/11914077>

If you type help command <word> <word> <word> <missingSubCommand> (e.g. help script import or help type summary fake), you will get help on the deepest matched command word (i.e. script or type summary in the examples)
Also, reworked the logic for commands to produce their help to make it more object-oriented

llvm-svn: 183822
This commit is contained in:
Enrico Granata 2013-06-12 01:50:57 +00:00
parent f045007f11
commit 9b62d1d5ee
6 changed files with 104 additions and 89 deletions

View File

@ -160,10 +160,11 @@ public:
{
}
void
GenerateHelpText (CommandReturnObject &result);
virtual void
GenerateHelpText (CommandReturnObject &result)
{
}
GenerateHelpText (Stream &result);
// this is needed in order to allow the SBCommand class to
// transparently try and load subcommands - it will fail on

View File

@ -47,7 +47,7 @@ public:
const lldb::CommandObjectSP& command_obj);
virtual void
GenerateHelpText (CommandReturnObject &result);
GenerateHelpText (Stream &output_stream);
virtual lldb::CommandObjectSP
GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL);

View File

@ -119,13 +119,7 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
{
std::string cmd_string;
command.GetCommandString (cmd_string);
if (matches.GetSize() < 2)
{
result.AppendErrorWithFormat("'%s' is not a known command.\n"
"Try 'help' to see a current list of commands.\n",
cmd_string.c_str());
}
else
if (matches.GetSize() >= 2)
{
StreamString s;
s.Printf ("ambiguous command %s", cmd_string.c_str());
@ -136,83 +130,29 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
}
s.Printf ("\n");
result.AppendError(s.GetData());
result.SetStatus (eReturnStatusFailed);
return false;
}
result.SetStatus (eReturnStatusFailed);
}
else
{
Stream &output_strm = result.GetOutputStream();
if (sub_cmd_obj->GetOptions() != NULL)
else if (!sub_cmd_obj)
{
if (sub_cmd_obj->WantsRawCommandString())
{
std::string help_text (sub_cmd_obj->GetHelp());
help_text.append (" This command takes 'raw' input (no need to quote stuff).");
m_interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
}
else
m_interpreter.OutputFormattedHelpText (output_strm, "", "", sub_cmd_obj->GetHelp(), 1);
output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
sub_cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, sub_cmd_obj);
const char *long_help = sub_cmd_obj->GetHelpLong();
if ((long_help != NULL)
&& (strlen (long_help) > 0))
output_strm.Printf ("\n%s", long_help);
if (sub_cmd_obj->WantsRawCommandString() && !sub_cmd_obj->WantsCompletion())
{
// Emit the message about using ' -- ' between the end of the command options and the raw input
// conditionally, i.e., only if the command object does not want completion.
m_interpreter.OutputFormattedHelpText (output_strm, "", "",
"\nIMPORTANT NOTE: Because this command takes 'raw' input, if you use any command options"
" you must use ' -- ' between the end of the command options and the beginning of the raw input.", 1);
}
else if (sub_cmd_obj->GetNumArgumentEntries() > 0
&& sub_cmd_obj->GetOptions()
&& sub_cmd_obj->GetOptions()->NumCommandOptions() > 0)
{
// Also emit a warning about using "--" in case you are using a command that takes options and arguments.
m_interpreter.OutputFormattedHelpText (output_strm, "", "",
"\nThis command takes options and free-form arguments. If your arguments resemble"
" option specifiers (i.e., they start with a - or --), you must use ' -- ' between"
" the end of the command options and the beginning of the arguments.", 1);
}
// Mark this help command with a success status.
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else if (sub_cmd_obj->IsMultiwordObject())
{
if (sub_cmd_obj->WantsRawCommandString())
{
std::string help_text (sub_cmd_obj->GetHelp());
help_text.append (" This command takes 'raw' input (no need to quote stuff).");
m_interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
}
else
m_interpreter.OutputFormattedHelpText (output_strm, "", "", sub_cmd_obj->GetHelp(), 1);
sub_cmd_obj->GenerateHelpText (result);
result.AppendErrorWithFormat("'%s' is not a known command.\n"
"Try 'help' to see a current list of commands.\n",
cmd_string.c_str());
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
const char *long_help = sub_cmd_obj->GetHelpLong();
if ((long_help != NULL)
&& (strlen (long_help) > 0))
output_strm.Printf ("%s", long_help);
else if (sub_cmd_obj->WantsRawCommandString())
{
std::string help_text (sub_cmd_obj->GetHelp());
help_text.append (" This command takes 'raw' input (no need to quote stuff).");
m_interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
}
else
m_interpreter.OutputFormattedHelpText (output_strm, "", "", sub_cmd_obj->GetHelp(), 1);
output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
// Mark this help command with a success status.
result.SetStatus (eReturnStatusSuccessFinishNoResult);
result.GetOutputStream().Printf("'%s' is not a known command.\n"
"Try 'help' to see a current list of commands.\n"
"The closest match is '%s'. Help on it follows.\n\n",
cmd_string.c_str(),
sub_cmd_obj->GetCommandName());
}
}
sub_cmd_obj->GenerateHelpText(result);
if (is_alias_command)
{
StreamString sstr;

View File

@ -108,7 +108,7 @@ protected:
virtual bool
DoExecute (Args& command,
CommandReturnObject &result);
private:
CommandOptions m_options;

View File

@ -115,7 +115,7 @@ CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &re
const size_t argc = args.GetArgumentCount();
if (argc == 0)
{
GenerateHelpText (result);
this->CommandObject::GenerateHelpText (result);
}
else
{
@ -125,7 +125,7 @@ CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &re
{
if (::strcasecmp (sub_command, "help") == 0)
{
GenerateHelpText (result);
this->CommandObject::GenerateHelpText (result);
}
else if (!m_subcommand_dict.empty())
{
@ -181,12 +181,11 @@ CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &re
}
void
CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result)
CommandObjectMultiword::GenerateHelpText (Stream &output_stream)
{
// First time through here, generate the help text for the object and
// push it to the return result object as well
Stream &output_stream = result.GetOutputStream();
output_stream.PutCString ("The following subcommands are supported:\n\n");
CommandMap::iterator pos;
@ -203,14 +202,14 @@ CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result)
{
std::string help_text (pos->second->GetHelp());
help_text.append (" This command takes 'raw' input (no need to quote stuff).");
m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
m_interpreter.OutputFormattedHelpText (output_stream,
indented_command.c_str(),
"--",
help_text.c_str(),
max_len);
}
else
m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
m_interpreter.OutputFormattedHelpText (output_stream,
indented_command.c_str(),
"--",
pos->second->GetHelp(),
@ -218,8 +217,6 @@ CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result)
}
output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
int

View File

@ -902,6 +902,83 @@ ExprPathHelpTextCallback()
" meaning of array slicing (taking elements n thru m inside the array or pointed-to memory).";
}
void
CommandObject::GenerateHelpText (CommandReturnObject &result)
{
GenerateHelpText(result.GetOutputStream());
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
void
CommandObject::GenerateHelpText (Stream &output_strm)
{
CommandInterpreter& interpreter = GetCommandInterpreter();
if (GetOptions() != NULL)
{
if (WantsRawCommandString())
{
std::string help_text (GetHelp());
help_text.append (" This command takes 'raw' input (no need to quote stuff).");
interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
}
else
interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
GetOptions()->GenerateOptionUsage (output_strm, this);
const char *long_help = GetHelpLong();
if ((long_help != NULL)
&& (strlen (long_help) > 0))
output_strm.Printf ("\n%s", long_help);
if (WantsRawCommandString() && !WantsCompletion())
{
// Emit the message about using ' -- ' between the end of the command options and the raw input
// conditionally, i.e., only if the command object does not want completion.
interpreter.OutputFormattedHelpText (output_strm, "", "",
"\nIMPORTANT NOTE: Because this command takes 'raw' input, if you use any command options"
" you must use ' -- ' between the end of the command options and the beginning of the raw input.", 1);
}
else if (GetNumArgumentEntries() > 0
&& GetOptions()
&& GetOptions()->NumCommandOptions() > 0)
{
// Also emit a warning about using "--" in case you are using a command that takes options and arguments.
interpreter.OutputFormattedHelpText (output_strm, "", "",
"\nThis command takes options and free-form arguments. If your arguments resemble"
" option specifiers (i.e., they start with a - or --), you must use ' -- ' between"
" the end of the command options and the beginning of the arguments.", 1);
}
}
else if (IsMultiwordObject())
{
if (WantsRawCommandString())
{
std::string help_text (GetHelp());
help_text.append (" This command takes 'raw' input (no need to quote stuff).");
interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
}
else
interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
GenerateHelpText (output_strm);
}
else
{
const char *long_help = GetHelpLong();
if ((long_help != NULL)
&& (strlen (long_help) > 0))
output_strm.Printf ("%s", long_help);
else if (WantsRawCommandString())
{
std::string help_text (GetHelp());
help_text.append (" This command takes 'raw' input (no need to quote stuff).");
interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
}
else
interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
}
}
void
CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, CommandArgumentType ID, CommandArgumentType IDRange)
{