blob: 14d1ae5a0b4327b95dde3e6d8c46a141fa5b389e [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
Greg Claytona7015092010-09-18 01:14:36 +000027CommandObjectHelp::CommandObjectHelp (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +000028 CommandObjectParsed (interpreter,
29 "help",
30 "Show a list of all debugger commands, or give details about specific commands.",
31 "help [<cmd-name>]"), m_options (interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032{
Caroline Tice405fe672010-10-04 22:28:36 +000033 CommandArgumentEntry arg;
34 CommandArgumentData command_arg;
35
36 // Define the first (and only) variant of this arg.
37 command_arg.arg_type = eArgTypeCommandName;
38 command_arg.arg_repetition = eArgRepeatStar;
39
40 // There is only one variant this argument could be; put it into the argument entry.
41 arg.push_back (command_arg);
42
43 // Push the data for the first argument into the m_arguments vector.
44 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000045}
46
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000047CommandObjectHelp::~CommandObjectHelp() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048
Enrico Granata08633ee2011-09-09 17:49:36 +000049OptionDefinition
50CommandObjectHelp::CommandOptions::g_option_table[] =
51{
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000052 { LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide aliases in the command list."},
53 { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide user-defined commands from the list."},
54 { LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include commands prefixed with an underscore."},
55 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Enrico Granata08633ee2011-09-09 17:49:36 +000056};
57
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058bool
Jim Ingham5a988412012-06-08 21:56:10 +000059CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000060{
61 CommandObject::CommandMap::iterator pos;
62 CommandObject *cmd_obj;
Greg Claytonc7bece562013-01-25 18:06:21 +000063 const size_t argc = command.GetArgumentCount ();
Greg Clayton66111032010-06-23 01:19:29 +000064
Enrico Granata08633ee2011-09-09 17:49:36 +000065 // 'help' doesn't take any arguments, other than command names. If argc is 0, we show the user
66 // 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 +000067 if (argc == 0)
68 {
Enrico Granata08633ee2011-09-09 17:49:36 +000069 uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin;
70 if (m_options.m_show_aliases)
71 cmd_types |= CommandInterpreter::eCommandTypesAliases;
72 if (m_options.m_show_user_defined)
73 cmd_types |= CommandInterpreter::eCommandTypesUserDef;
Kate Stonea487aa42015-01-15 00:52:41 +000074 if (m_options.m_show_hidden)
75 cmd_types |= CommandInterpreter::eCommandTypesHidden;
Enrico Granata08633ee2011-09-09 17:49:36 +000076
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Enrico Granata08633ee2011-09-09 17:49:36 +000078 m_interpreter.GetHelp (result, cmd_types); // General help
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079 }
80 else
81 {
82 // Get command object for the first command argument. Only search built-in command dictionary.
Jim Ingham279a6c22010-07-06 22:46:59 +000083 StringList matches;
Greg Claytona7015092010-09-18 01:14:36 +000084 cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches);
Caroline Ticee7941792010-10-28 23:17:48 +000085 bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0));
86 std::string alias_name = command.GetArgumentAtIndex(0);
Greg Clayton66111032010-06-23 01:19:29 +000087
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000088 if (cmd_obj != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089 {
Jim Ingham271ad292010-11-30 22:59:37 +000090 StringList matches;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091 bool all_okay = true;
92 CommandObject *sub_cmd_obj = cmd_obj;
93 // Loop down through sub_command dictionaries until we find the command object that corresponds
94 // to the help command entered.
Andy Gibbsa297a972013-06-19 19:04:53 +000095 for (size_t i = 1; i < argc && all_okay; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096 {
97 std::string sub_command = command.GetArgumentAtIndex(i);
Jim Ingham271ad292010-11-30 22:59:37 +000098 matches.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099 if (! sub_cmd_obj->IsMultiwordObject ())
100 {
101 all_okay = false;
102 }
103 else
104 {
Jim Ingham271ad292010-11-30 22:59:37 +0000105 CommandObject *found_cmd;
Greg Clayton998255b2012-10-13 02:07:45 +0000106 found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches);
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000107 if (found_cmd == nullptr)
Greg Clayton66111032010-06-23 01:19:29 +0000108 all_okay = false;
Jim Ingham97253e62010-12-01 00:42:17 +0000109 else if (matches.GetSize() > 1)
Jim Ingham271ad292010-11-30 22:59:37 +0000110 all_okay = false;
111 else
112 sub_cmd_obj = found_cmd;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113 }
114 }
Greg Clayton66111032010-06-23 01:19:29 +0000115
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000116 if (!all_okay || (sub_cmd_obj == nullptr))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 {
118 std::string cmd_string;
119 command.GetCommandString (cmd_string);
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000120 if (matches.GetSize() >= 2)
Jim Ingham271ad292010-11-30 22:59:37 +0000121 {
122 StreamString s;
123 s.Printf ("ambiguous command %s", cmd_string.c_str());
124 size_t num_matches = matches.GetSize();
125 for (size_t match_idx = 0; match_idx < num_matches; match_idx++)
126 {
127 s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx));
128 }
129 s.Printf ("\n");
130 result.AppendError(s.GetData());
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000131 result.SetStatus (eReturnStatusFailed);
132 return false;
Jim Ingham271ad292010-11-30 22:59:37 +0000133 }
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000134 else if (!sub_cmd_obj)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000135 {
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000136 result.AppendErrorWithFormat("'%s' is not a known command.\n"
Kate Stonea487aa42015-01-15 00:52:41 +0000137 "Try '%shelp' to see a current list of commands.\n",
138 cmd_string.c_str(),
139 m_interpreter.GetCommandPrefix());
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000140 result.SetStatus (eReturnStatusFailed);
141 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000142 }
143 else
144 {
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000145 result.GetOutputStream().Printf("'%s' is not a known command.\n"
Kate Stonea487aa42015-01-15 00:52:41 +0000146 "Try '%shelp' to see a current list of commands.\n"
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000147 "The closest match is '%s'. Help on it follows.\n\n",
148 cmd_string.c_str(),
Kate Stonea487aa42015-01-15 00:52:41 +0000149 m_interpreter.GetCommandPrefix(),
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000150 sub_cmd_obj->GetCommandName());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151 }
152 }
Caroline Ticee7941792010-10-28 23:17:48 +0000153
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000154 sub_cmd_obj->GenerateHelpText(result);
155
Caroline Ticee7941792010-10-28 23:17:48 +0000156 if (is_alias_command)
157 {
158 StreamString sstr;
159 m_interpreter.GetAliasHelp (alias_name.c_str(), cmd_obj->GetCommandName(), sstr);
160 result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData());
161 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162 }
Jim Ingham279a6c22010-07-06 22:46:59 +0000163 else if (matches.GetSize() > 0)
164 {
165 Stream &output_strm = result.GetOutputStream();
166 output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
Greg Claytonc7bece562013-01-25 18:06:21 +0000167 const size_t match_count = matches.GetSize();
168 for (size_t i = 0; i < match_count; i++)
Jim Ingham279a6c22010-07-06 22:46:59 +0000169 {
170 output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
171 }
172 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 else
174 {
Caroline Ticee139cf22010-10-01 17:46:38 +0000175 // Maybe the user is asking for help about a command argument rather than a command.
176 const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0));
177 if (arg_type != eArgTypeLastArg)
178 {
179 Stream &output_strm = result.GetOutputStream ();
180 CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter);
181 result.SetStatus (eReturnStatusSuccessFinishNoResult);
182 }
183 else
184 {
185 result.AppendErrorWithFormat
Kate Stonea487aa42015-01-15 00:52:41 +0000186 ("'%s' is not a known command.\nTry '%shelp' to see a current list of commands.\n",
187 command.GetArgumentAtIndex(0),
188 m_interpreter.GetCommandPrefix());
Caroline Ticee139cf22010-10-01 17:46:38 +0000189 result.SetStatus (eReturnStatusFailed);
190 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 }
192 }
Greg Clayton66111032010-06-23 01:19:29 +0000193
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194 return result.Succeeded();
195}
196
197int
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000198CommandObjectHelp::HandleCompletion(Args &input,
199 int &cursor_index,
200 int &cursor_char_position,
201 int match_start_point,
202 int max_return_elements,
203 bool &word_complete,
204 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205{
206 // Return the completions of the commands in the help system:
207 if (cursor_index == 0)
208 {
Greg Claytona7015092010-09-18 01:14:36 +0000209 return m_interpreter.HandleCompletionMatches (input,
210 cursor_index,
211 cursor_char_position,
212 match_start_point,
213 max_return_elements,
214 word_complete,
215 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000216 }
217 else
218 {
Greg Claytona7015092010-09-18 01:14:36 +0000219 CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
Jim Ingham1d18ebf2011-10-26 19:32:01 +0000220
221 // The command that they are getting help on might be ambiguous, in which case we should complete that,
222 // otherwise complete with the command the user is getting help on...
223
224 if (cmd_obj)
225 {
226 input.Shift();
227 cursor_index--;
228 return cmd_obj->HandleCompletion (input,
229 cursor_index,
230 cursor_char_position,
231 match_start_point,
232 max_return_elements,
233 word_complete,
234 matches);
235 }
236 else
237 {
238 return m_interpreter.HandleCompletionMatches (input,
239 cursor_index,
240 cursor_char_position,
241 match_start_point,
242 max_return_elements,
243 word_complete,
244 matches);
245 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246 }
247}