Author: David Spickett Date: 2026-05-08T11:14:40+01:00 New Revision: beb3a1cdab7fe65521c8e94092084092a22c686d
URL: https://github.com/llvm/llvm-project/commit/beb3a1cdab7fe65521c8e94092084092a22c686d DIFF: https://github.com/llvm/llvm-project/commit/beb3a1cdab7fe65521c8e94092084092a22c686d.diff LOG: Revert "[lldb] Real-time console pane for output in lldb tui (#177160)" This reverts commit 7578a9ad9361a6589fcfd89a36a24496cb6b5ec4. Added: Modified: lldb/include/lldb/Core/Debugger.h lldb/source/Core/CoreProperties.td lldb/source/Core/Debugger.cpp lldb/source/Core/IOHandlerCursesGUI.cpp llvm/docs/ReleaseNotes.md Removed: lldb/test/API/commands/gui/console-output/Makefile lldb/test/API/commands/gui/console-output/TestGuiConsoleOutput.py lldb/test/API/commands/gui/console-output/main.cpp ################################################################################ diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index 82d86f988f07f..e53e916d78cc1 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -406,8 +406,6 @@ class Debugger : public std::enable_shared_from_this<Debugger>, bool SetShowInlineDiagnostics(bool); - uint64_t GetGuiMaxConsoleLines() const; - bool LoadPlugin(const FileSpec &spec, Status &error); void RunIOHandlers(); diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td index e4a565e97b81f..8cea0931868aa 100644 --- a/lldb/source/Core/CoreProperties.td +++ b/lldb/source/Core/CoreProperties.td @@ -293,8 +293,4 @@ let Definition = "debugger", Path = "" in { Global, DefaultFalse, Desc<"Controls whether diagnostics can refer directly to the command input, drawing arrows to it. If false, diagnostics will echo the input.">; - def GuiMaxConsoleLines: Property<"gui-console-max-lines", "UInt64">, - Global, - DefaultUnsignedValue<10000>, - Desc<"The maximum number of lines to keep in the console output window.">; } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index e9fe71108c572..48e03881fa3b5 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -780,12 +780,6 @@ bool Debugger::SetShowInlineDiagnostics(bool b) { return SetPropertyAtIndex(idx, b); } -uint64_t Debugger::GetGuiMaxConsoleLines() const { - const uint32_t idx = ePropertyGuiMaxConsoleLines; - return GetPropertyAtIndexAs<uint64_t>( - idx, g_debugger_properties[idx].default_uint_value); -} - #pragma mark Debugger // const DebuggerPropertiesSP & diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index ff2cd2777af67..5b70917f11cbd 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -327,8 +327,6 @@ class WindowDelegate { virtual const char *WindowDelegateGetHelpText() { return nullptr; } virtual KeyHelp *WindowDelegateGetKeyHelp() { return nullptr; } - - virtual void WindowDelegateProcessEvent(const lldb::EventSP &event_sp) {} }; class HelpDialogDelegate : public WindowDelegate { @@ -801,13 +799,6 @@ class Window : public Surface { subwindow_sp->Draw(force); } - void HandleProcessEvent(const lldb::EventSP &event_sp) { - if (m_delegate_sp) - m_delegate_sp->WindowDelegateProcessEvent(event_sp); - for (auto &subwindow_sp : m_subwindows) - subwindow_sp->HandleProcessEvent(event_sp); - } - bool CreateHelpSubwindow() { if (m_delegate_sp) { const char *text = m_delegate_sp->WindowDelegateGetHelpText(); @@ -4394,11 +4385,6 @@ class Application { ConstString broadcaster_class( broadcaster->GetBroadcasterClass()); if (broadcaster_class == broadcaster_class_process) { - uint32_t event_type = event_sp->GetType(); - if (event_type & (Process::eBroadcastBitSTDOUT | - Process::eBroadcastBitSTDERR)) { - m_window_sp->HandleProcessEvent(event_sp); - } m_update_screen = true; continue; // Don't get any key, just update our view } @@ -6325,233 +6311,6 @@ HandleCharResult HelpDialogDelegate::WindowDelegateHandleChar(Window &window, return eKeyHandled; } -class ConsoleOutputWindowDelegate : public WindowDelegate { -private: - void PollProcessOutput() { - ExecutionContext exe_ctx = - m_debugger.GetCommandInterpreter().GetExecutionContext(); - Process *process = exe_ctx.GetProcessPtr(); - - if (!process || !process->IsAlive()) - return; - - // Buffer for reading output. - char buffer[1024]; - Status error; - - // Read all available stdout. - size_t bytes; - while ((bytes = process->GetSTDOUT(buffer, sizeof(buffer), error)) > 0) - AppendOutput(buffer, bytes, false); - - // Read all available stderr. - while ((bytes = process->GetSTDERR(buffer, sizeof(buffer), error)) > 0) - AppendOutput(buffer, bytes, true); - } - - void AppendOutput(const char *text, size_t len, bool is_stderr) { - if (!text || len == 0) - return; - - std::lock_guard<std::mutex> lock(m_output_mutex); - - // Split text into lines and add to buffer. - std::string remaining = m_partial_line; - remaining.append(text, len); - - size_t start = 0, pos = 0; - while ((pos = remaining.find('\n', start)) != std::string::npos) { - std::string line = remaining.substr(start, pos - start); - if (is_stderr) - line = "[stderr] " + line; - m_output_lines.push_back(line); - - // Keep buffer size under limit. - size_t max_lines = m_debugger.GetGuiMaxConsoleLines(); - while (m_output_lines.size() > max_lines) { - m_output_lines.pop_front(); - if (m_first_visible_line > 0) - --m_first_visible_line; - } - - start = pos + 1; - } - - // Save any remaining partial line. - m_partial_line = remaining.substr(start); - - // Auto-scroll to bottom if enabled. - if (m_auto_scroll && !m_output_lines.empty()) { - m_first_visible_line = - m_output_lines.size() > 0 ? m_output_lines.size() - 1 : 0; - } - } - -public: - ConsoleOutputWindowDelegate(Debugger &debugger) - : m_debugger(debugger), m_first_visible_line(0), m_auto_scroll(true) {} - - ~ConsoleOutputWindowDelegate() override = default; - - void WindowDelegateProcessEvent(const lldb::EventSP &event_sp) override { - if (event_sp->GetType() & - (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitSTDERR)) - PollProcessOutput(); - } - - bool WindowDelegateDraw(Window &window, bool force) override { - std::lock_guard<std::mutex> lock(m_output_mutex); - - window.Erase(); - window.DrawTitleBox(window.GetName()); - - const int width = window.GetWidth(); - const int height = window.GetHeight(); - - // Calculate the visible range. - size_t total_lines = m_output_lines.size(); - if (total_lines == 0) { - window.MoveCursor(2, 1); - window.PutCString("(no output yet)"); - return true; - } - - // Adjust scroll pos if needed. - if (m_first_visible_line >= total_lines) { - m_first_visible_line = total_lines > 0 ? total_lines - 1 : 0; - } - - // Draw visible line. - int visible_height = height - 2; - size_t start_line = m_first_visible_line; - - // If we are at the end, display last N lines. - if (m_auto_scroll || start_line + visible_height > total_lines) { - start_line = total_lines > static_cast<size_t>(visible_height) - ? total_lines - visible_height - : 0; - } - - for (int row = 1; - row <= visible_height && (start_line + row - 1) < total_lines; ++row) { - window.MoveCursor(2, row); - const std::string &line = m_output_lines[start_line + row - 1]; - - // Highlight stderr lines?. - bool is_stderr = (line.find("[stderr]") == 0); - if (is_stderr) - window.AttributeOn(COLOR_PAIR(2)); - - // Truncate line to fit window width. - int available_width = width - 3; - if (static_cast<int>(line.length()) > available_width) - window.PutCString(line.substr(0, available_width).c_str()); - else - window.PutCString(line.c_str()); - - if (is_stderr) - window.AttributeOff(COLOR_PAIR(2)); - } - - return true; - } - - HandleCharResult WindowDelegateHandleChar(Window &window, int key) override { - std::lock_guard<std::mutex> lock(m_output_mutex); - - size_t total_lines = m_output_lines.size(); - int visible_height = window.GetHeight() - 1; - - switch (key) { - case KEY_UP: - if (m_first_visible_line > 0) { - --m_first_visible_line; - m_auto_scroll = false; - } - return eKeyHandled; - - case KEY_DOWN: - if (m_first_visible_line + visible_height < total_lines) - ++m_first_visible_line; - // Re-enable Auto-scroll at bottom. - if (m_first_visible_line + visible_height >= total_lines) - m_auto_scroll = true; - return eKeyHandled; - - case KEY_PPAGE: - if (m_first_visible_line > static_cast<size_t>(visible_height)) - m_first_visible_line -= visible_height; - else - m_first_visible_line = 0; - m_auto_scroll = false; - return eKeyHandled; - - case KEY_NPAGE: - m_first_visible_line += visible_height; - if (m_first_visible_line + visible_height >= total_lines) { - m_first_visible_line = total_lines > static_cast<size_t>(visible_height) - ? total_lines - visible_height - : 0; - m_auto_scroll = true; - } - return eKeyHandled; - - case 'a': - m_auto_scroll = !m_auto_scroll; - if (m_auto_scroll && total_lines > 0) - m_first_visible_line = total_lines > static_cast<size_t>(visible_height) - ? total_lines - visible_height - : 0; - return eKeyHandled; - - case 'c': - m_output_lines.clear(); - m_partial_line.clear(); - m_first_visible_line = 0; - return eKeyHandled; - - case KEY_HOME: - m_first_visible_line = 0; - m_auto_scroll = false; - return eKeyHandled; - - case KEY_END: - m_first_visible_line = total_lines > static_cast<size_t>(visible_height) - ? total_lines - visible_height - : 0; - m_auto_scroll = true; - return eKeyHandled; - - default: - break; - } - - return eKeyNotHandled; - } - - const char *WindowDelegateGetHelpText() override { - return "Console Output view shows stdout and stderr from the process."; - } - - KeyHelp *WindowDelegateGetKeyHelp() override { - static curses::KeyHelp g_source_view_key_help[] = { - {KEY_UP, "Scroll up"}, {KEY_DOWN, "Scroll down"}, - {KEY_PPAGE, "Page up"}, {KEY_NPAGE, "Page down"}, - {KEY_HOME, "Go to top"}, {KEY_END, "Go to bottom"}, - {'h', "Show help dialog"}, {'a', "Toggle auto-scroll"}, - {'c', "Clear output"}, {'\0', nullptr}}; - return g_source_view_key_help; - } - -protected: - Debugger &m_debugger; - std::deque<std::string> m_output_lines; - std::string m_partial_line; - size_t m_first_visible_line = 0; - bool m_auto_scroll = true; - std::mutex m_output_mutex; -}; - class ApplicationDelegate : public WindowDelegate, public MenuDelegate { public: enum { @@ -6583,7 +6342,6 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { eMenuID_ViewSource, eMenuID_ViewVariables, eMenuID_ViewBreakpoints, - eMenuId_ViewConsole, eMenuID_Help, eMenuID_HelpGUIHelp @@ -6594,14 +6352,6 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { ~ApplicationDelegate() override = default; - WindowDelegateSP GetConsoleDelegate() { - if (!m_console_delegate_sp) { - m_console_delegate_sp = - WindowDelegateSP(new ConsoleOutputWindowDelegate(m_debugger)); - } - return m_console_delegate_sp; - } - bool WindowDelegateDraw(Window &window, bool force) override { return false; // Drawing not handled, let standard window drawing happen } @@ -6832,7 +6582,6 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { WindowSP main_window_sp = m_app.GetMainWindow(); WindowSP source_window_sp = main_window_sp->FindSubWindow("Source"); WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables"); - WindowSP console_window_sp = main_window_sp->FindSubWindow("Console"); WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers"); const Rect source_bounds = source_window_sp->GetBounds(); @@ -6841,52 +6590,39 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { main_window_sp->RemoveSubWindow(variables_window_sp.get()); - if (console_window_sp) { - Rect console_bounds = console_window_sp->GetBounds(); - console_bounds.origin.x = variables_bounds.origin.x; - console_bounds.size.width = - variables_bounds.size.width + console_bounds.size.width; - console_window_sp->SetBounds(console_bounds); - } else if (registers_window_sp) { + if (registers_window_sp) { // We have a registers window, so give all the area back to the - // registers window. + // registers window Rect registers_bounds = variables_bounds; registers_bounds.size.width = source_bounds.size.width; registers_window_sp->SetBounds(registers_bounds); } else { - // We have no console or registers window showing so give the bottom - // area back to the source view. + // We have no registers window showing so give the bottom area back + // to the source view source_window_sp->Resize(source_bounds.size.width, source_bounds.size.height + variables_bounds.size.height); } } else { - Rect new_vars_rect; - if (console_window_sp) { - // Console exists, so split the area. - const Rect console_bounds = console_window_sp->GetBounds(); - Rect new_console_rect; - console_bounds.VerticalSplitPercentage(0.50, new_vars_rect, - new_console_rect); - } else if (registers_window_sp) { + Rect new_variables_rect; + if (registers_window_sp) { // We have a registers window so split the area of the registers // window into two columns where the left hand side will be the - // variables and the right hand side will be the registers. - const Rect registers_bounds = registers_window_sp->GetBounds(); - Rect new_regs_rect; - registers_bounds.VerticalSplitPercentage(0.50, new_vars_rect, - new_regs_rect); - registers_window_sp->SetBounds(new_regs_rect); + // variables and the right hand side will be the registers + const Rect variables_bounds = registers_window_sp->GetBounds(); + Rect new_registers_rect; + variables_bounds.VerticalSplitPercentage(0.50, new_variables_rect, + new_registers_rect); + registers_window_sp->SetBounds(new_registers_rect); } else { - // No registers or console window, grab the bottom part of the source - // window. + // No registers window, grab the bottom part of the source window Rect new_source_rect; source_bounds.HorizontalSplitPercentage(0.70, new_source_rect, - new_vars_rect); + new_variables_rect); source_window_sp->SetBounds(new_source_rect); } - WindowSP new_window_sp = - main_window_sp->CreateSubWindow("Variables", new_vars_rect, false); + WindowSP new_window_sp = main_window_sp->CreateSubWindow( + "Variables", new_variables_rect, false); new_window_sp->SetDelegate( WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger))); } @@ -6906,13 +6642,13 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { const Rect variables_bounds = variables_window_sp->GetBounds(); // We have a variables window, so give all the area back to the - // variables window. + // variables window variables_window_sp->Resize(variables_bounds.size.width + registers_window_sp->GetWidth(), variables_bounds.size.height); } else { // We have no variables window showing so give the bottom area back - // to the source view. + // to the source view source_window_sp->Resize(source_bounds.size.width, source_bounds.size.height + registers_window_sp->GetHeight()); @@ -6923,14 +6659,14 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { if (variables_window_sp) { // We have a variables window, split it into two columns where the // left hand side will be the variables and the right hand side will - // be the registers. + // be the registers const Rect variables_bounds = variables_window_sp->GetBounds(); Rect new_vars_rect; variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect, new_regs_rect); variables_window_sp->SetBounds(new_vars_rect); } else { - // No variables window, grab the bottom part of the source window. + // No variables window, grab the bottom part of the source window Rect new_source_rect; source_bounds.HorizontalSplitPercentage(0.70, new_source_rect, new_regs_rect); @@ -6945,66 +6681,6 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { } return MenuActionResult::Handled; - case eMenuId_ViewConsole: { - WindowSP main_window_sp = m_app.GetMainWindow(); - WindowSP source_window_sp = main_window_sp->FindSubWindow("Source"); - WindowSP console_window_sp = main_window_sp->FindSubWindow("Console"); - WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables"); - WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers"); - const Rect source_bounds = source_window_sp->GetBounds(); - - if (console_window_sp) { - const Rect console_bounds = console_window_sp->GetBounds(); - main_window_sp->RemoveSubWindow(console_window_sp.get()); - - if (variables_window_sp) { - // Variables window exists, so give Console space to Variables. - Rect variables_bounds = variables_window_sp->GetBounds(); - variables_bounds.size.width = - variables_bounds.size.width + console_bounds.size.width; - variables_window_sp->SetBounds(variables_bounds); - } else if (registers_window_sp) { - // Registers window exists, so give Console space to Registers. - Rect registers_bounds = registers_window_sp->GetBounds(); - registers_bounds.size.width = source_bounds.size.width; - registers_window_sp->SetBounds(registers_bounds); - } else { - // No Variables or Registers window exists. - source_window_sp->Resize(source_bounds.size.width, - source_bounds.size.height + - console_bounds.size.height); - } - } else { - Rect new_console_rect; - if (variables_window_sp) { - // Variable window exists, split area. - const Rect variables_bounds = variables_window_sp->GetBounds(); - Rect new_vars_rect; - variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect, - new_console_rect); - variables_window_sp->SetBounds(new_vars_rect); - } else if (registers_window_sp) { - // Registers window exists, split area. - const Rect registers_bounds = registers_window_sp->GetBounds(); - Rect new_regs_rect; - registers_bounds.VerticalSplitPercentage(0.50, new_console_rect, - new_regs_rect); - registers_window_sp->SetBounds(new_regs_rect); - } else { - // No Registers or Variables window exists, split source area. - Rect new_source_rect; - source_bounds.HorizontalSplitPercentage(0.70, new_source_rect, - new_console_rect); - source_window_sp->SetBounds(new_source_rect); - } - WindowSP new_window_sp = - main_window_sp->CreateSubWindow("Console", new_console_rect, false); - new_window_sp->SetDelegate(GetConsoleDelegate()); - } - touchwin(stdscr); - } - return MenuActionResult::Handled; - case eMenuID_ViewBreakpoints: { WindowSP main_window_sp = m_app.GetMainWindow(); WindowSP threads_window_sp = main_window_sp->FindSubWindow("Threads"); @@ -7052,7 +6728,6 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { protected: Application &m_app; Debugger &m_debugger; - WindowDelegateSP m_console_delegate_sp; }; class StatusBarWindowDelegate : public WindowDelegate { @@ -7960,8 +7635,6 @@ void IOHandlerCursesGUI::Activate() { view_menu_sp->AddSubmenu( std::make_shared<Menu>("Breakpoints", nullptr, 'b', ApplicationDelegate::eMenuID_ViewBreakpoints)); - view_menu_sp->AddSubmenu(std::make_shared<Menu>( - "Console", nullptr, 'o', ApplicationDelegate::eMenuId_ViewConsole)); MenuSP help_menu_sp( new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help)); @@ -7985,16 +7658,12 @@ void IOHandlerCursesGUI::Activate() { Rect status_bounds = content_bounds.MakeStatusBar(); Rect source_bounds; Rect variables_bounds; - Rect console_bounds; Rect threads_bounds; Rect source_variables_bounds; - Rect variables_console_bounds; content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds, threads_bounds); source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds, - variables_console_bounds); - variables_console_bounds.VerticalSplitPercentage(0.50, variables_bounds, - console_bounds); + variables_bounds); WindowSP menubar_window_sp = main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false); @@ -8006,12 +7675,10 @@ void IOHandlerCursesGUI::Activate() { WindowSP source_window_sp( main_window_sp->CreateSubWindow("Source", source_bounds, true)); - WindowSP threads_window_sp( - main_window_sp->CreateSubWindow("Threads", threads_bounds, false)); WindowSP variables_window_sp( main_window_sp->CreateSubWindow("Variables", variables_bounds, false)); - WindowSP console_window_sp( - main_window_sp->CreateSubWindow("Console", console_bounds, false)); + WindowSP threads_window_sp( + main_window_sp->CreateSubWindow("Threads", threads_bounds, false)); WindowSP status_window_sp( main_window_sp->CreateSubWindow("Status", status_bounds, false)); status_window_sp->SetCanBeActive( @@ -8022,7 +7689,6 @@ void IOHandlerCursesGUI::Activate() { WindowDelegateSP(new SourceFileWindowDelegate(m_debugger))); variables_window_sp->SetDelegate( WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger))); - console_window_sp->SetDelegate(app_delegate_sp->GetConsoleDelegate()); TreeDelegateSP thread_delegate_sp(new ThreadsTreeDelegate(m_debugger)); threads_window_sp->SetDelegate(WindowDelegateSP( new TreeWindowDelegate(m_debugger, thread_delegate_sp))); diff --git a/lldb/test/API/commands/gui/console-output/Makefile b/lldb/test/API/commands/gui/console-output/Makefile deleted file mode 100644 index 3d0b98f13f3d7..0000000000000 --- a/lldb/test/API/commands/gui/console-output/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -CXX_SOURCES := main.cpp -include Makefile.rules diff --git a/lldb/test/API/commands/gui/console-output/TestGuiConsoleOutput.py b/lldb/test/API/commands/gui/console-output/TestGuiConsoleOutput.py deleted file mode 100644 index c21604a752b63..0000000000000 --- a/lldb/test/API/commands/gui/console-output/TestGuiConsoleOutput.py +++ /dev/null @@ -1,138 +0,0 @@ -""" -Test that the 'gui' console output pane displays stdout / stderr from the debugged process -""" - -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test.lldbpexpect import PExpectTest - - -class TestGuiConsoleOutputTest(PExpectTest): - # PExpect uses many timeouts internally and doesn't play well - # under ASAN on a loaded machine.. - @skipIfAsan - @skipIfCursesSupportMissing - def test_gui_console_output(self): - """Test that console pane prints messages""" - self.build() - - self.launch( - executable=self.getBuildArtifact("a.out"), - dimensions=(100, 500), - run_under=["env", "TERM=xterm"], - ) - - self.expect( - 'br set -o true -f main.cpp -p "// break here begin"', - substrs=["Breakpoint 1", "address ="], - ) - - self.expect( - 'br set -o true -f main.cpp -p "// break here end"', - substrs=["Breakpoint 2", "address ="], - ) - - self.expect("run", substrs=["stop reason ="]) - - escape_key = chr(27).encode() - - # Start the GUI. - self.child.sendline("gui") - - # Check for gui elements in Menu bar (top of screen) - # We expect these in the order they appear to avoid consumption issues - self.child.expect_exact("Target") - self.child.expect_exact("Process") - self.child.expect_exact("View") - - # Check for window titles (middle of screen) - self.child.expect_exact("Sources") - self.child.expect_exact("Console") - - # The Console window show this message before continuing - self.child.expect_exact("(no output yet)") - - # Continue program execution - self.child.send("c") - - # Check console output for messages - self.child.expect_exact("Hello from stdout line 1") - self.child.expect_exact("Hello from stderr line 3") - - # Check for large output (verify buffer draining) - self.child.expect_exact("Large output line 0") - self.child.expect_exact("Large output line 99") - - # Wait for Breakpoint 2 - self.child.expect_exact("stop reason") - - # Press escape to quit the gui - self.child.send(escape_key) - - self.expect_prompt() - self.quit() - - @skipIfAsan - @skipIfCursesSupportMissing - def test_gui_console_navigate(self): - """Test that console pane navigation works""" - self.build() - - self.launch( - executable=self.getBuildArtifact("a.out"), - dimensions=(100, 500), - run_under=["env", "TERM=xterm"], - ) - - self.expect( - 'br set -o true -f main.cpp -p "// break here begin"', - substrs=["Breakpoint 1", "address ="], - ) - - self.expect( - 'br set -o true -f main.cpp -p "// break here end"', - substrs=["Breakpoint 2", "address ="], - ) - - self.expect("run", substrs=["stop reason ="]) - - escape_key = chr(27).encode() - tab_key = chr(9).encode() - - # Start the GUI. - self.child.sendline("gui") - - # Match elements in top-to-bottom order - self.child.expect_exact("Target") - self.child.expect_exact("Sources") - self.child.expect_exact("Console") - - # The Console window show this message before continuing - self.child.expect_exact("(no output yet)") - - # Continue program execution - self.child.send("c") - - # Check console output for messages - self.child.expect_exact("Hello from stdout line 1") - - # Wait for Breakpoint 2 - self.child.expect_exact("stop reason") - - # Tab to console - self.child.send(tab_key) # Sources -> Threads - self.child.send(tab_key) # Threads -> Variables - self.child.send(tab_key) # Variables -> Console - - # Clear Console output - self.child.send("c") - - # The Console window show this message after clear - self.child.expect_exact("(no output yet)") - - # Press escape to quit the gui - self.child.send(escape_key) - - self.expect_prompt() - self.quit() diff --git a/lldb/test/API/commands/gui/console-output/main.cpp b/lldb/test/API/commands/gui/console-output/main.cpp deleted file mode 100644 index 9800cd50e04bd..0000000000000 --- a/lldb/test/API/commands/gui/console-output/main.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include <chrono> -#include <iostream> -#include <thread> - -void generate_output() { - for (unsigned i = 1; i < 4; ++i) { - std::cout << "Hello from stdout line " << i << std::endl; - std::cerr << "Hello from stderr line " << i << std::endl; - } -} - -void generate_large_output() { - for (unsigned i = 0; i < 100; ++i) { - std::cout << "Large output line " << i - << " to test buffer draining logic in the GUI console." - << std::endl; - } -} - -int main(int argc, char *argv[]) { - int test_var = 42; - - // Break before output. - int break_here = 0; // break here begin - - // Generate stdout/stderr output. - generate_output(); - generate_large_output(); - - // Wait to capture output. - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - return 0; // break here end -} diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index ec613d64e20a3..98f2205bc06a7 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -256,7 +256,6 @@ Makes programs 10x faster by doing Special New Thing. example, `breakpoint disable .` disables the just-hit breakpoint location. Another usage is to automate a command to run at the current location: `breakpoint command add -o 'p my_var' .`. * The `apropos` command now highlights matching keywords in its output when color is enabled. -* The TUI mode (enabled with the `gui` command) now has a real-time console output pane. stdout / stderr messages get redirected to this pane when it is enabled. #### Deprecated APIs _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
