Author: enrico Date: Mon Mar 14 17:17:04 2016 New Revision: 263499 URL: http://llvm.org/viewvc/llvm-project?rev=263499&view=rev Log: Lots of progress on the CommandAlias refactoring
This cleans things up such CommandAlias essentially can work as its own object; the aliases still live in a separate map, but are now just full-fledged CommandObjectSPs This patch also cleans up help generation for aliases, allows aliases to vend their own help, and adds a tweak such that "dash-dash aliases", such as po, don't show the list of options for their underlying command, since those can't be provided anyway I plan to fix up a few more things here, and then add a test case and proclaim victory Modified: lldb/trunk/include/lldb/Interpreter/CommandAlias.h lldb/trunk/include/lldb/Interpreter/CommandObject.h lldb/trunk/source/Commands/CommandObjectHelp.cpp lldb/trunk/source/Interpreter/CommandAlias.cpp lldb/trunk/source/Interpreter/CommandInterpreter.cpp lldb/trunk/source/Interpreter/CommandObject.cpp lldb/trunk/source/Interpreter/Options.cpp Modified: lldb/trunk/include/lldb/Interpreter/CommandAlias.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandAlias.h?rev=263499&r1=263498&r2=263499&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandAlias.h (original) +++ lldb/trunk/include/lldb/Interpreter/CommandAlias.h Mon Mar 14 17:17:04 2016 @@ -52,9 +52,43 @@ public: WantsRawCommandString() override; bool + WantsCompletion() override; + + int + HandleCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; + + int + HandleArgumentCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; + + Options* + GetOptions() override; + + bool IsAlias () override { return true; } bool + IsDashDashCommand () override; + + const char* + GetHelp () override; + + const char* + GetHelpLong () override; + + bool Execute(const char *args_string, CommandReturnObject &result) override; lldb::CommandObjectSP GetUnderlyingCommand() { return m_underlying_command_sp; } @@ -63,6 +97,7 @@ public: private: lldb::CommandObjectSP m_underlying_command_sp; OptionArgVectorSP m_option_args_sp ; + LazyBool m_is_dashdash_alias; }; } // namespace lldb_private Modified: lldb/trunk/include/lldb/Interpreter/CommandObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandObject.h?rev=263499&r1=263498&r2=263499&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandObject.h (original) +++ lldb/trunk/include/lldb/Interpreter/CommandObject.h Mon Mar 14 17:17:04 2016 @@ -148,7 +148,7 @@ public: virtual const char * GetHelpLong (); - const char * + virtual const char * GetSyntax (); const char * @@ -180,6 +180,12 @@ public: virtual bool IsAlias () { return false; } + + // override this to return true if your command is somehow a "dash-dash" + // form of some other command (e.g. po is expr -O --); this is a powerful + // hint to the help system that one cannot pass options to this command + virtual bool + IsDashDashCommand () { return false; } virtual lldb::CommandObjectSP GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr) Modified: lldb/trunk/source/Commands/CommandObjectHelp.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectHelp.cpp?rev=263499&r1=263498&r2=263499&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectHelp.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectHelp.cpp Mon Mar 14 17:17:04 2016 @@ -128,6 +128,8 @@ CommandObjectHelp::DoExecute (Args& comm { sub_command = command.GetArgumentAtIndex(i); matches.Clear(); + if (sub_cmd_obj->IsAlias()) + sub_cmd_obj = ((CommandAlias*)sub_cmd_obj)->GetUnderlyingCommand().get(); if (! sub_cmd_obj->IsMultiwordObject ()) { all_okay = false; Modified: lldb/trunk/source/Interpreter/CommandAlias.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandAlias.cpp?rev=263499&r1=263498&r2=263499&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandAlias.cpp (original) +++ lldb/trunk/source/Interpreter/CommandAlias.cpp Mon Mar 14 17:17:04 2016 @@ -85,11 +85,18 @@ CommandAlias::CommandAlias (CommandInter syntax, flags), m_underlying_command_sp(), -m_option_args_sp(new OptionArgVector) +m_option_args_sp(new OptionArgVector), +m_is_dashdash_alias(eLazyBoolCalculate) { if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) { m_underlying_command_sp = cmd_sp; + for (int i = 0; + auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i); + i++) + { + m_arguments.push_back(*cmd_entry); + } if (!help || !help[0]) { StreamString sstr; @@ -111,6 +118,64 @@ CommandAlias::WantsRawCommandString() } bool +CommandAlias::WantsCompletion() +{ + if (IsValid()) + return m_underlying_command_sp->WantsCompletion(); + return false; +} + +int +CommandAlias::HandleCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) +{ + if (IsValid()) + return m_underlying_command_sp->HandleCompletion(input, + cursor_index, + cursor_char_position, + match_start_point, + max_return_elements, + word_complete, + matches); + return -1; +} + +int +CommandAlias::HandleArgumentCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) +{ + if (IsValid()) + return m_underlying_command_sp->HandleArgumentCompletion(input, + cursor_index, + cursor_char_position, + opt_element_vector, + match_start_point, + max_return_elements, + word_complete, + matches); + return -1; +} + +Options* +CommandAlias::GetOptions() +{ + if (IsValid()) + return m_underlying_command_sp->GetOptions(); + return nullptr; +} + +bool CommandAlias::Execute(const char *args_string, CommandReturnObject &result) { llvm_unreachable("CommandAlias::Execute is not to be called"); @@ -149,3 +214,47 @@ CommandAlias::GetAliasExpansion (StreamS help_string.Printf ("'"); } + +bool +CommandAlias::IsDashDashCommand () +{ + if (m_is_dashdash_alias == eLazyBoolCalculate) + { + m_is_dashdash_alias = eLazyBoolNo; + if (IsValid()) + { + for (const OptionArgPair& opt_arg : *GetOptionArguments()) + { + if (opt_arg.first == "<argument>" && + opt_arg.second.second == " --") + { + m_is_dashdash_alias = eLazyBoolYes; + break; + } + } + } + } + return (m_is_dashdash_alias == eLazyBoolYes); +} + +// allow CommandAlias objects to provide their own help, but fallback to the info +// for the underlying command if no customization has been provided +const char* +CommandAlias::GetHelp () +{ + if (!m_cmd_help_short.empty()) + return m_cmd_help_short.c_str(); + if (IsValid()) + return m_underlying_command_sp->GetHelp(); + return nullptr; +} + +const char* +CommandAlias::GetHelpLong () +{ + if (!m_cmd_help_long.empty()) + return m_cmd_help_long.c_str(); + if (IsValid()) + return m_underlying_command_sp->GetHelpLong(); + return nullptr; +} Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=263499&r1=263498&r2=263499&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original) +++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Mon Mar 14 17:17:04 2016 @@ -772,7 +772,7 @@ CommandInterpreter::GetCommandSP (const { CommandAliasMap::iterator alias_pos = m_alias_dict.find(cmd); if (alias_pos != m_alias_dict.end()) - command_sp = ((CommandAlias*)alias_pos->second.get())->GetUnderlyingCommand(); + command_sp = alias_pos->second; } if (HasUserCommands()) @@ -823,7 +823,7 @@ CommandInterpreter::GetCommandSP (const cmd.assign(matches->GetStringAtIndex (num_cmd_matches)); CommandAliasMap::iterator alias_pos = m_alias_dict.find(cmd); if (alias_pos != m_alias_dict.end()) - alias_match_sp = ((CommandAlias*)alias_pos->second.get())->GetUnderlyingCommand(); + alias_match_sp = alias_pos->second; } if (HasUserCommands()) @@ -1351,15 +1351,16 @@ CommandInterpreter::BuildAliasResult (co alias_cmd_obj = GetCommandObject (alias_name); StreamString result_str; - if (alias_cmd_obj) + if (alias_cmd_obj && alias_cmd_obj->IsAlias()) { + OptionArgVectorSP option_arg_vector_sp = ((CommandAlias*)alias_cmd_obj)->GetOptionArguments(); + alias_cmd_obj = ((CommandAlias*)alias_cmd_obj)->GetUnderlyingCommand().get(); std::string alias_name_str = alias_name; if ((cmd_args.GetArgumentCount() == 0) || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)) cmd_args.Unshift (alias_name); result_str.Printf ("%s", alias_cmd_obj->GetCommandName ()); - OptionArgVectorSP option_arg_vector_sp = GetAlias(alias_name)->GetOptionArguments(); if (option_arg_vector_sp.get()) { Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=263499&r1=263498&r2=263499&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Mon Mar 14 17:17:04 2016 @@ -88,12 +88,12 @@ CommandObject::GetSyntax () { StreamString syntax_str; syntax_str.Printf ("%s", GetCommandName()); - if (GetOptions() != nullptr) + if (!IsDashDashCommand() && GetOptions() != nullptr) syntax_str.Printf (" <cmd-options>"); if (m_arguments.size() > 0) { syntax_str.Printf (" "); - if (WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions()) + if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions()) syntax_str.Printf("-- "); GetFormattedCommandArguments (syntax_str); } Modified: lldb/trunk/source/Interpreter/Options.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Options.cpp?rev=263499&r1=263498&r2=263499&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/Options.cpp (original) +++ lldb/trunk/source/Interpreter/Options.cpp Mon Mar 14 17:17:04 2016 @@ -14,6 +14,7 @@ #include <algorithm> #include <bitset> #include <map> +#include <set> // Other libraries and framework includes // Project includes @@ -477,6 +478,7 @@ Options::GenerateOptionUsage CommandObject *cmd ) { + const bool only_print_args = cmd->IsDashDashCommand(); const uint32_t screen_width = m_interpreter.GetDebugger().GetTerminalWidth(); const OptionDefinition *opt_defs = GetDefinitions(); @@ -523,105 +525,110 @@ Options::GenerateOptionUsage if (cmd) cmd->GetFormattedCommandArguments(args_str, opt_set_mask); - // First go through and print all options that take no arguments as - // a single string. If a command has "-a" "-b" and "-c", this will show - // up as [-abc] - - std::set<int> options; - std::set<int>::const_iterator options_pos, options_end; - for (i = 0; i < num_options; ++i) + if (!only_print_args) { - if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) - { - // Add current option to the end of out_stream. + // First go through and print all options that take no arguments as + // a single string. If a command has "-a" "-b" and "-c", this will show + // up as [-abc] - if (opt_defs[i].required == true && - opt_defs[i].option_has_arg == OptionParser::eNoArgument) + std::set<int> options; + std::set<int>::const_iterator options_pos, options_end; + for (i = 0; i < num_options; ++i) + { + if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) { - options.insert (opt_defs[i].short_option); - } - } - } + // Add current option to the end of out_stream. - if (options.empty() == false) - { - // We have some required options with no arguments - strm.PutCString(" -"); - for (i=0; i<2; ++i) - for (options_pos = options.begin(), options_end = options.end(); - options_pos != options_end; - ++options_pos) - { - if (i==0 && ::islower (*options_pos)) - continue; - if (i==1 && ::isupper (*options_pos)) - continue; - strm << (char)*options_pos; + if (opt_defs[i].required == true && + opt_defs[i].option_has_arg == OptionParser::eNoArgument) + { + options.insert (opt_defs[i].short_option); + } } - } + } - for (i = 0, options.clear(); i < num_options; ++i) - { - if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) + if (options.empty() == false) { - // Add current option to the end of out_stream. + // We have some required options with no arguments + strm.PutCString(" -"); + for (i=0; i<2; ++i) + for (options_pos = options.begin(), options_end = options.end(); + options_pos != options_end; + ++options_pos) + { + if (i==0 && ::islower (*options_pos)) + continue; + if (i==1 && ::isupper (*options_pos)) + continue; + strm << (char)*options_pos; + } + } - if (opt_defs[i].required == false && - opt_defs[i].option_has_arg == OptionParser::eNoArgument) + for (i = 0, options.clear(); i < num_options; ++i) + { + if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) { - options.insert (opt_defs[i].short_option); + // Add current option to the end of out_stream. + + if (opt_defs[i].required == false && + opt_defs[i].option_has_arg == OptionParser::eNoArgument) + { + options.insert (opt_defs[i].short_option); + } } } - } - if (options.empty() == false) - { - // We have some required options with no arguments - strm.PutCString(" [-"); - for (i=0; i<2; ++i) - for (options_pos = options.begin(), options_end = options.end(); - options_pos != options_end; - ++options_pos) - { - if (i==0 && ::islower (*options_pos)) - continue; - if (i==1 && ::isupper (*options_pos)) - continue; - strm << (char)*options_pos; - } - strm.PutChar(']'); - } + if (options.empty() == false) + { + // We have some required options with no arguments + strm.PutCString(" [-"); + for (i=0; i<2; ++i) + for (options_pos = options.begin(), options_end = options.end(); + options_pos != options_end; + ++options_pos) + { + if (i==0 && ::islower (*options_pos)) + continue; + if (i==1 && ::isupper (*options_pos)) + continue; + strm << (char)*options_pos; + } + strm.PutChar(']'); + } - // First go through and print the required options (list them up front). - - for (i = 0; i < num_options; ++i) - { - if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) + // First go through and print the required options (list them up front). + + for (i = 0; i < num_options; ++i) { - if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument) - PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm); + if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) + { + if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument) + PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm); + } } - } - // Now go through again, and this time only print the optional options. + // Now go through again, and this time only print the optional options. - for (i = 0; i < num_options; ++i) - { - if (opt_defs[i].usage_mask & opt_set_mask) + for (i = 0; i < num_options; ++i) { - // Add current option to the end of out_stream. + if (opt_defs[i].usage_mask & opt_set_mask) + { + // Add current option to the end of out_stream. - if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument) - PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm); + if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument) + PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm); + } } } if (args_str.GetSize() > 0) { - if (cmd->WantsRawCommandString()) + if (cmd->WantsRawCommandString() && !only_print_args) strm.Printf(" --"); strm.Printf (" %s", args_str.GetData()); + if (only_print_args) + break; } } @@ -636,76 +643,79 @@ Options::GenerateOptionUsage strm.Printf ("\n\n"); - // Now print out all the detailed information about the various options: long form, short form and help text: - // -short <argument> ( --long_name <argument> ) - // help text + if (!only_print_args) + { + // Now print out all the detailed information about the various options: long form, short form and help text: + // -short <argument> ( --long_name <argument> ) + // help text - // This variable is used to keep track of which options' info we've printed out, because some options can be in - // more than one usage level, but we only want to print the long form of its information once. + // This variable is used to keep track of which options' info we've printed out, because some options can be in + // more than one usage level, but we only want to print the long form of its information once. - std::multimap<int, uint32_t> options_seen; - strm.IndentMore (5); + std::multimap<int, uint32_t> options_seen; + strm.IndentMore (5); - // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option) - // when writing out detailed help for each option. + // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option) + // when writing out detailed help for each option. - for (i = 0; i < num_options; ++i) - options_seen.insert(std::make_pair(opt_defs[i].short_option, i)); + for (i = 0; i < num_options; ++i) + options_seen.insert(std::make_pair(opt_defs[i].short_option, i)); - // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option - // and write out the detailed help information for that option. + // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option + // and write out the detailed help information for that option. - bool first_option_printed = false;; + bool first_option_printed = false;; - for (auto pos : options_seen) - { - i = pos.second; - //Print out the help information for this option. + for (auto pos : options_seen) + { + i = pos.second; + //Print out the help information for this option. - // Put a newline separation between arguments - if (first_option_printed) - strm.EOL(); - else - first_option_printed = true; - - CommandArgumentType arg_type = opt_defs[i].argument_type; - - StreamString arg_name_str; - arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type)); + // Put a newline separation between arguments + if (first_option_printed) + strm.EOL(); + else + first_option_printed = true; + + CommandArgumentType arg_type = opt_defs[i].argument_type; + + StreamString arg_name_str; + arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type)); - strm.Indent (); - if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option)) - { - PrintOption (opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, strm); - PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm); - } - else - { - // Short option is not printable, just print long option - PrintOption (opt_defs[i], eDisplayLongOption, nullptr, nullptr, false, strm); - } - strm.EOL(); - - strm.IndentMore (5); - - if (opt_defs[i].usage_text) - OutputFormattedUsageText (strm, - opt_defs[i], - screen_width); - if (opt_defs[i].enum_values != nullptr) - { strm.Indent (); - strm.Printf("Values: "); - for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; k++) + if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option)) { - if (k == 0) - strm.Printf("%s", opt_defs[i].enum_values[k].string_value); - else - strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value); + PrintOption (opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, strm); + PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm); + } + else + { + // Short option is not printable, just print long option + PrintOption (opt_defs[i], eDisplayLongOption, nullptr, nullptr, false, strm); } strm.EOL(); + + strm.IndentMore (5); + + if (opt_defs[i].usage_text) + OutputFormattedUsageText (strm, + opt_defs[i], + screen_width); + if (opt_defs[i].enum_values != nullptr) + { + strm.Indent (); + strm.Printf("Values: "); + for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; k++) + { + if (k == 0) + strm.Printf("%s", opt_defs[i].enum_values[k].string_value); + else + strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value); + } + strm.EOL(); + } + strm.IndentLess (5); } - strm.IndentLess (5); } // Restore the indent level _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits