Rewrite OutputFormattedHelpText in terms of StringRef.
authorZachary Turner <zturner@google.com>
Tue, 8 Nov 2016 04:12:42 +0000 (04:12 +0000)
committerZachary Turner <zturner@google.com>
Tue, 8 Nov 2016 04:12:42 +0000 (04:12 +0000)
This makes the logic easier to follow and also propagates
StringRef up to the API boundary, which is necessary for
making higher up StringRef API changes.

Differential Revision: https://reviews.llvm.org/D26325

llvm-svn: 286204

lldb/include/lldb/Core/Stream.h
lldb/include/lldb/Interpreter/CommandInterpreter.h
lldb/source/Core/Stream.cpp
lldb/source/Interpreter/CommandInterpreter.cpp

index b3bb19c..807f9bf 100644 (file)
@@ -191,6 +191,8 @@ public:
   //------------------------------------------------------------------
   Stream &operator<<(const char *cstr);
 
+  Stream &operator<<(llvm::StringRef str);
+
   //------------------------------------------------------------------
   /// Output a pointer value \a p to the stream \a s.
   ///
index 58b847f..3bb62f9 100644 (file)
@@ -336,24 +336,21 @@ public:
 
   void GetAliasHelp(const char *alias_name, StreamString &help_string);
 
-  void OutputFormattedHelpText(Stream &strm, const char *prefix,
-                               const char *help_text);
+  void OutputFormattedHelpText(Stream &strm, llvm::StringRef prefix,
+                               llvm::StringRef help_text);
 
-  void OutputFormattedHelpText(Stream &stream, const char *command_word,
-                               const char *separator, const char *help_text,
-                               size_t max_word_len);
+  void OutputFormattedHelpText(Stream &stream, llvm::StringRef command_word,
+                               llvm::StringRef separator,
+                               llvm::StringRef help_text, size_t max_word_len);
 
   // this mimics OutputFormattedHelpText but it does perform a much simpler
   // formatting, basically ensuring line alignment. This is only good if you
-  // have
-  // some complicated layout for your help text and want as little help as
-  // reasonable
-  // in properly displaying it. Most of the times, you simply want to type some
-  // text
-  // and have it printed in a reasonable way on screen. If so, use
-  // OutputFormattedHelpText
-  void OutputHelpText(Stream &stream, const char *command_word,
-                      const char *separator, const char *help_text,
+  // have some complicated layout for your help text and want as little help as
+  // reasonable in properly displaying it. Most of the times, you simply want
+  // to type some text and have it printed in a reasonable way on screen. If
+  // so, use OutputFormattedHelpText
+  void OutputHelpText(Stream &stream, llvm::StringRef command_word,
+                      llvm::StringRef separator, llvm::StringRef help_text,
                       uint32_t max_word_len);
 
   Debugger &GetDebugger() { return m_debugger; }
index 7614d02..2f9c650 100644 (file)
@@ -227,6 +227,11 @@ Stream &Stream::operator<<(const char *s) {
   return *this;
 }
 
+Stream &Stream::operator<<(llvm::StringRef str) {
+  Write(str.data(), str.size());
+  return *this;
+}
+
 //------------------------------------------------------------------
 // Stream the pointer value out to this stream.
 //------------------------------------------------------------------
index e9a7025..89ef7fe 100644 (file)
@@ -1104,9 +1104,10 @@ bool CommandInterpreter::RemoveUser(llvm::StringRef alias_name) {
 
 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);
+  llvm::StringRef help_prologue(GetDebugger().GetIOHandlerHelpPrologue());
+  if (!help_prologue.empty()) {
+    OutputFormattedHelpText(result.GetOutputStream(), llvm::StringRef(),
+                            help_prologue);
   }
 
   CommandObject::CommandMap::const_iterator pos;
@@ -1121,8 +1122,8 @@ void CommandInterpreter::GetHelp(CommandReturnObject &result,
           (pos->first.compare(0, 1, "_") == 0))
         continue;
 
-      OutputFormattedHelpText(result.GetOutputStream(), pos->first.c_str(),
-                              "--", pos->second->GetHelp(), max_len);
+      OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
+                              pos->second->GetHelp(), max_len);
     }
     result.AppendMessage("");
   }
