Index: include/lldb/Core/Debugger.h =================================================================== --- include/lldb/Core/Debugger.h +++ include/lldb/Core/Debugger.h @@ -158,8 +158,6 @@ // To get the target's source manager, call GetSourceManager on the target instead. SourceManager & GetSourceManager (); - -public: lldb::TargetSP GetSelectedTarget () @@ -224,6 +222,12 @@ ConstString GetTopIOHandlerControlSequence(char ch); + const char * + GetIOHandlerCommandPrefix(); + + const char * + GetIOHandlerHelpPrologue(); + bool HideTopIOHandler(); @@ -352,7 +356,6 @@ bool GetNotifyVoid () const; - const ConstString & GetInstanceName() Index: include/lldb/Interpreter/CommandInterpreter.h =================================================================== --- include/lldb/Interpreter/CommandInterpreter.h +++ include/lldb/Interpreter/CommandInterpreter.h @@ -224,6 +224,7 @@ 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 @@ 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 @@ bool asynchronously, void *baton); + const char * + GetCommandPrefix (); + //------------------------------------------------------------------ // Properties //------------------------------------------------------------------ Index: source/Commands/CommandObjectHelp.h =================================================================== --- source/Commands/CommandObjectHelp.h +++ source/Commands/CommandObjectHelp.h @@ -62,11 +62,14 @@ 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 @@ 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 @@ // 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 * Index: source/Commands/CommandObjectHelp.cpp =================================================================== --- source/Commands/CommandObjectHelp.cpp +++ source/Commands/CommandObjectHelp.cpp @@ -54,9 +54,10 @@ 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 @@ 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 @@ 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 @@ 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); } } Index: source/Core/Debugger.cpp =================================================================== --- source/Core/Debugger.cpp +++ source/Core/Debugger.cpp @@ -927,6 +927,18 @@ 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) { Index: source/Interpreter/CommandInterpreter.cpp =================================================================== --- source/Interpreter/CommandInterpreter.cpp +++ source/Interpreter/CommandInterpreter.cpp @@ -1170,17 +1170,24 @@ 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 +1197,9 @@ 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 +1220,7 @@ 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 +1231,8 @@ result.AppendMessage(""); } - result.AppendMessage("For more information on any particular command, try 'help '."); + result.AppendMessageWithFormat("For more information on any command, type '%shelp '.\n", + GetCommandPrefix()); } CommandObject * @@ -2496,6 +2505,13 @@ } } +const char * +CommandInterpreter::GetCommandPrefix() +{ + const char * prefix = GetDebugger().GetIOHandlerCommandPrefix(); + return prefix == NULL ? "" : prefix; +} + PlatformSP CommandInterpreter::GetPlatform (bool prefer_target_platform) { @@ -2887,87 +2903,77 @@ 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; + 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 (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') + strm.IndentMore (prefix_width); + while (line_start < help_text_end) { - 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) + // 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) { - 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) + 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; } + ++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(); - 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; - } + // 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 CommandInterpreter::OutputHelpText (Stream &strm, const char *word_text, const char *separator,