blob: 71f280020d3e08c5e10e329bbd942505fc9caf7f [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();
Enrico Granatabef55ac2016-03-14 22:17:04 +0000131 if (sub_cmd_obj->IsAlias())
132 sub_cmd_obj = ((CommandAlias*)sub_cmd_obj)->GetUnderlyingCommand().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133 if (! sub_cmd_obj->IsMultiwordObject ())
134 {
135 all_okay = false;
136 }
137 else
138 {
Jim Ingham271ad292010-11-30 22:59:37 +0000139 CommandObject *found_cmd;
Greg Clayton998255b2012-10-13 02:07:45 +0000140 found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches);
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000141 if (found_cmd == nullptr)
Greg Clayton66111032010-06-23 01:19:29 +0000142 all_okay = false;
Jim Ingham97253e62010-12-01 00:42:17 +0000143 else if (matches.GetSize() > 1)
Jim Ingham271ad292010-11-30 22:59:37 +0000144 all_okay = false;
145 else
146 sub_cmd_obj = found_cmd;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147 }
148 }
Greg Clayton66111032010-06-23 01:19:29 +0000149
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000150 if (!all_okay || (sub_cmd_obj == nullptr))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151 {
152 std::string cmd_string;
153 command.GetCommandString (cmd_string);
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000154 if (matches.GetSize() >= 2)
Jim Ingham271ad292010-11-30 22:59:37 +0000155 {
156 StreamString s;
157 s.Printf ("ambiguous command %s", cmd_string.c_str());
158 size_t num_matches = matches.GetSize();
159 for (size_t match_idx = 0; match_idx < num_matches; match_idx++)
160 {
161 s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx));
162 }
163 s.Printf ("\n");
164 result.AppendError(s.GetData());
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000165 result.SetStatus (eReturnStatusFailed);
166 return false;
Jim Ingham271ad292010-11-30 22:59:37 +0000167 }
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000168 else if (!sub_cmd_obj)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000170 StreamString error_msg_stream;
171 GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
172 cmd_string.c_str(),
173 m_interpreter.GetCommandPrefix(),
174 sub_command.c_str());
175 result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000176 result.SetStatus (eReturnStatusFailed);
177 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178 }
179 else
180 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000181 GenerateAdditionalHelpAvenuesMessage(&result.GetOutputStream(),
182 cmd_string.c_str(),
183 m_interpreter.GetCommandPrefix(),
184 sub_command.c_str());
185 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 +0000186 }
187 }
Caroline Ticee7941792010-10-28 23:17:48 +0000188
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000189 sub_cmd_obj->GenerateHelpText(result);
190
Caroline Ticee7941792010-10-28 23:17:48 +0000191 if (is_alias_command)
192 {
193 StreamString sstr;
Enrico Granata4643c012016-03-09 02:27:57 +0000194 m_interpreter.GetAlias(alias_name.c_str())->GetAliasExpansion(sstr);
Caroline Ticee7941792010-10-28 23:17:48 +0000195 result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData());
196 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197 }
Jim Ingham279a6c22010-07-06 22:46:59 +0000198 else if (matches.GetSize() > 0)
199 {
200 Stream &output_strm = result.GetOutputStream();
201 output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
Greg Claytonc7bece562013-01-25 18:06:21 +0000202 const size_t match_count = matches.GetSize();
203 for (size_t i = 0; i < match_count; i++)
Jim Ingham279a6c22010-07-06 22:46:59 +0000204 {
205 output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
206 }
207 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000208 else
209 {
Caroline Ticee139cf22010-10-01 17:46:38 +0000210 // Maybe the user is asking for help about a command argument rather than a command.
211 const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0));
212 if (arg_type != eArgTypeLastArg)
213 {
214 Stream &output_strm = result.GetOutputStream ();
215 CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter);
216 result.SetStatus (eReturnStatusSuccessFinishNoResult);
217 }
218 else
219 {
Enrico Granata46d4aa22016-02-29 23:22:53 +0000220 StreamString error_msg_stream;
221 GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command.GetArgumentAtIndex(0), m_interpreter.GetCommandPrefix());
222 result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
Caroline Ticee139cf22010-10-01 17:46:38 +0000223 result.SetStatus (eReturnStatusFailed);
224 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225 }
226 }
Greg Clayton66111032010-06-23 01:19:29 +0000227
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228 return result.Succeeded();
229}
230
231int
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000232CommandObjectHelp::HandleCompletion(Args &input,
233 int &cursor_index,
234 int &cursor_char_position,
235 int match_start_point,
236 int max_return_elements,
237 bool &word_complete,
238 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000239{
240 // Return the completions of the commands in the help system:
241 if (cursor_index == 0)
242 {
Greg Claytona7015092010-09-18 01:14:36 +0000243 return m_interpreter.HandleCompletionMatches (input,
244 cursor_index,
245 cursor_char_position,
246 match_start_point,
247 max_return_elements,
248 word_complete,
249 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000250 }
251 else
252 {
Greg Claytona7015092010-09-18 01:14:36 +0000253 CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
Jim Ingham1d18ebf2011-10-26 19:32:01 +0000254
255 // The command that they are getting help on might be ambiguous, in which case we should complete that,
256 // otherwise complete with the command the user is getting help on...
257
258 if (cmd_obj)
259 {
260 input.Shift();
261 cursor_index--;
262 return cmd_obj->HandleCompletion (input,
263 cursor_index,
264 cursor_char_position,
265 match_start_point,
266 max_return_elements,
267 word_complete,
268 matches);
269 }
270 else
271 {
272 return m_interpreter.HandleCompletionMatches (input,
273 cursor_index,
274 cursor_char_position,
275 match_start_point,
276 max_return_elements,
277 word_complete,
278 matches);
279 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000280 }
281}