@@ -1138,8 +1139,7 @@ void CommandInterpreter::GetHelp(CommandReturnObject &result,
 
     for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end();
          ++alias_pos) {
-      OutputFormattedHelpText(result.GetOutputStream(),
-                              alias_pos->first.c_str(), "--",
+      OutputFormattedHelpText(result.GetOutputStream(), alias_pos->first, "--",
                               alias_pos->second->GetHelp(), max_len);
     }
     result.AppendMessage("");
@@ -1151,8 +1151,8 @@ void CommandInterpreter::GetHelp(CommandReturnObject &result,
     result.AppendMessage("");
     max_len = FindLongestCommandWord(m_user_dict);
     for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) {
-      OutputFormattedHelpText(result.GetOutputStream(), pos->first.c_str(),
-                              "--", pos->second->GetHelp(), max_len);
+      OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
+                              pos->second->GetHelp(), max_len);
     }
     result.AppendMessage("");
   }
@@ -2498,79 +2498,68 @@ void CommandInterpreter::SetSynchronous(bool value) {
 }
 
 void CommandInterpreter::OutputFormattedHelpText(Stream &strm,
-                                                 const char *prefix,
-                                                 const char *help_text) {
+                                                 llvm::StringRef prefix,
+                                                 llvm::StringRef help_text) {
   const uint32_t max_columns = m_debugger.GetTerminalWidth();
-  if (prefix == NULL)
-    prefix = "";
 
-  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;
+  size_t line_width_max = max_columns - prefix.size();
   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 == ' ') {
-        line_end = line_scan;
-        line_scan_end = line_start + line_width_max;
-      } else if (next == '\n' || next == '\0') {
-        line_end = line_scan;
-        break;
-      }
-      ++line_scan;
-    }
+    line_width_max = help_text.size() + prefix.size();
 
+  strm.IndentMore(prefix.size());
+  bool prefixed_yet = false;
+  while (!help_text.empty()) {
     // Prefix the first line, indent subsequent lines to line up
-    if (line_start == help_text)
-      strm.Write(prefix, prefix_width);
-    else
+    if (!prefixed_yet) {
+      strm << prefix;
+      prefixed_yet = true;
+    } else
       strm.Indent();
-    strm.Write(line_start, line_end - line_start);
+
+    // Never print more than the maximum on one line.
+    llvm::StringRef this_line = help_text.substr(0, line_width_max);
+
+    // Always break on an explicit newline.
+    std::size_t first_newline = this_line.find_first_of("\n");
+
+    // Don't break on space/tab unless the text is too long to fit on one line.
+    std::size_t last_space = llvm::StringRef::npos;
+    if (this_line.size() != help_text.size())
+      last_space = this_line.find_last_of(" \t");
+
+    // Break at whichever condition triggered first.
+    this_line = this_line.substr(0, std::min(first_newline, last_space));
+    strm.PutCString(this_line);
     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);
+    // Remove whitespace / newlines after breaking.
+    help_text = help_text.drop_front(this_line.size()).ltrim();
   }
-  strm.IndentLess(prefix_width);
+  strm.IndentLess(prefix.size());
 }
 
 void CommandInterpreter::OutputFormattedHelpText(Stream &strm,
-                                                 const char *word_text,
-                                                 const char *separator,
-                                                 const char *help_text,
+                                                 llvm::StringRef word_text,
+                                                 llvm::StringRef separator,
+                                                 llvm::StringRef help_text,
                                                  size_t max_word_len) {
   StreamString prefix_stream;
-  prefix_stream.Printf("  %-*s %s ", (int)max_word_len, word_text, separator);
+  prefix_stream.Printf("  %-*s %*s ", (int)max_word_len, word_text.data(),
+                       (int)separator.size(), separator.data());
   OutputFormattedHelpText(strm, prefix_stream.GetData(), help_text);
 }
 
-void CommandInterpreter::OutputHelpText(Stream &strm, const char *word_text,
-                                        const char *separator,
-                                        const char *help_text,
+void CommandInterpreter::OutputHelpText(Stream &strm, llvm::StringRef word_text,
+                                        llvm::StringRef separator,
+                                        llvm::StringRef help_text,
                                         uint32_t max_word_len) {
-  int indent_size = max_word_len + strlen(separator) + 2;
+  int indent_size = max_word_len + separator.size() + 2;
 
   strm.IndentMore(indent_size);
 
   StreamString text_strm;
-  text_strm.Printf("%-*s %s %s", max_word_len, word_text, separator, help_text);
+  text_strm.Printf("%-*s ", (int)max_word_len, word_text.data());
+  text_strm << separator << " " << help_text;
 
   const uint32_t max_columns = m_debugger.GetTerminalWidth();