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