[Lldb-commits] [lldb] r226068 - Three related changes to help:

Kate Stone katherine.stone at apple.com
Wed Jan 14 16:52:42 PST 2015


Author: kate
Date: Wed Jan 14 18:52:41 2015
New Revision: 226068

URL: http://llvm.org/viewvc/llvm-project?rev=226068&view=rev
Log:
Three related changes to help:

The default help display now shows the alias collection by default, and hides commands whose named begin with an underscore.  Help is primarily useful to those unfamiliar with LLDB and should aim to answer typical questions while still being able to provide more esoteric answers when required.  To that latter end an argument to include the hidden commands in help has been added, and instead of having a help flag to show aliases there is now one to hide them.  This final change might be controversial as it repurposes the -a shorthand as the opposite of its original meaning.

The previous implementation of OutputFormattedHelpText was easily confused by embedded newlines.  The new algorithm correctly breaks on the FIRST newline or LAST space/tab before the target column count rather than treating all whitespace interchangeably.

Command interpreters now have the ability to specify help prologue text and a command prefix string.  Neither are used in the current LLDB sources but are required to support REPL-like extensions where LLDB commands must be prefixed and additional help text is required to explain how to access traditional debugging commands.

<rdar://problem/17751929>
<rdar://problem/16953815>
<rdar://problem/16953841>
<rdar://problem/16930173>
<rdar://problem/16879028>

Modified:
    lldb/trunk/include/lldb/Core/Debugger.h
    lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
    lldb/trunk/source/Commands/CommandObjectHelp.cpp
    lldb/trunk/source/Commands/CommandObjectHelp.h
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Interpreter/CommandInterpreter.cpp

Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=226068&r1=226067&r2=226068&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Wed Jan 14 18:52:41 2015
@@ -158,8 +158,6 @@ public:
     // To get the target's source manager, call GetSourceManager on the target instead.
     SourceManager &
     GetSourceManager ();
-
-public:
     
     lldb::TargetSP
     GetSelectedTarget ()
@@ -224,6 +222,12 @@ public:
     ConstString
     GetTopIOHandlerControlSequence(char ch);
 
+    const char *
+    GetIOHandlerCommandPrefix();
+
+    const char *
+    GetIOHandlerHelpPrologue();
+
     bool
     HideTopIOHandler();
 
@@ -352,7 +356,6 @@ public:
     
     bool
     GetNotifyVoid () const;
-
     
     const ConstString &
     GetInstanceName()

Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=226068&r1=226067&r2=226068&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Wed Jan 14 18:52:41 2015
@@ -224,6 +224,7 @@ public:
         eCommandTypesBuiltin = 0x0001,  // native commands such as "frame"
         eCommandTypesUserDef = 0x0002,  // scripted commands
         eCommandTypesAliases = 0x0004,  // aliases such as "po"
+        eCommandTypesHidden  = 0x0008,  // commands prefixed with an underscore
         eCommandTypesAllThem = 0xFFFF   // all commands
     };
 
@@ -431,6 +432,11 @@ public:
                   StreamString &help_string);
 
     void
+    OutputFormattedHelpText (Stream &strm,
+                             const char *prefix,
+                             const char *help_text);
+
+    void
     OutputFormattedHelpText (Stream &stream,
                              const char *command_word,
                              const char *separator,
@@ -607,6 +613,9 @@ public:
                                     bool asynchronously,
                                     void *baton);
 
+    const char *
+    GetCommandPrefix ();
+
     //------------------------------------------------------------------
     // Properties
     //------------------------------------------------------------------

