[Lldb-commits] [lldb] [lldb] Implement a statusline in LLDB (PR #121860)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Jan 22 08:02:54 PST 2025


================
@@ -0,0 +1,161 @@
+//===-- Statusline.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/Statusline.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FormatEntity.h"
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Utility/AnsiTerminal.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamString.h"
+#include "llvm/Support/Locale.h"
+
+#include <sys/ioctl.h>
+#include <termios.h>
+
+#define ESCAPE "\x1b"
+#define ANSI_SAVE_CURSOR ESCAPE "7"
+#define ANSI_RESTORE_CURSOR ESCAPE "8"
+#define ANSI_CLEAR_BELOW ESCAPE "[J"
+#define ANSI_CLEAR_LINE "\r\x1B[2K"
+#define ANSI_SET_SCROLL_ROWS ESCAPE "[0;%ur"
+#define ANSI_TO_START_OF_ROW ESCAPE "[%u;0f"
+#define ANSI_UP_ROWS ESCAPE "[%dA"
+#define ANSI_DOWN_ROWS ESCAPE "[%dB"
+#define ANSI_FORWARD_COLS ESCAPE "\033[%dC"
+#define ANSI_BACKWARD_COLS ESCAPE "\033[%dD"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static size_t ColumnWidth(llvm::StringRef str) {
+  std::string stripped = ansi::StripAnsiTerminalCodes(str);
+  return llvm::sys::locale::columnWidth(stripped);
+}
+
+Statusline::Statusline(Debugger &debugger) : m_debugger(debugger) {}
+
+Statusline::~Statusline() { Disable(); }
+
+bool Statusline::IsSupported() const {
+  File &file = m_debugger.GetOutputFile();
+  return file.GetIsInteractive() && file.GetIsTerminalWithColors();
+}
+
+void Statusline::Enable() {
+  if (!IsSupported())
+    return;
+
+  UpdateTerminalProperties();
+
+  // Reduce the scroll window to make space for the status bar below.
+  SetScrollWindow(m_terminal_height - 1);
+
+  // Draw the statusline.
+  Update();
+}
+
+void Statusline::Disable() {
+  UpdateTerminalProperties();
+  // Clear the previous status bar if any.
+  Clear();
+  // Extend the scroll window to cover the status bar.
+  SetScrollWindow(m_terminal_height);
+}
+
+void Statusline::Draw(llvm::StringRef str) {
+  UpdateTerminalProperties();
+
+  const size_t ellipsis = 3;
+  const size_t column_width = ColumnWidth(str);
+
+  if (column_width + ellipsis >= m_terminal_width)
+    str = str.substr(0, m_terminal_width - ellipsis);
+
+  StreamFile &out = m_debugger.GetOutputStream();
+  out << ANSI_SAVE_CURSOR;
+  out.Printf(ANSI_TO_START_OF_ROW, static_cast<unsigned>(m_terminal_height));
+  out << ANSI_CLEAR_LINE;
+  out << str;
+  out << std::string(m_terminal_width - column_width, ' ');
+  out << ansi::FormatAnsiTerminalCodes(k_ansi_suffix);
+  out << ANSI_RESTORE_CURSOR;
+}
+
+void Statusline::Reset() {
+  StreamFile &out = m_debugger.GetOutputStream();
+  out << ANSI_SAVE_CURSOR;
+  out.Printf(ANSI_TO_START_OF_ROW, static_cast<unsigned>(m_terminal_height));
+  out << ANSI_CLEAR_LINE;
+  out << ANSI_RESTORE_CURSOR;
+}
+
+void Statusline::Clear() { Draw(""); }
+
+void Statusline::UpdateTerminalProperties() {
+  if (m_terminal_size_has_changed == 0)
+    return;
+
+  // Clear the previous statusline.
+  Reset();
+
+  // Purposely ignore the terminal settings. If the setting doesn't match
+  // reality and we draw the status bar over existing text, we have no way to
+  // recover.
+  struct winsize window_size;
+  if ((isatty(STDIN_FILENO) != 0) &&
+      ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
----------------
labath wrote:

- this won't build on windows (it only works in the lldb driver because of a very ugly hack in `driver/Platform.cpp`)
- Shouldn't this be getting file/fd from the debuggers stdin?
- actually maybe stdout, since stdin might be redirected?
- I'm not convinced this is the right thing to do anyway. What's this trying to fix/work around?

https://github.com/llvm/llvm-project/pull/121860


More information about the lldb-commits mailing list