[Lldb-commits] [lldb] r263499 - Lots of progress on the CommandAlias refactoring

Enrico Granata via lldb-commits lldb-commits at lists.llvm.org
Mon Mar 14 15:17:05 PDT 2016


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




More information about the lldb-commits mailing list