blob: d84de5423d0ac48a4eb003907acd66e1beb234ca [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectHelp.cpp -----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000014#include "CommandObjectHelp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015#include "lldb/Interpreter/CommandObjectMultiword.h"
16#include "lldb/Interpreter/CommandInterpreter.h"
Jim Ingham40af72e2010-06-15 19:49:27 +000017#include "lldb/Interpreter/Options.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Interpreter/CommandReturnObject.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23//-------------------------------------------------------------------------
24// CommandObjectHelp
25//-------------------------------------------------------------------------
26
Enrico Granata46d4aa22016-02-29 23:22:53 +000027void
28CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage (Stream *s,
29 const char* command,
30 const char* prefix,
31 const char* subcommand,
32 bool include_apropos,
33 bool include_type_lookup)
34{
35 if (s && command && *command)
36 {
37 s->Printf("'%s' is not a known command.\n", command);
38 if (prefix && *prefix)
39 {
40 s->Printf("Try '%shelp' to see a current list of commands.\n", prefix);
41 }
42 else
43 {
44 s->PutCString("Try 'help' to see a current list of commands.\n");
45 }
46
47 if (include_apropos)
48 {
49 s->Printf("Try 'apropos %s' for a list of related commands.\n", subcommand ? subcommand : command);
50 }
51 if (include_type_lookup)
52 {
53 s->Printf("Try 'type lookup %s' for information on types, methods, functions, modules, etc.", subcommand ? subcommand : command);
54 }
55 }
56}
57
Greg Claytona7015092010-09-18 01:14:36 +000058CommandObjectHelp::CommandObjectHelp (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +000059 CommandObjectParsed (interpreter,
60 "help",
61 "Show a list of all debugger commands, or give details about specific commands.",
62 "help [<cmd-name>]"), m_options (interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000063{
Caroline Tice405fe672010-10-04 22:28:36 +000064 CommandArgumentEntry arg;
65 CommandArgumentData command_arg;
66
67 // Define the first (and only) variant of this arg.
68 command_arg.arg_type = eArgTypeCommandName;
69 command_arg.arg_repetition = eArgRepeatStar;
70
71 // There is only one variant this argument could be; put it into the argument entry.
72 arg.push_back (command_arg);
73
74 // Push the data for the first argument into the m_arguments vector.
75 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000076}
77
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000078CommandObjectHelp::~CommandObjectHelp() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079
Enrico Granata08633ee2011-09-09 17:49:36 +000080OptionDefinition
81CommandObjectHelp::CommandOptions::g_option_table[] =
82{
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000083 { LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide aliases in the command list."},
84 { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide user-defined commands from the list."},
85 { LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include commands prefixed with an underscore."},
86 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Enrico Granata08633ee2011-09-09 17:49:36 +000087};
88
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089bool
Jim Ingham5a988412012-06-08 21:56:10 +000090CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091{
92 CommandObject::CommandMap::iterator pos;
93 CommandObject *cmd_obj;
Greg Claytonc7bece562013-01-25 18:06:21 +000094 const size_t argc = command.GetArgumentCount ();
Greg Clayton66111032010-06-23 01:19:29 +000095
Enrico Granata08633ee2011-09-09 17:49:36 +000096 // 'help' doesn't take any arguments, other than command names. If argc is 0, we show the user
97 // all commands (aliases and user commands if asked for). Otherwise every argument must be the name of a command or a sub-command.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098 if (argc == 0)
99 {
Enrico Granata08633ee2011-09-09 17:49:36 +0000100 uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin;
101 if (m_options.m_show_aliases)
102 cmd_types |= CommandInterpreter::eCommandTypesAliases;
103 if (m_options.m_show_user_defined)
104 cmd_types |= CommandInterpreter::eCommandTypesUserDef;
Kate Stonea487aa42015-01-15 00:52:41 +0000105 if (m_options.m_show_hidden)
106 cmd_types |= CommandInterpreter::eCommandTypesHidden;
Enrico Granata08633ee2011-09-09 17:49:36 +0000107
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Enrico Granata08633ee2011-09-09 17:49:36 +0000109 m_interpreter.GetHelp (result, cmd_types); // General help
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110 }
111 else
112 {
113 // Get command object for the first command argument. Only search built-in command dictionary.
Jim Ingham279a6c22010-07-06 22:46:59 +0000114 StringList matches;
Greg Claytona7015092010-09-18 01:14:36 +0000115 cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches);
Caroline Ticee7941792010-10-28 23:17:48 +0000116 bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0));
117 std::string alias_name = command.GetArgumentAtIndex(0);
Greg Clayton66111032010-06-23 01:19:29 +0000118
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000119 if (cmd_obj != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120 {
Jim Ingham271ad292010-11-30 22:59:37 +0000121 StringList matches;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000122 bool all_okay = true;
123 CommandObject *sub_cmd_obj = cmd_obj;
124 // Loop down through sub_command dictionaries until we find the command object that corresponds
125 // to the help command entered.
Enrico Granata46d4aa22016-02-29 23:22:53 +0000126 std::string sub_command;
Andy Gibbsa297a972013-06-19 19:04:53 +0000127 for (size_t i = 1; i < argc && all_okay; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000129 sub_command = command.GetArgumentAtIndex(i);
Jim Ingham271ad292010-11-30 22:59:37 +0000130 matches.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000131 if (! sub_cmd_obj->IsMultiwordObject ())
132 {
133 all_okay = false;
134 }
135 else
136 {
Jim Ingham271ad292010-11-30 22:59:37 +0000137 CommandObject *found_cmd;
Greg Clayton998255b2012-10-13 02:07:45 +0000138 found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches);
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000139 if (found_cmd == nullptr)
Greg Clayton66111032010-06-23 01:19:29 +0000140 all_okay = false;
Jim Ingham97253e62010-12-01 00:42:17 +0000141 else if (matches.GetSize() > 1)
Jim Ingham271ad292010-11-30 22:59:37 +0000142 all_okay = false;
143 else
144 sub_cmd_obj = found_cmd;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145 }
146 }
Greg Clayton66111032010-06-23 01:19:29 +0000147
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000148 if (!all_okay || (sub_cmd_obj == nullptr))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000149 {
150 std::string cmd_string;
151 command.GetCommandString (cmd_string);
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000152 if (matches.GetSize() >= 2)
Jim Ingham271ad292010-11-30 22:59:37 +0000153 {
154 StreamString s;
155 s.Printf ("ambiguous command %s", cmd_string.c_str());
156 size_t num_matches = matches.GetSize();
157 for (size_t match_idx = 0; match_idx < num_matches; match_idx++)
158 {
159 s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx));
160 }
161 s.Printf ("\n");
162 result.AppendError(s.GetData());
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000163 result.SetStatus (eReturnStatusFailed);
164 return false;
Jim Ingham271ad292010-11-30 22:59:37 +0000165 }
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000166 else if (!sub_cmd_obj)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000168 StreamString error_msg_stream;
169 GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
170 cmd_string.c_str(),
171 m_interpreter.GetCommandPrefix(),
172 sub_command.c_str());
173 result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000174 result.SetStatus (eReturnStatusFailed);
175 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000176 }
177 else
178 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000179 GenerateAdditionalHelpAvenuesMessage(&result.GetOutputStream(),
180 cmd_string.c_str(),
181 m_interpreter.GetCommandPrefix(),
182 sub_command.c_str());
183 result.GetOutputStream().Printf("\nThe closest match is '%s'. Help on it follows.\n\n", sub_cmd_obj->GetCommandName());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000184 }
185 }
Caroline Ticee7941792010-10-28 23:17:48 +0000186
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000187 sub_cmd_obj->GenerateHelpText(result);
188
Caroline Ticee7941792010-10-28 23:17:48 +0000189 if (is_alias_command)
190 {
191 StreamString sstr;
Enrico Granata4643c012016-03-09 02:27:57 +0000192 m_interpreter.GetAlias(alias_name.c_str())->GetAliasExpansion(sstr);
Caroline Ticee7941792010-10-28 23:17:48 +0000193 result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData());
194 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000195 }
Jim Ingham279a6c22010-07-06 22:46:59 +0000196 else if (matches.GetSize() > 0)
197 {
198 Stream &output_strm = result.GetOutputStream();
199 output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
Greg Claytonc7bece562013-01-25 18:06:21 +0000200 const size_t match_count = matches.GetSize();
201 for (size_t i = 0; i < match_count; i++)
Jim Ingham279a6c22010-07-06 22:46:59 +0000202 {
203 output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
204 }
205 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000206 else
207 {
Caroline Ticee139cf22010-10-01 17:46:38 +0000208 // Maybe the user is asking for help about a command argument rather than a command.
209 const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0));
210 if (arg_type != eArgTypeLastArg)
211 {
212 Stream &output_strm = result.GetOutputStream ();
213 CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter);
214 result.SetStatus (eReturnStatusSuccessFinishNoResult);
215 }
216 else
217 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000218 StreamString error_msg_stream;
219 GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command.GetArgumentAtIndex(0), m_interpreter.GetCommandPrefix());
220 result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
Caroline Ticee139cf22010-10-01 17:46:38 +0000221 result.SetStatus (eReturnStatusFailed);
222 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223 }
224 }
Greg Clayton66111032010-06-23 01:19:29 +0000225
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226 return result.Succeeded();
227}
228
229int
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000230CommandObjectHelp::HandleCompletion(Args &input,
231 int &cursor_index,
232 int &cursor_char_position,
233 int match_start_point,
234 int max_return_elements,
235 bool &word_complete,
236 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237{
238 // Return the completions of the commands in the help system:
239 if (cursor_index == 0)
240 {
Greg Claytona7015092010-09-18 01:14:36 +0000241 return m_interpreter.HandleCompletionMatches (input,
242 cursor_index,
243 cursor_char_position,
244 match_start_point,
245 max_return_elements,
246 word_complete,
247 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000248 }
249 else
250 {
Greg Claytona7015092010-09-18 01:14:36 +0000251 CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
Jim Ingham1d18ebf2011-10-26 19:32:01 +0000252
253 // The command that they are getting help on might be ambiguous, in which case we should complete that,
254 // otherwise complete with the command the user is getting help on...
255
256 if (cmd_obj)
257 {
258 input.Shift();
259 cursor_index--;
260 return cmd_obj->HandleCompletion (input,
261 cursor_index,
262 cursor_char_position,
263 match_start_point,
264 max_return_elements,
265 word_complete,
266 matches);
267 }
268 else
269 {
270 return m_interpreter.HandleCompletionMatches (input,
271 cursor_index,
272 cursor_char_position,
273 match_start_point,
274 max_return_elements,
275 word_complete,
276 matches);
277 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000278 }
279}