1 //===-- CommandObjectApropos.cpp ---------------------------------*- C++ 2 //-*-===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectApropos.h" 11 #include "lldb/Interpreter/CommandInterpreter.h" 12 #include "lldb/Interpreter/CommandReturnObject.h" 13 #include "lldb/Interpreter/Options.h" 14 #include "lldb/Interpreter/Property.h" 15 #include "lldb/Utility/Args.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 // CommandObjectApropos 21 22 CommandObjectApropos::CommandObjectApropos(CommandInterpreter &interpreter) 23 : CommandObjectParsed( 24 interpreter, "apropos", 25 "List debugger commands related to a word or subject.", nullptr) { 26 CommandArgumentEntry arg; 27 CommandArgumentData search_word_arg; 28 29 // Define the first (and only) variant of this arg. 30 search_word_arg.arg_type = eArgTypeSearchWord; 31 search_word_arg.arg_repetition = eArgRepeatPlain; 32 33 // There is only one variant this argument could be; put it into the argument 34 // entry. 35 arg.push_back(search_word_arg); 36 37 // Push the data for the first argument into the m_arguments vector. 38 m_arguments.push_back(arg); 39 } 40 41 CommandObjectApropos::~CommandObjectApropos() = default; 42 43 bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { 44 const size_t argc = args.GetArgumentCount(); 45 46 if (argc == 1) { 47 auto search_word = args[0].ref; 48 if (!search_word.empty()) { 49 // The bulk of the work must be done inside the Command Interpreter, 50 // since the command dictionary is private. 51 StringList commands_found; 52 StringList commands_help; 53 54 m_interpreter.FindCommandsForApropos(search_word, commands_found, 55 commands_help, true, true, true); 56 57 if (commands_found.GetSize() == 0) { 58 result.AppendMessageWithFormat("No commands found pertaining to '%s'. " 59 "Try 'help' to see a complete list of " 60 "debugger commands.\n", 61 args[0].c_str()); 62 } else { 63 if (commands_found.GetSize() > 0) { 64 result.AppendMessageWithFormat( 65 "The following commands may relate to '%s':\n", args[0].c_str()); 66 size_t max_len = 0; 67 68 for (size_t i = 0; i < commands_found.GetSize(); ++i) { 69 size_t len = strlen(commands_found.GetStringAtIndex(i)); 70 if (len > max_len) 71 max_len = len; 72 } 73 74 for (size_t i = 0; i < commands_found.GetSize(); ++i) 75 m_interpreter.OutputFormattedHelpText( 76 result.GetOutputStream(), commands_found.GetStringAtIndex(i), 77 "--", commands_help.GetStringAtIndex(i), max_len); 78 } 79 } 80 81 std::vector<const Property *> properties; 82 const size_t num_properties = 83 GetDebugger().Apropos(search_word, properties); 84 if (num_properties) { 85 const bool dump_qualified_name = true; 86 result.AppendMessageWithFormatv( 87 "\nThe following settings variables may relate to '{0}': \n\n", 88 args[0].ref); 89 for (size_t i = 0; i < num_properties; ++i) 90 properties[i]->DumpDescription( 91 m_interpreter, result.GetOutputStream(), 0, dump_qualified_name); 92 } 93 94 result.SetStatus(eReturnStatusSuccessFinishNoResult); 95 } else { 96 result.AppendError("'' is not a valid search word.\n"); 97 result.SetStatus(eReturnStatusFailed); 98 } 99 } else { 100 result.AppendError("'apropos' must be called with exactly one argument.\n"); 101 result.SetStatus(eReturnStatusFailed); 102 } 103 104 return result.Succeeded(); 105 } 106