summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEnrico Granata <egranata@apple.com>2016-02-29 23:22:53 +0000
committerEnrico Granata <egranata@apple.com>2016-02-29 23:22:53 +0000
commit46d4aa211ff9e84d8f71aafe818804758133b8aa (patch)
treee0b3359f9b1e2d1ea78ec80b81e23675eb4e245f
parentefc091f457c98ecf86498fe0fd45c81a58d4a2ab (diff)
downloadbcm5719-llvm-46d4aa211ff9e84d8f71aafe818804758133b8aa.tar.gz
bcm5719-llvm-46d4aa211ff9e84d8f71aafe818804758133b8aa.zip
When 'help' cannot find a command, produce additional help text that also points the user to the apropos and type lookup commands
This is useful in cases such as, e.g. (lldb) help NSString (the user meant type lookup) or (lldb) help kill (the user is looking for process kill) Fixes rdar://24868537 llvm-svn: 262271
-rw-r--r--lldb/packages/Python/lldbsuite/test/help/TestHelp.py15
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp13
-rw-r--r--lldb/source/Commands/CommandObjectHelp.cpp62
-rw-r--r--lldb/source/Commands/CommandObjectHelp.h8
-rw-r--r--lldb/source/Commands/CommandObjectSyntax.cpp14
5 files changed, 93 insertions, 19 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/help/TestHelp.py b/lldb/packages/Python/lldbsuite/test/help/TestHelp.py
index b36d82830a3..4bfbe6ef188 100644
--- a/lldb/packages/Python/lldbsuite/test/help/TestHelp.py
+++ b/lldb/packages/Python/lldbsuite/test/help/TestHelp.py
@@ -165,3 +165,18 @@ class HelpCommandTestCase(TestBase):
substrs = ['The following subcommands are supported:'],
patterns = ['expression +--',
'variable +--'])
+
+ @no_debug_info_test
+ def test_help_provides_alternatives(self):
+ """Test that help on commands that don't exist provides information on additional help avenues"""
+ self.expect("help thisisnotadebuggercommand",
+ substrs = ["'thisisnotadebuggercommand' is not a known command.",
+ "Try 'help' to see a current list of commands.",
+ "Try 'apropos thisisnotadebuggercommand' for a list of related commands.",
+ "Try 'type lookup thisisnotadebuggercommand' for information on types, methods, functions, modules, etc."], error=True)
+
+ self.expect("help process thisisnotadebuggercommand",
+ substrs = ["'process thisisnotadebuggercommand' is not a known command.",
+ "Try 'help' to see a current list of commands.",
+ "Try 'apropos thisisnotadebuggercommand' for a list of related commands.",
+ "Try 'type lookup thisisnotadebuggercommand' for information on types, methods, functions, modules, etc."])
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index 046698491d8..e2e2bb81ea0 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -14,6 +14,7 @@
// Project includes
#include "CommandObjectCommands.h"
+#include "CommandObjectHelp.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/StringList.h"
@@ -920,8 +921,16 @@ protected:
}
else
{
- result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
- command_name);
+ StreamString error_msg_stream;
+ const bool generate_apropos = true;
+ const bool generate_type_lookup = false;
+ CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
+ command_name,
+ nullptr,
+ nullptr,
+ generate_apropos,
+ generate_type_lookup);
+ result.AppendErrorWithFormat ("%s", error_msg_stream.GetData());
result.SetStatus (eReturnStatusFailed);
}
}
diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp
index 14d1ae5a0b4..ad969dbfd8f 100644
--- a/lldb/source/Commands/CommandObjectHelp.cpp
+++ b/lldb/source/Commands/CommandObjectHelp.cpp
@@ -24,6 +24,37 @@ using namespace lldb_private;
// CommandObjectHelp
//-------------------------------------------------------------------------
+void
+CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage (Stream *s,
+ const char* command,
+ const char* prefix,
+ const char* subcommand,
+ bool include_apropos,
+ bool include_type_lookup)
+{
+ if (s && command && *command)
+ {
+ s->Printf("'%s' is not a known command.\n", command);
+ if (prefix && *prefix)
+ {
+ s->Printf("Try '%shelp' to see a current list of commands.\n", prefix);
+ }
+ else
+ {
+ s->PutCString("Try 'help' to see a current list of commands.\n");
+ }
+
+ if (include_apropos)
+ {
+ s->Printf("Try 'apropos %s' for a list of related commands.\n", subcommand ? subcommand : command);
+ }
+ if (include_type_lookup)
+ {
+ s->Printf("Try 'type lookup %s' for information on types, methods, functions, modules, etc.", subcommand ? subcommand : command);
+ }
+ }
+}
+
CommandObjectHelp::CommandObjectHelp (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"help",
@@ -92,9 +123,10 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
CommandObject *sub_cmd_obj = cmd_obj;
// Loop down through sub_command dictionaries until we find the command object that corresponds
// to the help command entered.
+ std::string sub_command;
for (size_t i = 1; i < argc && all_okay; ++i)
{
- std::string sub_command = command.GetArgumentAtIndex(i);
+ sub_command = command.GetArgumentAtIndex(i);
matches.Clear();
if (! sub_cmd_obj->IsMultiwordObject ())
{
@@ -133,21 +165,22 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
}
else if (!sub_cmd_obj)
{
- result.AppendErrorWithFormat("'%s' is not a known command.\n"
- "Try '%shelp' to see a current list of commands.\n",
- cmd_string.c_str(),
- m_interpreter.GetCommandPrefix());
+ StreamString error_msg_stream;
+ GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
+ cmd_string.c_str(),
+ m_interpreter.GetCommandPrefix(),
+ sub_command.c_str());
+ result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
- result.GetOutputStream().Printf("'%s' is not a known command.\n"
- "Try '%shelp' to see a current list of commands.\n"
- "The closest match is '%s'. Help on it follows.\n\n",
- cmd_string.c_str(),
- m_interpreter.GetCommandPrefix(),
- sub_cmd_obj->GetCommandName());
+ GenerateAdditionalHelpAvenuesMessage(&result.GetOutputStream(),
+ cmd_string.c_str(),
+ m_interpreter.GetCommandPrefix(),
+ sub_command.c_str());
+ result.GetOutputStream().Printf("\nThe closest match is '%s'. Help on it follows.\n\n", sub_cmd_obj->GetCommandName());
}
}
@@ -182,10 +215,9 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
}
else
{
- result.AppendErrorWithFormat
- ("'%s' is not a known command.\nTry '%shelp' to see a current list of commands.\n",
- command.GetArgumentAtIndex(0),
- m_interpreter.GetCommandPrefix());
+ StreamString error_msg_stream;
+ GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command.GetArgumentAtIndex(0), m_interpreter.GetCommandPrefix());
+ result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
result.SetStatus (eReturnStatusFailed);
}
}
diff --git a/lldb/source/Commands/CommandObjectHelp.h b/lldb/source/Commands/CommandObjectHelp.h
index 1dd7b9b8d6a..a374a10e3e7 100644
--- a/lldb/source/Commands/CommandObjectHelp.h
+++ b/lldb/source/Commands/CommandObjectHelp.h
@@ -40,6 +40,14 @@ public:
bool &word_complete,
StringList &matches) override;
+ static void
+ GenerateAdditionalHelpAvenuesMessage (Stream *s,
+ const char* command,
+ const char* prefix = nullptr,
+ const char* subcommand = nullptr,
+ bool include_apropos = true,
+ bool include_type_lookup = true);
+
class CommandOptions : public Options
{
public:
diff --git a/lldb/source/Commands/CommandObjectSyntax.cpp b/lldb/source/Commands/CommandObjectSyntax.cpp
index 12bfce3c292..c238bccfb5d 100644
--- a/lldb/source/Commands/CommandObjectSyntax.cpp
+++ b/lldb/source/Commands/CommandObjectSyntax.cpp
@@ -12,6 +12,7 @@
// Other libraries and framework includes
// Project includes
#include "CommandObjectSyntax.h"
+#include "CommandObjectHelp.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -97,8 +98,17 @@ CommandObjectSyntax::DoExecute (Args& command, CommandReturnObject &result)
{
std::string cmd_string;
command.GetCommandString (cmd_string);
- result.AppendErrorWithFormat ("'%s' is not a known command.\n", cmd_string.c_str());
- result.AppendError ("Try 'help' to see a current list of commands.");
+
+ StreamString error_msg_stream;
+ const bool generate_apropos = true;
+ const bool generate_type_lookup = false;
+ CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
+ cmd_string.c_str(),
+ nullptr,
+ nullptr,
+ generate_apropos,
+ generate_type_lookup);
+ result.AppendErrorWithFormat ("%s", error_msg_stream.GetData());
result.SetStatus (eReturnStatusFailed);
}
}
OpenPOWER on IntegriCloud