1 //===-- CommandObjectApropos.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 "CommandObjectApropos.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Interpreter/Args.h"
17 #include "lldb/Interpreter/Options.h"
18 #include "lldb/Interpreter/Property.h"
19 
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 //-------------------------------------------------------------------------
27 // CommandObjectApropos
28 //-------------------------------------------------------------------------
29 
30 CommandObjectApropos::CommandObjectApropos (CommandInterpreter &interpreter) :
31     CommandObjectParsed (interpreter,
32                          "apropos",
33                          "Find a list of debugger commands related to a particular word/subject.",
34                          NULL)
35 {
36     CommandArgumentEntry arg;
37     CommandArgumentData search_word_arg;
38 
39     // Define the first (and only) variant of this arg.
40     search_word_arg.arg_type = eArgTypeSearchWord;
41     search_word_arg.arg_repetition = eArgRepeatPlain;
42 
43     // There is only one variant this argument could be; put it into the argument entry.
44     arg.push_back (search_word_arg);
45 
46     // Push the data for the first argument into the m_arguments vector.
47     m_arguments.push_back (arg);
48 }
49 
50 CommandObjectApropos::~CommandObjectApropos()
51 {
52 }
53 
54 
55 bool
56 CommandObjectApropos::DoExecute (Args& args, CommandReturnObject &result)
57 {
58     const size_t argc = args.GetArgumentCount ();
59 
60     if (argc == 1)
61     {
62         const char *search_word = args.GetArgumentAtIndex(0);
63         if ((search_word != NULL)
64             && (strlen (search_word) > 0))
65         {
66             // The bulk of the work must be done inside the Command Interpreter, since the command dictionary
67             // is private.
68             StringList commands_found;
69             StringList commands_help;
70             StringList user_commands_found;
71             StringList user_commands_help;
72 
73             m_interpreter.FindCommandsForApropos (search_word, commands_found, commands_help, true, false);
74             m_interpreter.FindCommandsForApropos (search_word, user_commands_found, user_commands_help, false, true);
75 
76             if (commands_found.GetSize() == 0 && user_commands_found.GetSize() == 0)
77             {
78                 result.AppendMessageWithFormat ("No commands found pertaining to '%s'. Try 'help' to see a complete list of debugger commands.\n", search_word);
79             }
80             else
81             {
82                 if (commands_found.GetSize() > 0)
83                 {
84                     result.AppendMessageWithFormat ("The following built-in commands may relate to '%s':\n", search_word);
85                     size_t max_len = 0;
86 
87                     for (size_t i = 0; i < commands_found.GetSize(); ++i)
88                     {
89                         size_t len = strlen (commands_found.GetStringAtIndex (i));
90                         if (len > max_len)
91                             max_len = len;
92                     }
93 
94                     for (size_t i = 0; i < commands_found.GetSize(); ++i)
95                         m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
96                                                                commands_found.GetStringAtIndex(i),
97                                                                "--",
98                                                                commands_help.GetStringAtIndex(i),
99                                                                max_len);
100                     if (user_commands_found.GetSize() > 0)
101                         result.AppendMessage("");
102                 }
103 
104                 if (user_commands_found.GetSize() > 0)
105                 {
106                     result.AppendMessageWithFormat ("The following user commands may relate to '%s':\n", search_word);
107                     size_t max_len = 0;
108 
109                     for (size_t i = 0; i < user_commands_found.GetSize(); ++i)
110                     {
111                         size_t len = strlen (user_commands_found.GetStringAtIndex (i));
112                         if (len > max_len)
113                             max_len = len;
114                     }
115 
116                     for (size_t i = 0; i < user_commands_found.GetSize(); ++i)
117                         m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
118                                                                user_commands_found.GetStringAtIndex(i),
119                                                                "--",
120                                                                user_commands_help.GetStringAtIndex(i),
121                                                                max_len);
122                 }
123 
124             }
125 
126 
127             std::vector<const Property *> properties;
128             const size_t num_properties = m_interpreter.GetDebugger().Apropos(search_word, properties);
129             if (num_properties)
130             {
131                 const bool dump_qualified_name = true;
132                 result.AppendMessageWithFormat ("\nThe following settings variables may relate to '%s': \n\n", search_word);
133                 for (size_t i=0; i<num_properties; ++i)
134                     properties[i]->DumpDescription (m_interpreter, result.GetOutputStream(), 0, dump_qualified_name);
135 
136             }
137 
138             result.SetStatus (eReturnStatusSuccessFinishNoResult);
139         }
140         else
141         {
142             result.AppendError ("'' is not a valid search word.\n");
143             result.SetStatus (eReturnStatusFailed);
144         }
145     }
146     else
147     {
148         result.AppendError ("'apropos' must be called with exactly one argument.\n");
149         result.SetStatus (eReturnStatusFailed);
150     }
151 
152     return result.Succeeded();
153 }
154