<rdar://problem/11914077>
authorEnrico Granata <egranata@apple.com>
Wed, 12 Jun 2013 01:50:57 +0000 (01:50 +0000)
committerEnrico Granata <egranata@apple.com>
Wed, 12 Jun 2013 01:50:57 +0000 (01:50 +0000)
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

lldb/include/lldb/Interpreter/CommandObject.h
lldb/include/lldb/Interpreter/CommandObjectMultiword.h
lldb/source/Commands/CommandObjectHelp.cpp
lldb/source/Commands/CommandObjectHelp.h
lldb/source/Commands/CommandObjectMultiword.cpp
lldb/source/Interpreter/CommandObject.cpp

index 917061e3e14c9bb40861ac04181a993b9208544c..6ddebdb563a779b0632a172bf71e740f30c78ccc 100644 (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
index d417f23eea8449b6768a324b09ccc94eb8b835fa..491d43c4bd9db1a25b4cc8766cca3370c6de8bbc 100644 (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);
index 00e2551842fc2a2566f4e0be4290391be1d0c966..7d638a4732e014618f3cbfa790dbbc59ba83067f 100644 (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)
-                {
-                    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())
+                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);
-                    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;
index 91a40b529496cc1e3e05346f31bf6b10b589a093..6e8f9d4cbc7b2715f2f464c85f8ee8e6f5c3d28d 100644 (file)
@@ -108,7 +108,7 @@ protected:
     virtual bool
     DoExecute (Args& command,
              CommandReturnObject &result);
-
+    
 private:
     CommandOptions m_options;
     
index bfb5132a6443e99c3ab9b7007876d2773b30aa6b..f84b401f3aa6e56823437ff8292d053e9a514a7d 100644 (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
index 68756050c6f7ce6f125e648c18ed69833123ce93..67d57f1b1e1d94c85786bd7615a4556843979ced 100644 (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)
 {