XTCAPTURE Buffer Capture
A proposal for a program to ask its terminal for the text of its last lines, scrollback included, for a fuzzy finder or the like to search.
CSI > Pl ; Pr , t
- Specification
- Buffer Capture, Contour VT extensions
Buffer Capture lets a program ask its terminal for the text of the last lines on it, reaching back into the scrollback, so that a shell can hand what was on the screen to a tool such as fzf to search and pick from. It is Contour’s, which names it XTCAPTURE. Its definition is Buffer Capture, kept with Contour’s other VT extensions, read at commit 3cdeed6, and the details below that the specification leaves out are from Contour’s source at release 0.8.0. No other terminal is known to implement it, and libghostty-vt does not.
The request
CSI > Pl ; Pr , t
Pl is 1 to count logical lines, where a line that wrapped across several rows of the screen is one line, and 0 to count rows; Contour takes 0 when it is left out and ignores the request for any other value. Pr is how many to capture, counting up from the bottom of the page; left out, it is the height of the page (CAPTURE). A count larger than the page reaches into the scrollback, as far as the scrollback goes.
The , intermediate is new. Contour first used CSI > Pl ; Pr t, which is xterm’s XTSMTITLE, the sequence that sets how xterm encodes titles, and the specification now gives that form up to xterm.
The answer
PM 314 ; data ST
The text comes back in privacy messages, as many as it takes, followed by one with no data, PM 314 ; ST, which ends the answer. data is the captured text in UTF-8, each line followed by LF.
Contour sends at most 4096 bytes of text in each message, and cuts the text wherever that limit falls, so one character’s bytes can be split between two messages; a reader joins the messages before decoding them. Each line loses its trailing blanks, and a line left empty is left out altogether rather than sent as a bare LF. Counting logical lines, a row that continues a wrapped line is joined to the one before without an LF. Contour always reads the main screen, even while the alternate screen is showing (Screen::captureBuffer).
Permission
Handing over the screen and its scrollback is something the user may not want, so a capture waits on Contour’s capture_buffer permission: allow, deny, or ask, which is the default and asks the user. A refused request is still answered, with the closing PM 314 ; ST and nothing before it, because the protocol has no way to say that no answer is coming and a program reading up to the end would otherwise wait forever. A refusal therefore cannot be told apart from capturing a blank screen, and the specification says that is deliberate (TerminalSession.cpp).