130fdc8d8SChris Lattner //===-- CommandObjectHelp.cpp -----------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner // C Includes
1130fdc8d8SChris Lattner // C++ Includes
1230fdc8d8SChris Lattner // Other libraries and framework includes
1330fdc8d8SChris Lattner // Project includes
1426cac3afSEugene Zelenko #include "CommandObjectHelp.h"
1530fdc8d8SChris Lattner #include "lldb/Interpreter/CommandObjectMultiword.h"
1630fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
1740af72e1SJim Ingham #include "lldb/Interpreter/Options.h"
1830fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
1930fdc8d8SChris Lattner 
2030fdc8d8SChris Lattner using namespace lldb;
2130fdc8d8SChris Lattner using namespace lldb_private;
2230fdc8d8SChris Lattner 
2330fdc8d8SChris Lattner //-------------------------------------------------------------------------
2430fdc8d8SChris Lattner // CommandObjectHelp
2530fdc8d8SChris Lattner //-------------------------------------------------------------------------
2630fdc8d8SChris Lattner 
2746d4aa21SEnrico Granata void
2846d4aa21SEnrico Granata CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage (Stream *s,
2946d4aa21SEnrico Granata                                                          const char* command,
3046d4aa21SEnrico Granata                                                          const char* prefix,
3146d4aa21SEnrico Granata                                                          const char* subcommand,
3246d4aa21SEnrico Granata                                                          bool include_apropos,
3346d4aa21SEnrico Granata                                                          bool include_type_lookup)
3446d4aa21SEnrico Granata {
3546d4aa21SEnrico Granata     if (s && command && *command)
3646d4aa21SEnrico Granata     {
3746d4aa21SEnrico Granata         s->Printf("'%s' is not a known command.\n", command);
38*25d6072aSKate Stone         s->Printf("Try '%shelp' to see a current list of commands.\n", prefix ? prefix : "");
3946d4aa21SEnrico Granata         if (include_apropos)
4046d4aa21SEnrico Granata         {
41*25d6072aSKate Stone 	  s->Printf("Try '%sapropos %s' for a list of related commands.\n",
42*25d6072aSKate Stone                     prefix ? prefix : "", subcommand ? subcommand : command);
4346d4aa21SEnrico Granata         }
4446d4aa21SEnrico Granata         if (include_type_lookup)
4546d4aa21SEnrico Granata         {
46*25d6072aSKate Stone             s->Printf("Try '%stype lookup %s' for information on types, methods, functions, modules, etc.",
47*25d6072aSKate Stone 		      prefix ? prefix : "", subcommand ? subcommand : command);
4846d4aa21SEnrico Granata         }
4946d4aa21SEnrico Granata     }
5046d4aa21SEnrico Granata }
5146d4aa21SEnrico Granata 
52a7015092SGreg Clayton CommandObjectHelp::CommandObjectHelp (CommandInterpreter &interpreter) :
535a988416SJim Ingham     CommandObjectParsed (interpreter,
54a7015092SGreg Clayton                          "help",
553f4c09c1SCaroline Tice                          "Show a list of all debugger commands, or give details about specific commands.",
5608633eeaSEnrico Granata                          "help [<cmd-name>]"), m_options (interpreter)
5730fdc8d8SChris Lattner {
58405fe67fSCaroline Tice     CommandArgumentEntry arg;
59405fe67fSCaroline Tice     CommandArgumentData command_arg;
60405fe67fSCaroline Tice 
61405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
62405fe67fSCaroline Tice     command_arg.arg_type = eArgTypeCommandName;
63405fe67fSCaroline Tice     command_arg.arg_repetition = eArgRepeatStar;
64405fe67fSCaroline Tice 
65405fe67fSCaroline Tice     // There is only one variant this argument could be; put it into the argument entry.
66405fe67fSCaroline Tice     arg.push_back (command_arg);
67405fe67fSCaroline Tice 
68405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
69405fe67fSCaroline Tice     m_arguments.push_back (arg);
7030fdc8d8SChris Lattner }
7130fdc8d8SChris Lattner 
7226cac3afSEugene Zelenko CommandObjectHelp::~CommandObjectHelp() = default;
7330fdc8d8SChris Lattner 
7408633eeaSEnrico Granata OptionDefinition
7508633eeaSEnrico Granata CommandObjectHelp::CommandOptions::g_option_table[] =
7608633eeaSEnrico Granata {
7726cac3afSEugene Zelenko     { LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,         "Hide aliases in the command list."},
7826cac3afSEugene Zelenko     { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,         "Hide user-defined commands from the list."},
7926cac3afSEugene Zelenko     { LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,         "Include commands prefixed with an underscore."},
8026cac3afSEugene Zelenko     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
8108633eeaSEnrico Granata };
8208633eeaSEnrico Granata 
8330fdc8d8SChris Lattner bool
845a988416SJim Ingham CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
8530fdc8d8SChris Lattner {
8630fdc8d8SChris Lattner     CommandObject::CommandMap::iterator pos;
8730fdc8d8SChris Lattner     CommandObject *cmd_obj;
88c7bece56SGreg Clayton     const size_t argc = command.GetArgumentCount ();
8930fdc8d8SChris Lattner 
9008633eeaSEnrico Granata     // 'help' doesn't take any arguments, other than command names.  If argc is 0, we show the user
9108633eeaSEnrico Granata     // all commands (aliases and user commands if asked for).  Otherwise every argument must be the name of a command or a sub-command.
9230fdc8d8SChris Lattner     if (argc == 0)
9330fdc8d8SChris Lattner     {
9408633eeaSEnrico Granata         uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin;
9508633eeaSEnrico Granata         if (m_options.m_show_aliases)
9608633eeaSEnrico Granata             cmd_types |= CommandInterpreter::eCommandTypesAliases;
9708633eeaSEnrico Granata         if (m_options.m_show_user_defined)
9808633eeaSEnrico Granata             cmd_types |= CommandInterpreter::eCommandTypesUserDef;
99a487aa4cSKate Stone         if (m_options.m_show_hidden)
100a487aa4cSKate Stone             cmd_types |= CommandInterpreter::eCommandTypesHidden;
10108633eeaSEnrico Granata 
10230fdc8d8SChris Lattner         result.SetStatus (eReturnStatusSuccessFinishNoResult);
10308633eeaSEnrico Granata         m_interpreter.GetHelp (result, cmd_types);  // General help
10430fdc8d8SChris Lattner     }
10530fdc8d8SChris Lattner     else
10630fdc8d8SChris Lattner     {
10730fdc8d8SChris Lattner         // Get command object for the first command argument. Only search built-in command dictionary.
108279a6c26SJim Ingham         StringList matches;
109a7015092SGreg Clayton         cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches);
110e7941795SCaroline Tice         bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0));
111e7941795SCaroline Tice         std::string alias_name = command.GetArgumentAtIndex(0);
11230fdc8d8SChris Lattner 
11326cac3afSEugene Zelenko         if (cmd_obj != nullptr)
11430fdc8d8SChris Lattner         {
115271ad29aSJim Ingham             StringList matches;
11630fdc8d8SChris Lattner             bool all_okay = true;
11730fdc8d8SChris Lattner             CommandObject *sub_cmd_obj = cmd_obj;
11830fdc8d8SChris Lattner             // Loop down through sub_command dictionaries until we find the command object that corresponds
11930fdc8d8SChris Lattner             // to the help command entered.
12046d4aa21SEnrico Granata             std::string sub_command;
121a297a97eSAndy Gibbs             for (size_t i = 1; i < argc && all_okay; ++i)
12230fdc8d8SChris Lattner             {
12346d4aa21SEnrico Granata                 sub_command = command.GetArgumentAtIndex(i);
124271ad29aSJim Ingham                 matches.Clear();
125bef55ac8SEnrico Granata                 if (sub_cmd_obj->IsAlias())
126bef55ac8SEnrico Granata                     sub_cmd_obj = ((CommandAlias*)sub_cmd_obj)->GetUnderlyingCommand().get();
12730fdc8d8SChris Lattner                 if (! sub_cmd_obj->IsMultiwordObject ())
12830fdc8d8SChris Lattner                 {
12930fdc8d8SChris Lattner                     all_okay = false;
13030fdc8d8SChris Lattner                 }
13130fdc8d8SChris Lattner                 else
13230fdc8d8SChris Lattner                 {
133271ad29aSJim Ingham                     CommandObject *found_cmd;
134998255bfSGreg Clayton                     found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches);
13526cac3afSEugene Zelenko                     if (found_cmd == nullptr)
13630fdc8d8SChris Lattner                         all_okay = false;
13797253e62SJim Ingham                     else if (matches.GetSize() > 1)
138271ad29aSJim Ingham                         all_okay = false;
139271ad29aSJim Ingham                     else
140271ad29aSJim Ingham                         sub_cmd_obj = found_cmd;
14130fdc8d8SChris Lattner                 }
14230fdc8d8SChris Lattner             }
14330fdc8d8SChris Lattner 
14426cac3afSEugene Zelenko             if (!all_okay || (sub_cmd_obj == nullptr))
14530fdc8d8SChris Lattner             {
14630fdc8d8SChris Lattner                 std::string cmd_string;
14730fdc8d8SChris Lattner                 command.GetCommandString (cmd_string);
1489b62d1d5SEnrico Granata                 if (matches.GetSize() >= 2)
149271ad29aSJim Ingham                 {
150271ad29aSJim Ingham                     StreamString s;
151271ad29aSJim Ingham                     s.Printf ("ambiguous command %s", cmd_string.c_str());
152271ad29aSJim Ingham                     size_t num_matches = matches.GetSize();
153271ad29aSJim Ingham                     for (size_t match_idx = 0; match_idx < num_matches; match_idx++)
154271ad29aSJim Ingham                     {
155271ad29aSJim Ingham                         s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx));
156271ad29aSJim Ingham                     }
157271ad29aSJim Ingham                     s.Printf ("\n");
158271ad29aSJim Ingham                     result.AppendError(s.GetData());
15930fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
1609b62d1d5SEnrico Granata                     return false;
1619b62d1d5SEnrico Granata                 }
1629b62d1d5SEnrico Granata                 else if (!sub_cmd_obj)
1639b62d1d5SEnrico Granata                 {
16446d4aa21SEnrico Granata                     StreamString error_msg_stream;
16546d4aa21SEnrico Granata                     GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
166a487aa4cSKate Stone                                                          cmd_string.c_str(),
16746d4aa21SEnrico Granata                                                          m_interpreter.GetCommandPrefix(),
16846d4aa21SEnrico Granata                                                          sub_command.c_str());
16946d4aa21SEnrico Granata                     result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
1709b62d1d5SEnrico Granata                     result.SetStatus (eReturnStatusFailed);
1719b62d1d5SEnrico Granata                     return false;
17230fdc8d8SChris Lattner                 }
17330fdc8d8SChris Lattner                 else
17430fdc8d8SChris Lattner                 {
17546d4aa21SEnrico Granata                     GenerateAdditionalHelpAvenuesMessage(&result.GetOutputStream(),
1769b62d1d5SEnrico Granata                                                          cmd_string.c_str(),
177a487aa4cSKate Stone                                                          m_interpreter.GetCommandPrefix(),
17846d4aa21SEnrico Granata                                                          sub_command.c_str());
17946d4aa21SEnrico Granata                     result.GetOutputStream().Printf("\nThe closest match is '%s'. Help on it follows.\n\n", sub_cmd_obj->GetCommandName());
180e139cf23SCaroline Tice                 }
181c007e846SJim Ingham             }
182c007e846SJim Ingham 
183998255bfSGreg Clayton             sub_cmd_obj->GenerateHelpText(result);
184e7941795SCaroline Tice 
185e7941795SCaroline Tice             if (is_alias_command)
186e7941795SCaroline Tice             {
187e7941795SCaroline Tice                 StreamString sstr;
1884643c012SEnrico Granata                 m_interpreter.GetAlias(alias_name.c_str())->GetAliasExpansion(sstr);
189e7941795SCaroline Tice                 result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData());
190e7941795SCaroline Tice             }
19130fdc8d8SChris Lattner         }
192279a6c26SJim Ingham         else if (matches.GetSize() > 0)
193279a6c26SJim Ingham         {
194279a6c26SJim Ingham             Stream &output_strm = result.GetOutputStream();
195279a6c26SJim Ingham             output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
196c7bece56SGreg Clayton             const size_t match_count = matches.GetSize();
197c7bece56SGreg Clayton             for (size_t i = 0; i < match_count; i++)
198279a6c26SJim Ingham             {
199279a6c26SJim Ingham                 output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
200279a6c26SJim Ingham             }
201279a6c26SJim Ingham         }
20230fdc8d8SChris Lattner         else
20330fdc8d8SChris Lattner         {
204e139cf23SCaroline Tice             // Maybe the user is asking for help about a command argument rather than a command.
205e139cf23SCaroline Tice             const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0));
206e139cf23SCaroline Tice             if (arg_type != eArgTypeLastArg)
207e139cf23SCaroline Tice             {
208e139cf23SCaroline Tice                 Stream &output_strm = result.GetOutputStream ();
209e139cf23SCaroline Tice                 CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter);
210e139cf23SCaroline Tice                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
211e139cf23SCaroline Tice             }
212e139cf23SCaroline Tice             else
213e139cf23SCaroline Tice             {
21446d4aa21SEnrico Granata                 StreamString error_msg_stream;
21546d4aa21SEnrico Granata                 GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command.GetArgumentAtIndex(0), m_interpreter.GetCommandPrefix());
21646d4aa21SEnrico Granata                 result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
21730fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
21830fdc8d8SChris Lattner             }
21930fdc8d8SChris Lattner         }
220e139cf23SCaroline Tice     }
22130fdc8d8SChris Lattner 
22230fdc8d8SChris Lattner     return result.Succeeded();
22330fdc8d8SChris Lattner }
22430fdc8d8SChris Lattner 
22530fdc8d8SChris Lattner int
22626cac3afSEugene Zelenko CommandObjectHelp::HandleCompletion(Args &input,
22730fdc8d8SChris Lattner                                     int &cursor_index,
22830fdc8d8SChris Lattner                                     int &cursor_char_position,
22930fdc8d8SChris Lattner                                     int match_start_point,
23030fdc8d8SChris Lattner                                     int max_return_elements,
231558ce124SJim Ingham                                     bool &word_complete,
23226cac3afSEugene Zelenko                                     StringList &matches)
23330fdc8d8SChris Lattner {
23430fdc8d8SChris Lattner     // Return the completions of the commands in the help system:
23530fdc8d8SChris Lattner     if (cursor_index == 0)
23630fdc8d8SChris Lattner     {
237a7015092SGreg Clayton         return m_interpreter.HandleCompletionMatches (input,
238a7015092SGreg Clayton                                                     cursor_index,
239a7015092SGreg Clayton                                                     cursor_char_position,
240a7015092SGreg Clayton                                                     match_start_point,
241a7015092SGreg Clayton                                                     max_return_elements,
242a7015092SGreg Clayton                                                     word_complete,
243a7015092SGreg Clayton                                                     matches);
24430fdc8d8SChris Lattner     }
24530fdc8d8SChris Lattner     else
24630fdc8d8SChris Lattner     {
247a7015092SGreg Clayton         CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
2481d18ebf6SJim Ingham 
2491d18ebf6SJim Ingham         // The command that they are getting help on might be ambiguous, in which case we should complete that,
2501d18ebf6SJim Ingham         // otherwise complete with the command the user is getting help on...
2511d18ebf6SJim Ingham 
2521d18ebf6SJim Ingham         if (cmd_obj)
2531d18ebf6SJim Ingham         {
25430fdc8d8SChris Lattner             input.Shift();
25530fdc8d8SChris Lattner             cursor_index--;
256a7015092SGreg Clayton             return cmd_obj->HandleCompletion (input,
257a7015092SGreg Clayton                                               cursor_index,
258a7015092SGreg Clayton                                               cursor_char_position,
259a7015092SGreg Clayton                                               match_start_point,
260a7015092SGreg Clayton                                               max_return_elements,
261a7015092SGreg Clayton                                               word_complete,
262a7015092SGreg Clayton                                               matches);
26330fdc8d8SChris Lattner         }
2641d18ebf6SJim Ingham         else
2651d18ebf6SJim Ingham         {
2661d18ebf6SJim Ingham             return m_interpreter.HandleCompletionMatches (input,
2671d18ebf6SJim Ingham                                                         cursor_index,
2681d18ebf6SJim Ingham                                                         cursor_char_position,
2691d18ebf6SJim Ingham                                                         match_start_point,
2701d18ebf6SJim Ingham                                                         max_return_elements,
2711d18ebf6SJim Ingham                                                         word_complete,
2721d18ebf6SJim Ingham                                                         matches);
2731d18ebf6SJim Ingham         }
2741d18ebf6SJim Ingham     }
27530fdc8d8SChris Lattner }
276