Path: blob/main/contrib/llvm-project/lldb/source/Core/Statusline.cpp
213765 views
//===-- Statusline.cpp ---------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Core/Statusline.h"9#include "lldb/Core/Debugger.h"10#include "lldb/Core/FormatEntity.h"11#include "lldb/Host/StreamFile.h"12#include "lldb/Interpreter/CommandInterpreter.h"13#include "lldb/Symbol/SymbolContext.h"14#include "lldb/Target/Process.h"15#include "lldb/Target/StackFrame.h"16#include "lldb/Utility/AnsiTerminal.h"17#include "lldb/Utility/StreamString.h"18#include "llvm/ADT/StringRef.h"19#include "llvm/Support/Locale.h"2021#define ESCAPE "\x1b"22#define ANSI_NORMAL ESCAPE "[0m"23#define ANSI_SAVE_CURSOR ESCAPE "7"24#define ANSI_RESTORE_CURSOR ESCAPE "8"25#define ANSI_CLEAR_BELOW ESCAPE "[J"26#define ANSI_CLEAR_SCREEN ESCAPE "[2J"27#define ANSI_SET_SCROLL_ROWS ESCAPE "[1;%ur"28#define ANSI_TO_START_OF_ROW ESCAPE "[%u;1f"29#define ANSI_REVERSE_VIDEO ESCAPE "[7m"30#define ANSI_UP_ROWS ESCAPE "[%dA"3132using namespace lldb;33using namespace lldb_private;3435Statusline::Statusline(Debugger &debugger)36: m_debugger(debugger), m_terminal_width(m_debugger.GetTerminalWidth()),37m_terminal_height(m_debugger.GetTerminalHeight()) {38Enable();39}4041Statusline::~Statusline() { Disable(); }4243void Statusline::TerminalSizeChanged() {44m_terminal_width = m_debugger.GetTerminalWidth();45m_terminal_height = m_debugger.GetTerminalHeight();4647UpdateScrollWindow(ResizeStatusline);4849// Draw the old statusline.50Redraw(/*update=*/false);51}5253void Statusline::Enable() {54// Reduce the scroll window to make space for the status bar below.55UpdateScrollWindow(EnableStatusline);5657// Draw the statusline.58Redraw(/*update=*/true);59}6061void Statusline::Disable() {62// Extend the scroll window to cover the status bar.63UpdateScrollWindow(DisableStatusline);64}6566void Statusline::Draw(std::string str) {67lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();68if (!stream_sp)69return;7071m_last_str = str;7273str = ansi::TrimAndPad(str, m_terminal_width);7475LockedStreamFile locked_stream = stream_sp->Lock();76locked_stream << ANSI_SAVE_CURSOR;77locked_stream.Printf(ANSI_TO_START_OF_ROW,78static_cast<unsigned>(m_terminal_height));7980// Use "reverse video" to make sure the statusline has a background. Only do81// this when colors are disabled, and rely on the statusline format otherwise.82if (!m_debugger.GetUseColor())83locked_stream << ANSI_REVERSE_VIDEO;8485locked_stream << str;86locked_stream << ANSI_NORMAL;87locked_stream << ANSI_RESTORE_CURSOR;88}8990void Statusline::UpdateScrollWindow(ScrollWindowMode mode) {91assert(m_terminal_width != 0 && m_terminal_height != 0);9293lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();94if (!stream_sp)95return;9697const unsigned reduced_scroll_window = m_terminal_height - 1;98LockedStreamFile locked_stream = stream_sp->Lock();99100switch (mode) {101case EnableStatusline:102// Move everything on the screen up.103locked_stream << '\n';104locked_stream.Printf(ANSI_UP_ROWS, 1);105// Reduce the scroll window.106locked_stream << ANSI_SAVE_CURSOR;107locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_window);108locked_stream << ANSI_RESTORE_CURSOR;109break;110case DisableStatusline:111// Reset the scroll window.112locked_stream << ANSI_SAVE_CURSOR;113locked_stream.Printf(ANSI_SET_SCROLL_ROWS, 0);114locked_stream << ANSI_RESTORE_CURSOR;115// Clear the screen below to hide the old statusline.116locked_stream << ANSI_CLEAR_BELOW;117break;118case ResizeStatusline:119// Clear the screen and update the scroll window.120// FIXME: Find a better solution (#146919).121locked_stream << ANSI_CLEAR_SCREEN;122locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_window);123break;124}125126m_debugger.RefreshIOHandler();127}128129void Statusline::Redraw(bool update) {130if (!update) {131Draw(m_last_str);132return;133}134135ExecutionContext exe_ctx = m_debugger.GetSelectedExecutionContext();136137// For colors and progress events, the format entity needs access to the138// debugger, which requires a target in the execution context.139if (!exe_ctx.HasTargetScope())140exe_ctx.SetTargetPtr(&m_debugger.GetSelectedOrDummyTarget());141142SymbolContext symbol_ctx;143if (ProcessSP process_sp = exe_ctx.GetProcessSP()) {144// Check if the process is stopped, and if it is, make sure it remains145// stopped until we've computed the symbol context.146Process::StopLocker stop_locker;147if (stop_locker.TryLock(&process_sp->GetRunLock())) {148if (auto frame_sp = exe_ctx.GetFrameSP())149symbol_ctx = frame_sp->GetSymbolContext(eSymbolContextEverything);150}151}152153StreamString stream;154FormatEntity::Entry format = m_debugger.GetStatuslineFormat();155FormatEntity::Format(format, stream, &symbol_ctx, &exe_ctx, nullptr, nullptr,156false, false);157158Draw(stream.GetString().str());159}160161162