brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · 922aada Raw
157 lines · cpp
1//===-- Statusline.cpp ---------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/Statusline.h"10#include "lldb/Core/Debugger.h"11#include "lldb/Core/FormatEntity.h"12#include "lldb/Host/StreamFile.h"13#include "lldb/Interpreter/CommandInterpreter.h"14#include "lldb/Symbol/SymbolContext.h"15#include "lldb/Target/Process.h"16#include "lldb/Target/StackFrame.h"17#include "lldb/Utility/AnsiTerminal.h"18#include "lldb/Utility/StreamString.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/Support/Locale.h"21 22#define ESCAPE "\x1b"23#define ANSI_NORMAL ESCAPE "[0m"24#define ANSI_SAVE_CURSOR ESCAPE "7"25#define ANSI_RESTORE_CURSOR ESCAPE "8"26#define ANSI_CLEAR_BELOW ESCAPE "[J"27#define ANSI_CLEAR_SCREEN ESCAPE "[2J"28#define ANSI_SET_SCROLL_ROWS ESCAPE "[1;%ur"29#define ANSI_TO_START_OF_ROW ESCAPE "[%u;1f"30#define ANSI_REVERSE_VIDEO ESCAPE "[7m"31#define ANSI_UP_ROWS ESCAPE "[%dA"32 33using namespace lldb;34using namespace lldb_private;35 36Statusline::Statusline(Debugger &debugger)37    : m_debugger(debugger), m_terminal_width(m_debugger.GetTerminalWidth()),38      m_terminal_height(m_debugger.GetTerminalHeight()) {}39 40Statusline::~Statusline() { Disable(); }41 42void Statusline::TerminalSizeChanged() {43  m_terminal_width = m_debugger.GetTerminalWidth();44  m_terminal_height = m_debugger.GetTerminalHeight();45 46  UpdateScrollWindow(ResizeStatusline);47 48  // Redraw the old statusline.49  Redraw(std::nullopt);50}51 52void Statusline::Enable(std::optional<ExecutionContextRef> exe_ctx_ref) {53  // Reduce the scroll window to make space for the status bar below.54  UpdateScrollWindow(EnableStatusline);55 56  // Draw the statusline.57  Redraw(exe_ctx_ref);58}59 60void Statusline::Disable() {61  // Extend the scroll window to cover the status bar.62  UpdateScrollWindow(DisableStatusline);63}64 65void Statusline::Draw(std::string str) {66  lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();67  if (!stream_sp)68    return;69 70  str = ansi::TrimAndPad(str, m_terminal_width);71 72  LockedStreamFile locked_stream = stream_sp->Lock();73  locked_stream << ANSI_SAVE_CURSOR;74  locked_stream.Printf(ANSI_TO_START_OF_ROW,75                       static_cast<unsigned>(m_terminal_height));76 77  // Use "reverse video" to make sure the statusline has a background. Only do78  // this when colors are disabled, and rely on the statusline format otherwise.79  if (!m_debugger.GetUseColor())80    locked_stream << ANSI_REVERSE_VIDEO;81 82  locked_stream << str;83  locked_stream << ANSI_NORMAL;84  locked_stream << ANSI_RESTORE_CURSOR;85}86 87void Statusline::UpdateScrollWindow(ScrollWindowMode mode) {88  assert(m_terminal_width != 0 && m_terminal_height != 0);89 90  lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();91  if (!stream_sp)92    return;93 94  const unsigned reduced_scroll_rows = m_terminal_height - 1;95  LockedStreamFile locked_stream = stream_sp->Lock();96 97  switch (mode) {98  case EnableStatusline:99    // Move everything on the screen up.100    locked_stream << '\n';101    locked_stream.Printf(ANSI_UP_ROWS, 1);102    // Reduce the scroll window.103    locked_stream << ANSI_SAVE_CURSOR;104    locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_rows);105    locked_stream << ANSI_RESTORE_CURSOR;106    break;107  case DisableStatusline:108    // Reset the scroll window.109    locked_stream << ANSI_SAVE_CURSOR;110    locked_stream.Printf(ANSI_SET_SCROLL_ROWS,111                         static_cast<unsigned>(m_terminal_height));112    locked_stream << ANSI_RESTORE_CURSOR;113    // Clear the screen below to hide the old statusline.114    locked_stream << ANSI_CLEAR_BELOW;115    break;116  case ResizeStatusline:117    // Clear the screen and update the scroll window.118    // FIXME: Find a better solution (#146919).119    locked_stream << ANSI_CLEAR_SCREEN;120    locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_rows);121    break;122  }123 124  m_debugger.RefreshIOHandler();125}126 127void Statusline::Redraw(std::optional<ExecutionContextRef> exe_ctx_ref) {128  // Update the cached execution context.129  if (exe_ctx_ref)130    m_exe_ctx_ref = *exe_ctx_ref;131 132  // Lock the execution context.133  ExecutionContext exe_ctx =134      m_exe_ctx_ref.Lock(/*thread_and_frame_only_if_stopped=*/false);135 136  // Compute the symbol context if we're stopped.137  SymbolContext sym_ctx;138  llvm::Expected<StoppedExecutionContext> stopped_exe_ctx =139      GetStoppedExecutionContext(&m_exe_ctx_ref);140  if (stopped_exe_ctx) {141    // The StoppedExecutionContext only ensures that we hold the run lock.142    // The process could be in an exited or unloaded state and have no frame.143    if (auto frame_sp = stopped_exe_ctx->GetFrameSP())144      sym_ctx = frame_sp->GetSymbolContext(eSymbolContextEverything);145  } else {146    // We can draw the statusline without being stopped.147    llvm::consumeError(stopped_exe_ctx.takeError());148  }149 150  StreamString stream;151  FormatEntity::Entry format = m_debugger.GetStatuslineFormat();152  FormatEntity::Format(format, stream, &sym_ctx, &exe_ctx, nullptr, nullptr,153                       false, false);154 155  Draw(stream.GetString().str());156}157