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 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 #include "CommandObjectHelp.h" 15 #include "lldb/Interpreter/CommandObjectMultiword.h" 16 #include "lldb/Interpreter/CommandInterpreter.h" 17 #include "lldb/Interpreter/Options.h" 18 #include "lldb/Interpreter/CommandReturnObject.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 //------------------------------------------------------------------------- 24 // CommandObjectHelp 25 //------------------------------------------------------------------------- 26 27 CommandObjectHelp::CommandObjectHelp (CommandInterpreter &interpreter) : 28 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) 32 { 33 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); 45 } 46 47 CommandObjectHelp::~CommandObjectHelp() = default; 48 49 OptionDefinition 50 CommandObjectHelp::CommandOptions::g_option_table[] = 51 { 52 { 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 } 56 }; 57 58 bool 59 CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result) 60 { 61 CommandObject::CommandMap::iterator pos; 62 CommandObject *cmd_obj; 63 const size_t argc = command.GetArgumentCount (); 64 65 // '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. 67 if (argc == 0) 68 { 69 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; 74 if (m_options.m_show_hidden) 75 cmd_types |= CommandInterpreter::eCommandTypesHidden; 76 77 result.SetStatus (eReturnStatusSuccessFinishNoResult); 78 m_interpreter.GetHelp (result, cmd_types); // General help 79 } 80 else 81 { 82 // Get command object for the first command argument. Only search built-in command dictionary. 83 StringList matches; 84 cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches); 85 bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0)); 86 std::string alias_name = command.GetArgumentAtIndex(0); 87 88 if (cmd_obj != nullptr) 89 { 90 StringList matches; 91 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. 95 for (size_t i = 1; i < argc && all_okay; ++i) 96 { 97 std::string sub_command = command.GetArgumentAtIndex(i); 98 matches.Clear(); 99 if (! sub_cmd_obj->IsMultiwordObject ()) 100 { 101 all_okay = false; 102 } 103 else 104 { 105 CommandObject *found_cmd; 106 found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches); 107 if (found_cmd == nullptr) 108 all_okay = false; 109 else if (matches.GetSize() > 1) 110 all_okay = false; 111 else 112 sub_cmd_obj = found_cmd; 113 } 114 } 115 116 if (!all_okay || (sub_cmd_obj == nullptr)) 117 { 118 std::string cmd_string; 119 command.GetCommandString (cmd_string); 120 if (matches.GetSize() >= 2) 121 { 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()); 131 result.SetStatus (eReturnStatusFailed); 132 return false; 133 } 134 else if (!sub_cmd_obj) 135 { 136 result.AppendErrorWithFormat("'%s' is not a known command.\n" 137 "Try '%shelp' to see a current list of commands.\n", 138 cmd_string.c_str(), 139 m_interpreter.GetCommandPrefix()); 140 result.SetStatus (eReturnStatusFailed); 141 return false; 142 } 143 else 144 { 145 result.GetOutputStream().Printf("'%s' is not a known command.\n" 146 "Try '%shelp' to see a current list of commands.\n" 147 "The closest match is '%s'. Help on it follows.\n\n", 148 cmd_string.c_str(), 149 m_interpreter.GetCommandPrefix(), 150 sub_cmd_obj->GetCommandName()); 151 } 152 } 153 154 sub_cmd_obj->GenerateHelpText(result); 155 156 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 } 162 } 163 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"); 167 const size_t match_count = matches.GetSize(); 168 for (size_t i = 0; i < match_count; i++) 169 { 170 output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i)); 171 } 172 } 173 else 174 { 175 // 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 186 ("'%s' is not a known command.\nTry '%shelp' to see a current list of commands.\n", 187 command.GetArgumentAtIndex(0), 188 m_interpreter.GetCommandPrefix()); 189 result.SetStatus (eReturnStatusFailed); 190 } 191 } 192 } 193 194 return result.Succeeded(); 195 } 196 197 int 198 CommandObjectHelp::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) 205 { 206 // Return the completions of the commands in the help system: 207 if (cursor_index == 0) 208 { 209 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); 216 } 217 else 218 { 219 CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0)); 220 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 } 246 } 247 } 248