llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Raphael Isemann (Teemperor) <details> <summary>Changes</summary> LLDB has an autosuggestion feature that shows previous commands that start with the current command line invocation. These commands are shown in a faint color after the command line. As an alternative to this mode, this patch adds a tab-mode to the autosuggestions. We no longer show previous commands, but instead just show what the tab-completion would complete if the user pressed tab. This makes LLDB's command line a bit less frustrating to explore for users that don't want to enable the full autosuggestion feature. --- Full diff: https://github.com/llvm/llvm-project/pull/206728.diff 6 Files Affected: - (modified) lldb/include/lldb/Core/Debugger.h (+1-1) - (modified) lldb/include/lldb/lldb-private-enumerations.h (+11) - (modified) lldb/source/Core/CoreProperties.td (+4-3) - (modified) lldb/source/Core/Debugger.cpp (+23-3) - (modified) lldb/source/Core/IOHandler.cpp (+15-1) - (modified) lldb/test/API/iohandler/autosuggestion/TestAutosuggestion.py (+76) ``````````diff diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index fff514fed156d..05b1bd83e32fd 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -348,7 +348,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>, llvm::StringRef GetDisabledAnsiSuffix() const; - bool GetUseAutosuggestion() const; + AutosuggestionMode GetAutosuggestionMode() const; llvm::StringRef GetAutosuggestionAnsiPrefix() const; diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h index a6965657f5bc9..f6278dbc74325 100644 --- a/lldb/include/lldb/lldb-private-enumerations.h +++ b/lldb/include/lldb/lldb-private-enumerations.h @@ -257,6 +257,17 @@ enum class IterationAction { Stop, }; +/// Controls how the `show-autosuggestion` setting drives inline suggestions +/// in the interactive command line. +enum AutosuggestionMode { + /// Do not show any autosuggestion. + eAutosuggestionOff = 0, + /// Show a suggestion sourced from previously entered commands. + eAutosuggestionOn = 1, + /// Show the prefix that tab completion would insert for the current line. + eAutosuggestionTabMode = 2, +}; + /// Specifies the type of PCs when creating a `HistoryThread`. /// - `Returns` - Usually, when LLDB unwinds the stack or we retrieve a stack /// trace via `backtrace()` we are collecting return addresses (except for the diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td index 8cea0931868aa..97bfd4a361032 100644 --- a/lldb/source/Core/CoreProperties.td +++ b/lldb/source/Core/CoreProperties.td @@ -260,10 +260,11 @@ let Definition = "debugger", Path = "" in { Global, DefaultStringValue<"frame #${frame.index}: {${ansi.fg.cyan}${frame.pc}${ansi.normal} }{${module.file.basename}{`}}{${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">, Desc<"The default frame format string to use when displaying stack frame information for threads from thread backtrace unique.">; - def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">, + def ShowAutosuggestion: Property<"show-autosuggestion", "Enum">, Global, - DefaultFalse, - Desc<"If true, LLDB will show suggestions to complete the command the user typed. Suggestions may be accepted using Ctrl-F.">; + DefaultEnumValue<"eAutosuggestionOff">, + EnumValues<"OptionEnumValues(g_show_autosuggestion_enum_values)">, + Desc<"Controls whether LLDB shows suggestions to complete the command the user typed. Suggestions may be accepted using Ctrl-F. Use 'true' to suggest from previously entered commands, 'tab-mode' to suggest the prefix that would be inserted by tab completion, or 'false' to disable suggestions.">; def ShowAutosuggestionAnsiPrefix: Property<"show-autosuggestion-ansi-prefix", "String">, Global, DefaultStringValue<"${ansi.faint}">, diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index b2e6fe66dc29e..413e74aa37292 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -195,6 +195,25 @@ static constexpr OptionEnumValueElement s_stop_show_column_values[] = { }, }; +static constexpr OptionEnumValueElement g_show_autosuggestion_enum_values[] = { + { + eAutosuggestionOff, + "false", + "Do not show any autosuggestion.", + }, + { + eAutosuggestionOn, + "true", + "Show a suggestion sourced from previously entered commands.", + }, + { + eAutosuggestionTabMode, + "tab-mode", + "Show the prefix that tab completion would insert for the current " + "line.", + }, +}; + #define LLDB_PROPERTIES_debugger #include "CoreProperties.inc" @@ -600,10 +619,11 @@ bool Debugger::SetSeparator(llvm::StringRef s) { return ret; } -bool Debugger::GetUseAutosuggestion() const { +AutosuggestionMode Debugger::GetAutosuggestionMode() const { const uint32_t idx = ePropertyShowAutosuggestion; - return GetPropertyAtIndexAs<bool>( - idx, g_debugger_properties[idx].default_uint_value != 0); + return GetPropertyAtIndexAs<AutosuggestionMode>( + idx, static_cast<AutosuggestionMode>( + g_debugger_properties[idx].default_uint_value)); } llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const { diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp index 5cc15ad2ed6ff..f19fe3204ddf5 100644 --- a/lldb/source/Core/IOHandler.cpp +++ b/lldb/source/Core/IOHandler.cpp @@ -266,7 +266,7 @@ IOHandlerEditline::IOHandlerEditline( }); m_editline_up->SetRedrawCallback([this]() { this->RedrawCallback(); }); - if (debugger.GetUseAutosuggestion()) { + if (debugger.GetAutosuggestionMode() != eAutosuggestionOff) { m_editline_up->SetSuggestionCallback([this](llvm::StringRef line) { return this->SuggestionCallback(line); }); @@ -440,6 +440,20 @@ int IOHandlerEditline::FixIndentationCallback(Editline *editline, std::optional<std::string> IOHandlerEditline::SuggestionCallback(llvm::StringRef line) { + // In tab-mode, we just display what tab would complete if the user + // would tab. + if (m_debugger.GetAutosuggestionMode() == eAutosuggestionTabMode) { + CompletionResult result; + CompletionRequest request(line, line.size(), result); + m_delegate.IOHandlerComplete(*this, request); + StringList matches; + result.GetMatches(matches); + std::string longest_prefix = matches.LongestCommonPrefix(); + llvm::StringRef cursor_arg_prefix = request.GetCursorArgumentPrefix(); + if (longest_prefix.size() > cursor_arg_prefix.size()) + return longest_prefix.substr(cursor_arg_prefix.size()); + return std::nullopt; + } return m_delegate.IOHandlerSuggestion(*this, line); } diff --git a/lldb/test/API/iohandler/autosuggestion/TestAutosuggestion.py b/lldb/test/API/iohandler/autosuggestion/TestAutosuggestion.py index 401b06f6c9b49..2c287eeeef676 100644 --- a/lldb/test/API/iohandler/autosuggestion/TestAutosuggestion.py +++ b/lldb/test/API/iohandler/autosuggestion/TestAutosuggestion.py @@ -154,3 +154,79 @@ def test_autosuggestion_custom_ansi_prefix_suffix(self): self.child.expect_exact(self.ANSI_RED + "ame variable" + self.ANSI_CYAN) self.child.send("\n") + @skipIfAsan + @skipIfEditlineSupportMissing + def test_autosuggestion_tab_mode(self): + """Test that show-autosuggestion=tab-mode suggests the prefix that + tab completion would insert, instead of consulting command history.""" + self.launch( + use_colors=True, + extra_args=[ + "-o", + "settings set show-autosuggestion tab-mode", + "-o", + "settings set use-color true", + ], + ) + + ctrl_f = "\x06" + + # Put 'help frame' into the session history. If tab-mode incorrectly + # consulted history (as the 'true' mode does), typing 'hel' would + # suggest 'p frame'. In tab-mode the suggestion should be just 'p', + # since the only tab completion of 'hel' is 'help'. + frame_output_needle = "Syntax: frame <subcommand>" + self.expect("help frame", substrs=[frame_output_needle]) + + self.child.send("hel") + # Note that the ANSI_RESET color prevents us from accepting a longer + # suggestion as a valid test outcome. + self.child.expect_exact( + cursor_horizontal_abs("(lldb) he") + + "l" + + self.ANSI_FAINT + + "p" + + self.ANSI_RESET + ) + + # Applying the suggestion with Ctrl-F should leave the line as 'help' + # (not 'help frame'). Running it lists all commands. + self.child.send(ctrl_f + "\n") + self.child.expect_exact("Debugger commands:") + + # Tab completion must still work in tab-mode. Pressing tab on 'hel' + # should complete to 'help'; running it lists all commands. + self.child.send("hel\t\n") + self.child.expect_exact("Debugger commands:") + + @skipIfAsan + @skipIfEditlineSupportMissing + def test_autosuggestion_tab_mode_no_common_prefix(self): + """Test that show-autosuggestion=tab-mode shows no suggestion when + the tab completions don't share a prefix beyond what the user typed.""" + self.launch( + use_colors=True, + extra_args=[ + "-o", + "settings set show-autosuggestion tab-mode", + "-o", + "settings set use-color true", + ], + ) + + ctrl_f = "\x06" + + # 'se' matches several top-level commands (session, settings, ...) + # whose longest common prefix is 'se' itself, so tab-mode must not + # show any suggestion. Pressing Ctrl-F should therefore do nothing + # and running the line should yield the 'ambiguous command' error. + self.child.send("se" + ctrl_f + "\n") + self.child.expect_exact("ambiguous command 'se'") + + # Tab completion must still work in tab-mode even when there is no + # common prefix to suggest: pressing tab on 'se' should list the + # available completions. + self.child.send("se\t") + self.child.expect_exact("session") + self.child.expect_exact("settings") + `````````` </details> https://github.com/llvm/llvm-project/pull/206728 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
