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);
3825d6072aSKate Stone         s->Printf("Try '%shelp' to see a current list of commands.\n", prefix ? prefix : "");
3946d4aa21SEnrico Granata         if (include_apropos)
4046d4aa21SEnrico Granata         {
4125d6072aSKate Stone 	  s->Printf("Try '%sapropos %s' for a list of related commands.\n",
4225d6072aSKate Stone                     prefix ? prefix : "", subcommand ? subcommand : command);
4346d4aa21SEnrico Granata         }
4446d4aa21SEnrico Granata         if (include_type_lookup)
4546d4aa21SEnrico Granata         {
4625d6072aSKate Stone             s->Printf("Try '%stype lookup %s' for information on types, methods, functions, modules, etc.",
4725d6072aSKate Stone 		      prefix ? prefix : "", subcommand ? subcommand : command);
4846d4aa21SEnrico Granata         }
4946d4aa21SEnrico Granata     }
5046d4aa21SEnrico Granata }
5146d4aa21SEnrico Granata 
527428a18cSKate Stone CommandObjectHelp::CommandObjectHelp(CommandInterpreter &interpreter)
537428a18cSKate Stone     : CommandObjectParsed(interpreter, "help",
547428a18cSKate Stone                           "Show a list of all debugger commands, or give details about a specific command.",
557428a18cSKate Stone                           "help [<cmd-name>]"),
56e1cfbc79STodd Fiala       m_options()
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 {
77*ac9c3a62SKate Stone   // clang-format off
7826cac3afSEugene Zelenko   {LLDB_OPT_SET_ALL, false, "hide-aliases",         'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide aliases in the command list."},
7926cac3afSEugene Zelenko   {LLDB_OPT_SET_ALL, false, "hide-user-commands",   'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide user-defined commands from the list."},
8026cac3afSEugene Zelenko   {LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include commands prefixed with an underscore."},
8126cac3afSEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
82*ac9c3a62SKate Stone   // clang-format on
8308633eeaSEnrico Granata };
8408633eeaSEnrico Granata 
8530fdc8d8SChris Lattner bool
865a988416SJim Ingham CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result)
8730fdc8d8SChris Lattner {
8830fdc8d8SChris Lattner     CommandObject::CommandMap::iterator pos;
8930fdc8d8SChris Lattner     CommandObject *cmd_obj;
90c7bece56SGreg Clayton     const size_t argc = command.GetArgumentCount ();
9130fdc8d8SChris Lattner 
9208633eeaSEnrico Granata     // 'help' doesn't take any arguments, other than command names.  If argc is 0, we show the user
9308633eeaSEnrico Granata     // all commands (aliases and user commands if asked for).  Otherwise every argument must be the name of a command or a sub-command.
9430fdc8d8SChris Lattner     if (argc == 0)
9530fdc8d8SChris Lattner     {
9608633eeaSEnrico Granata         uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin;
9708633eeaSEnrico Granata         if (m_options.m_show_aliases)
9808633eeaSEnrico Granata             cmd_types |= CommandInterpreter::eCommandTypesAliases;
9908633eeaSEnrico Granata         if (m_options.m_show_user_defined)
10008633eeaSEnrico Granata             cmd_types |= CommandInterpreter::eCommandTypesUserDef;
101a487aa4cSKate Stone         if (m_options.m_show_hidden)
102a487aa4cSKate Stone             cmd_types |= CommandInterpreter::eCommandTypesHidden;
10308633eeaSEnrico Granata 
10430fdc8d8SChris Lattner         result.SetStatus (eReturnStatusSuccessFinishNoResult);
10508633eeaSEnrico Granata         m_interpreter.GetHelp (result, cmd_types);  // General help
10630fdc8d8SChris Lattner     }
10730fdc8d8SChris Lattner     else
10830fdc8d8SChris Lattner     {
10930fdc8d8SChris Lattner         // Get command object for the first command argument. Only search built-in command dictionary.
110279a6c26SJim Ingham         StringList matches;
111a7015092SGreg Clayton         cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches);
112e7941795SCaroline Tice         bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0));
113e7941795SCaroline Tice         std::string alias_name = command.GetArgumentAtIndex(0);
11430fdc8d8SChris Lattner 
11526cac3afSEugene Zelenko         if (cmd_obj != nullptr)
11630fdc8d8SChris Lattner         {
117271ad29aSJim Ingham             StringList matches;
11830fdc8d8SChris Lattner             bool all_okay = true;
11930fdc8d8SChris Lattner             CommandObject *sub_cmd_obj = cmd_obj;
12030fdc8d8SChris Lattner             // Loop down through sub_command dictionaries until we find the command object that corresponds
12130fdc8d8SChris Lattner             // to the help command entered.
12246d4aa21SEnrico Granata             std::string sub_command;
123a297a97eSAndy Gibbs             for (size_t i = 1; i < argc && all_okay; ++i)
12430fdc8d8SChris Lattner             {
12546d4aa21SEnrico Granata                 sub_command = command.GetArgumentAtIndex(i);
126271ad29aSJim Ingham                 matches.Clear();
127bef55ac8SEnrico Granata                 if (sub_cmd_obj->IsAlias())
128bef55ac8SEnrico Granata                     sub_cmd_obj = ((CommandAlias*)sub_cmd_obj)->GetUnderlyingCommand().get();
12930fdc8d8SChris Lattner                 if (! sub_cmd_obj->IsMultiwordObject ())
13030fdc8d8SChris Lattner                 {
13130fdc8d8SChris Lattner                     all_okay = false;
13230fdc8d8SChris Lattner                 }
13330fdc8d8SChris Lattner                 else
13430fdc8d8SChris Lattner                 {
135271ad29aSJim Ingham                     CommandObject *found_cmd;
136998255bfSGreg Clayton                     found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches);
13726cac3afSEugene Zelenko                     if (found_cmd == nullptr)
13830fdc8d8SChris Lattner                         all_okay = false;
13997253e62SJim Ingham                     else if (matches.GetSize() > 1)
140271ad29aSJim Ingham                         all_okay = false;
141271ad29aSJim Ingham                     else
142271ad29aSJim Ingham                         sub_cmd_obj = found_cmd;
14330fdc8d8SChris Lattner                 }
14430fdc8d8SChris Lattner             }
14530fdc8d8SChris Lattner 
14626cac3afSEugene Zelenko             if (!all_okay || (sub_cmd_obj == nullptr))
14730fdc8d8SChris Lattner             {
14830fdc8d8SChris Lattner                 std::string cmd_string;
14930fdc8d8SChris Lattner                 command.GetCommandString (cmd_string);
1509b62d1d5SEnrico Granata                 if (matches.GetSize() >= 2)
151271ad29aSJim Ingham                 {
152271ad29aSJim Ingham                     StreamString s;
153271ad29aSJim Ingham                     s.Printf ("ambiguous command %s", cmd_string.c_str());
154271ad29aSJim Ingham                     size_t num_matches = matches.GetSize();
155271ad29aSJim Ingham                     for (size_t match_idx = 0; match_idx < num_matches; match_idx++)
156271ad29aSJim Ingham                     {
157271ad29aSJim Ingham                         s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx));
158271ad29aSJim Ingham                     }
159271ad29aSJim Ingham                     s.Printf ("\n");
160271ad29aSJim Ingham                     result.AppendError(s.GetData());
16130fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
1629b62d1d5SEnrico Granata                     return false;
1639b62d1d5SEnrico Granata                 }
1649b62d1d5SEnrico Granata                 else if (!sub_cmd_obj)
1659b62d1d5SEnrico Granata                 {
16646d4aa21SEnrico Granata                     StreamString error_msg_stream;
16746d4aa21SEnrico Granata                     GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
168a487aa4cSKate Stone                                                          cmd_string.c_str(),
16946d4aa21SEnrico Granata                                                          m_interpreter.GetCommandPrefix(),
17046d4aa21SEnrico Granata                                                          sub_command.c_str());
17146d4aa21SEnrico Granata                     result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
1729b62d1d5SEnrico Granata                     result.SetStatus (eReturnStatusFailed);
1739b62d1d5SEnrico Granata                     return false;
17430fdc8d8SChris Lattner                 }
17530fdc8d8SChris Lattner                 else
17630fdc8d8SChris Lattner                 {
17746d4aa21SEnrico Granata                     GenerateAdditionalHelpAvenuesMessage(&result.GetOutputStream(),
1789b62d1d5SEnrico Granata                                                          cmd_string.c_str(),
179a487aa4cSKate Stone                                                          m_interpreter.GetCommandPrefix(),
18046d4aa21SEnrico Granata                                                          sub_command.c_str());
18146d4aa21SEnrico Granata                     result.GetOutputStream().Printf("\nThe closest match is '%s'. Help on it follows.\n\n", sub_cmd_obj->GetCommandName());
182e139cf23SCaroline Tice                 }
183c007e846SJim Ingham             }
184c007e846SJim Ingham 
185998255bfSGreg Clayton             sub_cmd_obj->GenerateHelpText(result);
186e7941795SCaroline Tice 
187e7941795SCaroline Tice             if (is_alias_command)
188e7941795SCaroline Tice             {
189e7941795SCaroline Tice                 StreamString sstr;
1904643c012SEnrico Granata                 m_interpreter.GetAlias(alias_name.c_str())->GetAliasExpansion(sstr);
191e7941795SCaroline Tice                 result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData());
192e7941795SCaroline Tice             }
19330fdc8d8SChris Lattner         }
194279a6c26SJim Ingham         else if (matches.GetSize() > 0)
195279a6c26SJim Ingham         {
196279a6c26SJim Ingham             Stream &output_strm = result.GetOutputStream();
197279a6c26SJim Ingham             output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
198c7bece56SGreg Clayton             const size_t match_count = matches.GetSize();
199c7bece56SGreg Clayton             for (size_t i = 0; i < match_count; i++)
200279a6c26SJim Ingham             {
201279a6c26SJim Ingham                 output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
202279a6c26SJim Ingham             }
203279a6c26SJim Ingham         }
20430fdc8d8SChris Lattner         else
20530fdc8d8SChris Lattner         {
206e139cf23SCaroline Tice             // Maybe the user is asking for help about a command argument rather than a command.
207e139cf23SCaroline Tice             const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0));
208e139cf23SCaroline Tice             if (arg_type != eArgTypeLastArg)
209e139cf23SCaroline Tice             {
210e139cf23SCaroline Tice                 Stream &output_strm = result.GetOutputStream ();
211e139cf23SCaroline Tice                 CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter);
212e139cf23SCaroline Tice                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
213e139cf23SCaroline Tice             }
214e139cf23SCaroline Tice             else
215e139cf23SCaroline Tice             {
21646d4aa21SEnrico Granata                 StreamString error_msg_stream;
21746d4aa21SEnrico Granata                 GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command.GetArgumentAtIndex(0), m_interpreter.GetCommandPrefix());
21846d4aa21SEnrico Granata                 result.AppendErrorWithFormat("%s",error_msg_stream.GetData());
21930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
22030fdc8d8SChris Lattner             }
22130fdc8d8SChris Lattner         }
222e139cf23SCaroline Tice     }
22330fdc8d8SChris Lattner 
22430fdc8d8SChris Lattner     return result.Succeeded();
22530fdc8d8SChris Lattner }
22630fdc8d8SChris Lattner 
22730fdc8d8SChris Lattner int
22826cac3afSEugene Zelenko CommandObjectHelp::HandleCompletion(Args &input,
22930fdc8d8SChris Lattner                                     int &cursor_index,
23030fdc8d8SChris Lattner                                     int &cursor_char_position,
23130fdc8d8SChris Lattner                                     int match_start_point,
23230fdc8d8SChris Lattner                                     int max_return_elements,
233558ce124SJim Ingham                                     bool &word_complete,
23426cac3afSEugene Zelenko                                     StringList &matches)
23530fdc8d8SChris Lattner {
23630fdc8d8SChris Lattner     // Return the completions of the commands in the help system:
23730fdc8d8SChris Lattner     if (cursor_index == 0)
23830fdc8d8SChris Lattner     {
239a7015092SGreg Clayton         return m_interpreter.HandleCompletionMatches (input,
240a7015092SGreg Clayton                                                     cursor_index,
241a7015092SGreg Clayton                                                     cursor_char_position,
242a7015092SGreg Clayton                                                     match_start_point,
243a7015092SGreg Clayton                                                     max_return_elements,
244a7015092SGreg Clayton                                                     word_complete,
245a7015092SGreg Clayton                                                     matches);
24630fdc8d8SChris Lattner     }
24730fdc8d8SChris Lattner     else
24830fdc8d8SChris Lattner     {
249a7015092SGreg Clayton         CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
2501d18ebf6SJim Ingham 
2511d18ebf6SJim Ingham         // The command that they are getting help on might be ambiguous, in which case we should complete that,
2521d18ebf6SJim Ingham         // otherwise complete with the command the user is getting help on...
2531d18ebf6SJim Ingham 
2541d18ebf6SJim Ingham         if (cmd_obj)
2551d18ebf6SJim Ingham         {
25630fdc8d8SChris Lattner             input.Shift();
25730fdc8d8SChris Lattner             cursor_index--;
258a7015092SGreg Clayton             return cmd_obj->HandleCompletion (input,
259a7015092SGreg Clayton                                               cursor_index,
260a7015092SGreg Clayton                                               cursor_char_position,
261a7015092SGreg Clayton                                               match_start_point,
262a7015092SGreg Clayton                                               max_return_elements,
263a7015092SGreg Clayton                                               word_complete,
264a7015092SGreg Clayton                                               matches);
26530fdc8d8SChris Lattner         }
2661d18ebf6SJim Ingham         else
2671d18ebf6SJim Ingham         {
2681d18ebf6SJim Ingham             return m_interpreter.HandleCompletionMatches (input,
2691d18ebf6SJim Ingham                                                         cursor_index,
2701d18ebf6SJim Ingham                                                         cursor_char_position,
2711d18ebf6SJim Ingham                                                         match_start_point,
2721d18ebf6SJim Ingham                                                         max_return_elements,
2731d18ebf6SJim Ingham                                                         word_complete,
2741d18ebf6SJim Ingham                                                         matches);
2751d18ebf6SJim Ingham         }
2761d18ebf6SJim Ingham     }
27730fdc8d8SChris Lattner }
278