Modified: lldb/trunk/source/Commands/CommandObjectHelp.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectHelp.cpp?rev=226068&r1=226067&r2=226068&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectHelp.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectHelp.cpp Wed Jan 14 18:52:41 2015
@@ -54,9 +54,10 @@ CommandObjectHelp::~CommandObjectHelp()
 OptionDefinition
 CommandObjectHelp::CommandOptions::g_option_table[] =
 {
-    { LLDB_OPT_SET_ALL, false, "show-aliases", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Show aliases in the command list."},
+    { LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Hide aliases in the command list."},
     { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Hide user-defined commands from the list."},
-    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+    { LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Include commands prefixed with an underscore."},
+    { 0, false, NULL, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
 };
 
 bool
@@ -75,6 +76,8 @@ CommandObjectHelp::DoExecute (Args& comm
             cmd_types |= CommandInterpreter::eCommandTypesAliases;
         if (m_options.m_show_user_defined)
             cmd_types |= CommandInterpreter::eCommandTypesUserDef;
+        if (m_options.m_show_hidden)
+            cmd_types |= CommandInterpreter::eCommandTypesHidden;
 
         result.SetStatus (eReturnStatusSuccessFinishNoResult);
         m_interpreter.GetHelp (result, cmd_types);  // General help
@@ -136,17 +139,19 @@ CommandObjectHelp::DoExecute (Args& comm
                 else if (!sub_cmd_obj)
                 {
                     result.AppendErrorWithFormat("'%s' is not a known command.\n"
-                                                 "Try 'help' to see a current list of commands.\n",
-                                                 cmd_string.c_str());
+                                                 "Try '%shelp' to see a current list of commands.\n",
+                                                 cmd_string.c_str(),
+                                                 m_interpreter.GetCommandPrefix());
                     result.SetStatus (eReturnStatusFailed);
                     return false;
                 }
                 else
                 {
                     result.GetOutputStream().Printf("'%s' is not a known command.\n"
-                                                   "Try 'help' to see a current list of commands.\n"
+                                                   "Try '%shelp' to see a current list of commands.\n"
                                                     "The closest match is '%s'. Help on it follows.\n\n",
                                                    cmd_string.c_str(),
+                                                   m_interpreter.GetCommandPrefix(),
                                                    sub_cmd_obj->GetCommandName());
                 }
             }
@@ -183,8 +188,9 @@ CommandObjectHelp::DoExecute (Args& comm
             else
             {
                 result.AppendErrorWithFormat 
-                    ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
-                     command.GetArgumentAtIndex(0));
+                    ("'%s' is not a known command.\nTry '%shelp' to see a current list of commands.\n",
+                     command.GetArgumentAtIndex(0),
+                     m_interpreter.GetCommandPrefix());
                 result.SetStatus (eReturnStatusFailed);
             }
         }

Modified: lldb/trunk/source/Commands/CommandObjectHelp.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectHelp.h?rev=226068&r1=226067&r2=226068&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectHelp.h (original)
+++ lldb/trunk/source/Commands/CommandObjectHelp.h Wed Jan 14 18:52:41 2015
@@ -62,11 +62,14 @@ public:
             switch (short_option)
             {
                 case 'a':
-                    m_show_aliases = true;
+                    m_show_aliases = false;
                     break;
                 case 'u':
                     m_show_user_defined = false;
                     break;
+                case 'h':
+                    m_show_hidden = true;
+                    break;
                 default:
                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                     break;
@@ -78,8 +81,9 @@ public:
         void
         OptionParsingStarting ()
         {
-            m_show_aliases = false;
+            m_show_aliases = true;
             m_show_user_defined = true;
+            m_show_hidden = false;
         }
         
         const OptionDefinition*
@@ -95,7 +99,8 @@ public:
         // Instance variables to hold the values for command options.
         
         bool m_show_aliases;
-        bool m_show_user_defined;        
+        bool m_show_user_defined;
+        bool m_show_hidden;
     };
     
     virtual Options *

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=226068&r1=226067&r2=226068&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Wed Jan 14 18:52:41 2015
@@ -927,6 +927,18 @@ Debugger::GetTopIOHandlerControlSequence
     return m_input_reader_stack.GetTopIOHandlerControlSequence (ch);
 }
 
+const char *
+Debugger::GetIOHandlerCommandPrefix()
+{
+    return m_input_reader_stack.GetTopIOHandlerCommandPrefix();
+}
+
+const char *
+Debugger::GetIOHandlerHelpPrologue()
+{
+    return m_input_reader_stack.GetTopIOHandlerHelpPrologue();
+}
+
 void
 Debugger::RunIOHandler (const IOHandlerSP& reader_sp)
 {

Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=226068&r1=226067&r2=226068&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Wed Jan 14 18:52:41 2015
@@ -1170,17 +1170,25 @@ void
 CommandInterpreter::GetHelp (CommandReturnObject &result,
                              uint32_t cmd_types)
 {
+    const char * help_prologue = GetDebugger().GetIOHandlerHelpPrologue();
+    if (help_prologue != NULL)
+    {
+        OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue);
+    }
+
     CommandObject::CommandMap::const_iterator pos;
     size_t max_len = FindLongestCommandWord (m_command_dict);
     
     if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
     {
-    
-        result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
+        result.AppendMessage("Debugger commands:");
         result.AppendMessage("");
 
         for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
         {
+            if (!(cmd_types & eCommandTypesHidden) && (pos->first.compare(0, 1, "_") == 0))
+                continue;
+
             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
                                      max_len);
         }
@@ -1190,8 +1198,9 @@ CommandInterpreter::GetHelp (CommandRetu
 
     if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
     {
-        result.AppendMessage("The following is a list of your current command abbreviations "
-                             "(see 'help command alias' for more info):");
+        result.AppendMessageWithFormat("Current command abbreviations "
+                                       "(type '%shelp command alias' for more info):\n",
+                                       GetCommandPrefix());
         result.AppendMessage("");
         max_len = FindLongestCommandWord (m_alias_dict);
 
@@ -1212,7 +1221,7 @@ CommandInterpreter::GetHelp (CommandRetu
 
     if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
     {
-        result.AppendMessage ("The following is a list of your current user-defined commands:");
+        result.AppendMessage ("Current user-defined commands:");
         result.AppendMessage("");
         max_len = FindLongestCommandWord (m_user_dict);
         for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
@@ -1223,7 +1232,8 @@ CommandInterpreter::GetHelp (CommandRetu
         result.AppendMessage("");
     }
 
-    result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
+    result.AppendMessageWithFormat("For more information on any command, type '%shelp <command-name>'.\n",
+                                   GetCommandPrefix());
 }
 
 CommandObject *
@@ -2496,6 +2506,13 @@ CommandInterpreter::SourceInitFile (bool
     }
 }
 
+const char *
+CommandInterpreter::GetCommandPrefix()
+{
+    const char * prefix = GetDebugger().GetIOHandlerCommandPrefix();
+    return prefix == NULL ? "" : prefix;
+}
+
 PlatformSP
 CommandInterpreter::GetPlatform (bool prefer_target_platform)
 {
@@ -2887,84 +2904,74 @@ CommandInterpreter::SetSynchronous (bool
 
 void
 CommandInterpreter::OutputFormattedHelpText (Stream &strm,
-                                             const char *word_text,
-                                             const char *separator,
-                                             const char *help_text,
-                                             size_t max_word_len)
+                                             const char *prefix,
+                                             const char *help_text)
 {
     const uint32_t max_columns = m_debugger.GetTerminalWidth();
+    if (prefix == NULL)
+        prefix = "";
 
-    int indent_size = max_word_len + strlen (separator) + 2;
-
-    strm.IndentMore (indent_size);
-    
-    StreamString text_strm;
-    text_strm.Printf ("%-*s %s %s",  (int)max_word_len, word_text, separator, help_text);
-    
-    size_t len = text_strm.GetSize();
-    const char *text = text_strm.GetData();
-    if (text[len - 1] == '\n')
-    {
-        text_strm.EOL();
-        len = text_strm.GetSize();
-    }
-
-    if (len  < max_columns)
-    {
-        // Output it as a single line.
-        strm.Printf ("%s", text);
-    }
-    else
-    {
-        // We need to break it up into multiple lines.
-        bool first_line = true;
-        int text_width;
-        size_t start = 0;
-        size_t end = start;
-        const size_t final_end = strlen (text);
-        
-        while (end < final_end)
-        {
-            if (first_line)
-                text_width = max_columns - 1;
-            else
-                text_width = max_columns - indent_size - 1;
-
-            // Don't start the 'text' on a space, since we're already outputting the indentation.
-            if (!first_line)
+    size_t prefix_width = strlen(prefix);
+    size_t line_width_max = max_columns - prefix_width;
+    const char *help_text_end = help_text + strlen(help_text);
+    const char *line_start = help_text;
+    if (line_width_max < 16)
+        line_width_max = help_text_end - help_text + prefix_width;
+
+    strm.IndentMore (prefix_width);
+    while (line_start < help_text_end)
+    {
+        // Break each line at the first newline or last space/tab before
+        // the maximum number of characters that fit on a line.  Lines with no
+        // natural break are left unbroken to wrap.
+        const char *line_end = help_text_end;
+        const char *line_scan = line_start;
+        const char *line_scan_end = help_text_end;
+        while (line_scan < line_scan_end)
+        {
+            char next = *line_scan;
+            if (next == '\t' || next == ' ')
             {
-                while ((start < final_end) && (text[start] == ' '))
-                  start++;
+                line_end = line_scan;
+                line_scan_end = line_start + line_width_max;
             }
-
-            end = start + text_width;
-            if (end > final_end)
-                end = final_end;
-            else
+            else if (next == '\n' || next == '\0')
             {
-                // If we're not at the end of the text, make sure we break the line on white space.
-                while (end > start
-                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
-                    end--;
-                assert (end > 0);
+                line_end = line_scan;
+                break;
             }
-
-            const size_t sub_len = end - start;
-            if (start != 0)
-              strm.EOL();
-            if (!first_line)
-                strm.Indent();
-            else
-                first_line = false;
-            assert (start <= final_end);
-            assert (start + sub_len <= final_end);
-            if (sub_len > 0)
-                strm.Write (text + start, sub_len);
-            start = end + 1;
+            ++line_scan;
         }
+        
+        // Prefix the first line, indent subsequent lines to line up
+        if (line_start == help_text)
+            strm.Write (prefix, prefix_width);
+        else
+            strm.Indent();
+        strm.Write (line_start, line_end - line_start);
+        strm.EOL();
+
+        // When a line breaks at whitespace consume it before continuing
+        line_start = line_end;
+        char next = *line_start;
+        if (next == '\n')
+            ++line_start;
+        else while (next == ' ' || next == '\t')
+            next = *(++line_start);
     }
-    strm.EOL();
-    strm.IndentLess(indent_size);
+    strm.IndentLess (prefix_width);
+}
+
+void
+CommandInterpreter::OutputFormattedHelpText (Stream &strm,
+                                             const char *word_text,
+                                             const char *separator,
+                                             const char *help_text,
+                                             size_t max_word_len)
+{
+    StreamString prefix_stream;
+    prefix_stream.Printf ("  %-*s %s ",  (int)max_word_len, word_text, separator);
+    OutputFormattedHelpText (strm, prefix_stream.GetData(), help_text);
 }
 
 void





More information about the lldb-commits mailing list