RFC: LLDB Statusline (original) (raw)

Objective

Add a statusline to command-line LLDB to display progress events and other information related to the current state of the debugger. The statusline is a dedicated area displayed the bottom of the screen. The contents of the status line are configurable through a setting consisting of LLDB’s format strings.

Motivation

LLDB’s current implementation to display progress events inline has several issue and limitations. The majority can be traced back to the lack of synchronization of stdout. The result is that progress events and output from the inferior or LLDB get mangled. LLDB’s abstractions over output streams provide no or limited synchronization, and the situation is further complicated by the IOHandler (including IOHandlerEditline) which assume they have control over the whole terminal screen. Although it would be possible to fully synchronize all of LLDB’s output, it would add significant overhead (due to locking) and complexity (due to all abstractions having to synchronize with each other).

Instead, we have tried to mitigate these issue by limiting the places we emit progress events (e.g. by avoiding emitting progress events asynchronously) and by attempting to limit the amount of updates (i.e. by shadowing shorter running progress events).

These issues has hurt the adoption of new progress events. We had a few situations where new events were added but never shown (because of shadowing) reducing their value. Even worse, we had a few situations where new progress were emitted asynchronously (from a thread pool) and would get interleaved with process and LLDB output.

Proposal

To avoid the issues mentioned above and without having to synchronize between, I propose to reserve a dedicated part of the screen (i.e. the bottom row of the terminal). This relies on a terminal feature that allows you to adjust the scroll window through ANSI escape codes. The reduced scroll window ensures that no output is ever shown there, unless the cursor is moved there explicitly through ANSI escape characters, which is how the statusline is redrawn.

When the statusline is enabled, a dedicated thread is responsible for periodically redrawing the statusline. I found 4 FPS to be the best trade-off between performance and latency.

Although the statusline is primarily motivated by showing progress events, other information can be displayed here as well. Over the years we’ve seen requests from users who want to customize their prompt to include information pertaining to the state of the debugger. The statusline would be a natural place to display that.

The statusline should be configurable through a setting. I’m proposing that we reuse the format strings that allow customizing thread and frame formats. Using the same infrastructure means that when we add support for more formats, both features benefit from it.

Prototype

Statusline Prototype

Video: LLDB Statusline - asciinema.org

Open Questions

Statusline as the default

The statusline feature can be disabled with a setting:

(lldb) settings show show-statusline
show-statusline (boolean) = true

Do we want the statusline to be on by default or opt-in? The answer likely depends on the next question below.

Replacing the current progress events

I propose that the statusline supersedes the current inline progress events. I would strongly prefer not having to maintain both. If we have to keep supporting the existing way of displaying them, the limitations mentioned in the motivation continue to hurt progress event adoption.

Configuration Format

I propose configuring the statusline with a new option value called format-string-list. The motivation for making this a list, rather than a single string is the current implementation of the FormatEntity class. If we fail to display one variable in the format string, the whole thing fails. This is problematic for the statusline because variables are not always available. For example, displaying the current source file doesn’t work if the process isn’t stopped.

With a format string list, the setting looks like this:

(lldb) settings show statusline-format
statusline-format (format-string-list) =
  [0]: <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>m</mi><mi>o</mi><mi>d</mi><mi>u</mi><mi>l</mi><mi>e</mi><mi mathvariant="normal">.</mi><mi>f</mi><mi>i</mi><mi>l</mi><mi>e</mi><mi mathvariant="normal">.</mi><mi>b</mi><mi>a</mi><mi>s</mi><mi>e</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></mrow><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo><mo>:</mo></mrow><annotation encoding="application/x-tex">{module.file.basename}  [1]: </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord">.</span><span class="mord mathnormal">ba</span><span class="mord mathnormal">se</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span></span><span class="mopen">[</span><span class="mord">1</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span></span></span></span>{line.file.basename}:${line.number}:${line.column}  [2]: ${thread.stop-reason}

Unavailable variables are skipped and the separator hidden.

I also propose that we do not include the progress events as a format string, but instead always append it, if the existing option show-progress is enabled:

(lldb) settings show show-progress
show-progress (boolean) = true

Pull Request

Draft PR with my prototype implementation: LLDB Statusline by JDevlieghere · Pull Request #121860 · llvm/llvm-project · GitHub