1 //===-- 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
10 #include "CommandObjectHelp.h"
11
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Interpreter/CommandObjectMultiword.h"
17 #include "lldb/Interpreter/CommandInterpreter.h"
18 #include "lldb/Interpreter/Options.h"
19 #include "lldb/Interpreter/CommandReturnObject.h"
20
21 using namespace lldb;
22 using namespace lldb_private;
23
24 //-------------------------------------------------------------------------
25 // CommandObjectHelp
26 //-------------------------------------------------------------------------
27
CommandObjectHelp(CommandInterpreter & interpreter)28 CommandObjectHelp::CommandObjectHelp (CommandInterpreter &interpreter) :
29 CommandObjectParsed (interpreter,
30 "help",
31 "Show a list of all debugger commands, or give details about specific commands.",
32 "help [<cmd-name>]"), m_options (interpreter)
33 {
34 CommandArgumentEntry arg;
35 CommandArgumentData command_arg;
36
37 // Define the first (and only) variant of this arg.
38 command_arg.arg_type = eArgTypeCommandName;
39 command_arg.arg_repetition = eArgRepeatStar;
40
41 // There is only one variant this argument could be; put it into the argument entry.
42 arg.push_back (command_arg);
43
44 // Push the data for the first argument into the m_arguments vector.
45 m_arguments.push_back (arg);
46 }
47
~CommandObjectHelp()48 CommandObjectHelp::~CommandObjectHelp()
49 {
50 }
51
52 OptionDefinition
53 CommandObjectHelp::CommandOptions::g_option_table[] =
54 {
55 { LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Hide aliases in the command list."},
56 { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Hide user-defined commands from the list."},
57 { LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Include commands prefixed with an underscore."},
58 { 0, false, NULL, 0, 0, 0, NULL, 0, eArgTypeNone, NULL }
59 };
60
61 bool
DoExecute(Args & command,CommandReturnObject & result)62 CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
63 {
64 CommandObject::CommandMap::iterator pos;
65 CommandObject *cmd_obj;
66 const size_t argc = command.GetArgumentCount ();
67
68 // 'help' doesn't take any arguments, other than command names. If argc is 0, we show the user
69 // all commands (aliases and user commands if asked for). Otherwise every argument must be the name of a command or a sub-command.
70 if (argc == 0)
71 {
72 uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin;
73 if (m_options.m_show_aliases)
74 cmd_types |= CommandInterpreter::eCommandTypesAliases;
75 if (m_options.m_show_user_defined)
76 cmd_types |= CommandInterpreter::eCommandTypesUserDef;
77 if (m_options.m_show_hidden)
78 cmd_types |= CommandInterpreter::eCommandTypesHidden;
79
80 result.SetStatus (eReturnStatusSuccessFinishNoResult);
81 m_interpreter.GetHelp (result, cmd_types); // General help
82 }
83 else
84 {
85 // Get command object for the first command argument. Only search built-in command dictionary.
86 StringList matches;
87 cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches);
88 bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0));
89 std::string alias_name = command.GetArgumentAtIndex(0);
90
91 if (cmd_obj != NULL)
92 {
93 StringList matches;
94 bool all_okay = true;
95 CommandObject *sub_cmd_obj = cmd_obj;
96 // Loop down through sub_command dictionaries until we find the command object that corresponds
97 // to the help command entered.
98 for (size_t i = 1; i < argc && all_okay; ++i)
99 {
100 std::string sub_command = command.GetArgumentAtIndex(i);
101 matches.Clear();
102 if (! sub_cmd_obj->IsMultiwordObject ())
103 {
104 all_okay = false;
105 }
106 else
107 {
108 CommandObject *found_cmd;
109 found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches);
110 if (found_cmd == NULL)
111 all_okay = false;
112 else if (matches.GetSize() > 1)
113 all_okay = false;
114 else
115 sub_cmd_obj = found_cmd;
116 }
117 }
118
119 if (!all_okay || (sub_cmd_obj == NULL))
120 {
121 std::string cmd_string;
122 command.GetCommandString (cmd_string);
123 if (matches.GetSize() >= 2)
124 {
125 StreamString s;
126 s.Printf ("ambiguous command %s", cmd_string.c_str());
127 size_t num_matches = matches.GetSize();
128 for (size_t match_idx = 0; match_idx < num_matches; match_idx++)
129 {
130 s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx));
131 }
132 s.Printf ("\n");
133 result.AppendError(s.GetData());
134 result.SetStatus (eReturnStatusFailed);
135 return false;
136 }
137 else if (!sub_cmd_obj)
138 {
139 result.AppendErrorWithFormat("'%s' is not a known command.\n"
140 "Try '%shelp' to see a current list of commands.\n",
141 cmd_string.c_str(),
142 m_interpreter.GetCommandPrefix());
143 result.SetStatus (eReturnStatusFailed);
144 return false;
145 }
146 else
147 {
148 result.GetOutputStream().Printf("'%s' is not a known command.\n"
149 "Try '%shelp' to see a current list of commands.\n"
150 "The closest match is '%s'. Help on it follows.\n\n",
151 cmd_string.c_str(),
152 m_interpreter.GetCommandPrefix(),
153 sub_cmd_obj->GetCommandName());
154 }
155 }
156
157 sub_cmd_obj->GenerateHelpText(result);
158
159 if (is_alias_command)
160 {
161 StreamString sstr;
162 m_interpreter.GetAliasHelp (alias_name.c_str(), cmd_obj->GetCommandName(), sstr);
163 result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData());
164 }
165 }
166 else if (matches.GetSize() > 0)
167 {
168 Stream &output_strm = result.GetOutputStream();
169 output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
170 const size_t match_count = matches.GetSize();
171 for (size_t i = 0; i < match_count; i++)
172 {
173 output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
174 }
175 }
176 else
177 {
178 // Maybe the user is asking for help about a command argument rather than a command.
179 const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0));
180 if (arg_type != eArgTypeLastArg)
181 {
182 Stream &output_strm = result.GetOutputStream ();
183 CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter);
184 result.SetStatus (eReturnStatusSuccessFinishNoResult);
185 }
186 else
187 {
188 result.AppendErrorWithFormat
189 ("'%s' is not a known command.\nTry '%shelp' to see a current list of commands.\n",
190 command.GetArgumentAtIndex(0),
191 m_interpreter.GetCommandPrefix());
192 result.SetStatus (eReturnStatusFailed);
193 }
194 }
195 }
196
197 return result.Succeeded();
198 }
199
200 int
HandleCompletion(Args & input,int & cursor_index,int & cursor_char_position,int match_start_point,int max_return_elements,bool & word_complete,StringList & matches)201 CommandObjectHelp::HandleCompletion
202 (
203 Args &input,
204 int &cursor_index,
205 int &cursor_char_position,
206 int match_start_point,
207 int max_return_elements,
208 bool &word_complete,
209 StringList &matches
210 )
211 {
212 // Return the completions of the commands in the help system:
213 if (cursor_index == 0)
214 {
215 return m_interpreter.HandleCompletionMatches (input,
216 cursor_index,
217 cursor_char_position,
218 match_start_point,
219 max_return_elements,
220 word_complete,
221 matches);
222 }
223 else
224 {
225 CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
226
227 // The command that they are getting help on might be ambiguous, in which case we should complete that,
228 // otherwise complete with the command the user is getting help on...
229
230 if (cmd_obj)
231 {
232 input.Shift();
233 cursor_index--;
234 return cmd_obj->HandleCompletion (input,
235 cursor_index,
236 cursor_char_position,
237 match_start_point,
238 max_return_elements,
239 word_complete,
240 matches);
241 }
242 else
243 {
244 return m_interpreter.HandleCompletionMatches (input,
245 cursor_index,
246 cursor_char_position,
247 match_start_point,
248 max_return_elements,
249 word_complete,
250 matches);
251 }
252 }
253 }
254