blob: 56c940ed38472c29a03a763a6c86a0a318ef1188 [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);
Kate Stone25d60722016-04-21 00:55:20 +000038 s->Printf("Try '%shelp' to see a current list of commands.\n", prefix ? prefix : "");
Enrico Granata46d4aa22016-02-29 23:22:53 +000039 if (include_apropos)
40 {
Kate Stone25d60722016-04-21 00:55:20 +000041 s->Printf("Try '%sapropos %s' for a list of related commands.\n",
42 prefix ? prefix : "", subcommand ? subcommand : command);
Enrico Granata46d4aa22016-02-29 23:22:53 +000043 }
44 if (include_type_lookup)
45 {
Kate Stone25d60722016-04-21 00:55:20 +000046 s->Printf("Try '%stype lookup %s' for information on types, methods, functions, modules, etc.",
47 prefix ? prefix : "", subcommand ? subcommand : command);
Enrico Granata46d4aa22016-02-29 23:22:53 +000048 }
49 }
50}
51
Kate Stone7428a182016-07-14 22:03:10 +000052CommandObjectHelp::CommandObjectHelp(CommandInterpreter &interpreter)
53 : CommandObjectParsed(interpreter, "help",
54 "Show a list of all debugger commands, or give details about a specific command.",
55 "help [<cmd-name>]"),
Todd Fialae1cfbc72016-08-11 23:51:28 +000056 m_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057{
Caroline Tice405fe672010-10-04 22:28:36 +000058 CommandArgumentEntry arg;
59 CommandArgumentData command_arg;
60
61 // Define the first (and only) variant of this arg.
62 command_arg.arg_type = eArgTypeCommandName;
63 command_arg.arg_repetition = eArgRepeatStar;
64
65 // There is only one variant this argument could be; put it into the argument entry.
66 arg.push_back (command_arg);
67
68 // Push the data for the first argument into the m_arguments vector.
69 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000070}
71
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000072CommandObjectHelp::~CommandObjectHelp() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073
Enrico Granata08633ee2011-09-09 17:49:36 +000074OptionDefinition
75CommandObjectHelp::CommandOptions::g_option_table[] =
76{
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000077 { LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide aliases in the command list."},
78 { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide user-defined commands from the list."},
79 { LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include commands prefixed with an underscore."},
80 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Enrico Granata08633ee2011-09-09 17:49:36 +000081};
82
Chris Lattner30fdc8d2010-06-08 16:52:24 +000083bool
Jim Ingham5a988412012-06-08 21:56:10 +000084CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000085{
86 CommandObject::CommandMap::iterator pos;
87 CommandObject *cmd_obj;
Greg Claytonc7bece562013-01-25 18:06:21 +000088 const size_t argc = command.GetArgumentCount ();
Greg Clayton66111032010-06-23 01:19:29 +000089
Enrico Granata08633ee2011-09-09 17:49:36 +000090 // 'help' doesn't take any arguments, other than command names. If argc is 0, we show the user
91 // 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 +000092 if (argc == 0)
93 {
Enrico Granata08633ee2011-09-09 17:49:36 +000094 uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin;
95 if (m_options.m_show_aliases)
96 cmd_types |= CommandInterpreter::eCommandTypesAliases;
97 if (m_options.m_show_user_defined)
98 cmd_types |= CommandInterpreter::eCommandTypesUserDef;
Kate Stonea487aa42015-01-15 00:52:41 +000099 if (m_options.m_show_hidden)
100 cmd_types |= CommandInterpreter::eCommandTypesHidden;
Enrico Granata08633ee2011-09-09 17:49:36 +0000101
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Enrico Granata08633ee2011-09-09 17:49:36 +0000103 m_interpreter.GetHelp (result, cmd_types); // General help
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 }
105 else
106 {
107 // Get command object for the first command argument. Only search built-in command dictionary.
Jim Ingham279a6c22010-07-06 22:46:59 +0000108 StringList matches;
Greg Claytona7015092010-09-18 01:14:36 +0000109 cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches);
Caroline Ticee7941792010-10-28 23:17:48 +0000110 bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0));
111 std::string alias_name = command.GetArgumentAtIndex(0);
Greg Clayton66111032010-06-23 01:19:29 +0000112
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000113 if (cmd_obj != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114 {
Jim Ingham271ad292010-11-30 22:59:37 +0000115 StringList matches;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116 bool all_okay = true;
117 CommandObject *sub_cmd_obj = cmd_obj;
118 // Loop down through sub_command dictionaries until we find the command object that corresponds
119 // to the help command entered.
Enrico Granata46d4aa22016-02-29 23:22:53 +0000120 std::string sub_command;
Andy Gibbsa297a972013-06-19 19:04:53 +0000121 for (size_t i = 1; i < argc && all_okay; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000122 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000123 sub_command = command.GetArgumentAtIndex(i);
Jim Ingham271ad292010-11-30 22:59:37 +0000124 matches.Clear();
Enrico Granatabef55ac2016-03-14 22:17:04 +0000125 if (sub_cmd_obj->IsAlias())
126 sub_cmd_obj = ((CommandAlias*)sub_cmd_obj)->GetUnderlyingCommand().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000127 if (! sub_cmd_obj->IsMultiwordObject ())
128 {
129 all_okay = false;
130 }
131 else
132 {
Jim Ingham271ad292010-11-30 22:59:37 +0000133 CommandObject *found_cmd;
Greg Clayton998255b2012-10-13 02:07:45 +0000134 found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches);
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000135 if (found_cmd == nullptr)
Greg Clayton66111032010-06-23 01:19:29 +0000136 all_okay = false;
Jim Ingham97253e62010-12-01 00:42:17 +0000137 else if (matches.GetSize() > 1)
Jim Ingham271ad292010-11-30 22:59:37 +0000138 all_okay = false;
139 else
140 sub_cmd_obj = found_cmd;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141 }
142 }
Greg Clayton66111032010-06-23 01:19:29 +0000143
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000144 if (!all_okay || (sub_cmd_obj == nullptr))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145 {
146 std::string cmd_string;
147 command.GetCommandString (cmd_string);
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000148 if (matches.GetSize() >= 2)
Jim Ingham271ad292010-11-30 22:59:37 +0000149 {
150 StreamString s;
151 s.Printf ("ambiguous command %s", cmd_string.c_str());
152 size_t num_matches = matches.GetSize();
153 for (size_t match_idx = 0; match_idx < num_matches; match_idx++)
154 {
155 s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx));
156 }
157 s.Printf ("\n");
158 result.AppendError(s.GetData());
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000159 result.SetStatus (eReturnStatusFailed);
160 return false;
Jim Ingham271ad292010-11-30 22:59:37 +0000161 }
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000162 else if (!sub_cmd_obj)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000163 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000164 StreamString error_msg_stream;
165 GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
166 cmd_string.c_str(),
167 m_interpreter.GetCommandPrefix(),
168 sub_command.c_str());
169 result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000170 result.SetStatus (eReturnStatusFailed);
171 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000172 }
173 else
174 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000175 GenerateAdditionalHelpAvenuesMessage(&result.GetOutputStream(),
176 cmd_string.c_str(),
177 m_interpreter.GetCommandPrefix(),
178 sub_command.c_str());
179 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 +0000180 }
181 }
Caroline Ticee7941792010-10-28 23:17:48 +0000182
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000183 sub_cmd_obj->GenerateHelpText(result);
184
Caroline Ticee7941792010-10-28 23:17:48 +0000185 if (is_alias_command)
186 {
187 StreamString sstr;
Enrico Granata4643c012016-03-09 02:27:57 +0000188 m_interpreter.GetAlias(alias_name.c_str())->GetAliasExpansion(sstr);
Caroline Ticee7941792010-10-28 23:17:48 +0000189 result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData());
190 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 }
Jim Ingham279a6c22010-07-06 22:46:59 +0000192 else if (matches.GetSize() > 0)
193 {
194 Stream &output_strm = result.GetOutputStream();
195 output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
Greg Claytonc7bece562013-01-25 18:06:21 +0000196 const size_t match_count = matches.GetSize();
197 for (size_t i = 0; i < match_count; i++)
Jim Ingham279a6c22010-07-06 22:46:59 +0000198 {
199 output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
200 }
201 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000202 else
203 {
Caroline Ticee139cf22010-10-01 17:46:38 +0000204 // Maybe the user is asking for help about a command argument rather than a command.
205 const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0));
206 if (arg_type != eArgTypeLastArg)
207 {
208 Stream &output_strm = result.GetOutputStream ();
209 CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter);
210 result.SetStatus (eReturnStatusSuccessFinishNoResult);
211 }
212 else
213 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000214 StreamString error_msg_stream;
215 GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command.GetArgumentAtIndex(0), m_interpreter.GetCommandPrefix());
216 result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
Caroline Ticee139cf22010-10-01 17:46:38 +0000217 result.SetStatus (eReturnStatusFailed);
218 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000219 }
220 }
Greg Clayton66111032010-06-23 01:19:29 +0000221
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000222 return result.Succeeded();
223}
224
225int
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000226CommandObjectHelp::HandleCompletion(Args &input,
227 int &cursor_index,
228 int &cursor_char_position,
229 int match_start_point,
230 int max_return_elements,
231 bool &word_complete,
232 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233{
234 // Return the completions of the commands in the help system:
235 if (cursor_index == 0)
236 {
Greg Claytona7015092010-09-18 01:14:36 +0000237 return m_interpreter.HandleCompletionMatches (input,
238 cursor_index,
239 cursor_char_position,
240 match_start_point,
241 max_return_elements,
242 word_complete,
243 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 }
245 else
246 {
Greg Claytona7015092010-09-18 01:14:36 +0000247 CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
Jim Ingham1d18ebf2011-10-26 19:32:01 +0000248
249 // The command that they are getting help on might be ambiguous, in which case we should complete that,
250 // otherwise complete with the command the user is getting help on...
251
252 if (cmd_obj)
253 {
254 input.Shift();
255 cursor_index--;
256 return cmd_obj->HandleCompletion (input,
257 cursor_index,
258 cursor_char_position,
259 match_start_point,
260 max_return_elements,
261 word_complete,
262 matches);
263 }
264 else
265 {
266 return m_interpreter.HandleCompletionMatches (input,
267 cursor_index,
268 cursor_char_position,
269 match_start_point,
270 max_return_elements,
271 word_complete,
272 matches);
273 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000274 }
275}