libghostty: selection formatting

This commit is contained in:
Mitchell Hashimoto
2026-05-24 13:56:54 -07:00
parent eb777b8036
commit 2ce5db29ca
6 changed files with 376 additions and 17 deletions

View File

@@ -32,23 +32,6 @@ extern "C" {
* @{
*/
/**
* Output format.
*
* @ingroup formatter
*/
typedef enum GHOSTTY_ENUM_TYPED {
/** Plain text (no escape sequences). */
GHOSTTY_FORMATTER_FORMAT_PLAIN,
/** VT sequences preserving colors, styles, URLs, etc. */
GHOSTTY_FORMATTER_FORMAT_VT,
/** HTML with inline styles. */
GHOSTTY_FORMATTER_FORMAT_HTML,
GHOSTTY_FORMATTER_FORMAT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyFormatterFormat;
/**
* Extra screen state to include in styled output.
*

View File

@@ -10,8 +10,10 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <ghostty/vt/allocator.h>
#include <ghostty/vt/grid_ref.h>
#include <ghostty/vt/point.h>
#include <ghostty/vt/types.h>
#ifdef __cplusplus
extern "C" {
@@ -161,6 +163,46 @@ typedef struct {
bool semantic_prompt_boundary;
} GhosttyTerminalSelectLineOptions;
/**
* Options for one-shot formatting of a terminal selection.
*
* This is a sized struct. Use GHOSTTY_INIT_SIZED() to initialize it.
*
* If selection is NULL, the terminal's current active selection is used.
* If selection is non-NULL, that caller-provided snapshot selection is used.
*
* The selection is formatted from the terminal's active screen using the same
* formatting semantics as GhosttyFormatter. For copy/clipboard behavior
* matching Ghostty's Screen.selectionString(), use plain output with unwrap
* and trim both set to true.
*
* @ingroup selection
*/
typedef struct {
/** Size of this struct in bytes. Must be set to sizeof(GhosttyTerminalSelectionFormatOptions). */
size_t size;
/** Output format to emit. */
GhosttyFormatterFormat emit;
/** Whether to unwrap soft-wrapped lines. */
bool unwrap;
/** Whether to trim trailing whitespace on non-blank lines. */
bool trim;
/**
* Optional selection to format.
*
* If NULL, the terminal's current active selection is used. If the terminal
* has no active selection, formatting returns GHOSTTY_NO_VALUE.
*
* If non-NULL, the pointed-to selection must be a valid snapshot selection
* for this terminal and must obey GhosttySelection lifetime rules.
*/
const GhosttySelection *selection;
} GhosttyTerminalSelectionFormatOptions;
/**
* Ordering of a selection's endpoints in terminal coordinates.
*
@@ -355,6 +397,74 @@ GHOSTTY_API GhosttyResult ghostty_terminal_select_output(
GhosttyGridRef ref,
GhosttySelection* out_selection);
/**
* Format a terminal selection into a caller-provided buffer.
*
* This is a one-shot convenience API for formatting either the terminal's
* active selection or a caller-provided GhosttySelection without explicitly
* creating a GhosttyFormatter.
*
* Pass NULL for buf to query the required output size. In that case,
* out_written receives the required size and the function returns
* GHOSTTY_OUT_OF_SPACE.
*
* If buf is too small, the function returns GHOSTTY_OUT_OF_SPACE and writes
* the required size to out_written. The caller can then retry with a larger
* buffer.
*
* If options.selection is NULL and the terminal has no active selection, the
* function returns GHOSTTY_NO_VALUE.
*
* @param terminal The terminal to read from (must not be NULL)
* @param options Selection formatting options
* @param buf Output buffer, or NULL to query required size
* @param buf_len Length of buf in bytes
* @param out_written Number of bytes written, or required size on
* GHOSTTY_OUT_OF_SPACE (must not be NULL)
* @return GHOSTTY_SUCCESS on success, or an error code on failure
*
* @ingroup selection
*/
GHOSTTY_API GhosttyResult ghostty_terminal_selection_format_buf(
GhosttyTerminal terminal,
GhosttyTerminalSelectionFormatOptions options,
uint8_t* buf,
size_t buf_len,
size_t* out_written);
/**
* Format a terminal selection into an allocated buffer.
*
* This is a one-shot convenience API for formatting either the terminal's
* active selection or a caller-provided GhosttySelection without explicitly
* creating a GhosttyFormatter.
*
* The returned buffer is allocated using allocator, or the default allocator
* if NULL is passed. The caller owns the returned buffer and must free it with
* ghostty_free(), passing the same allocator and returned length.
*
* The returned bytes are not NUL-terminated. This supports plain text, VT, and
* HTML uniformly as byte output.
*
* If options.selection is NULL and the terminal has no active selection, the
* function returns GHOSTTY_NO_VALUE and leaves out_ptr as NULL and out_len as 0.
*
* @param terminal The terminal to read from (must not be NULL)
* @param allocator Allocator used for the returned buffer, or NULL for the default allocator
* @param options Selection formatting options
* @param out_ptr Receives the allocated output buffer (must not be NULL)
* @param out_len Receives the output length in bytes (must not be NULL)
* @return GHOSTTY_SUCCESS on success, or an error code on failure
*
* @ingroup selection
*/
GHOSTTY_API GhosttyResult ghostty_terminal_selection_format_alloc(
GhosttyTerminal terminal,
const GhosttyAllocator* allocator,
GhosttyTerminalSelectionFormatOptions options,
uint8_t** out_ptr,
size_t* out_len);
/**
* Adjust a selection snapshot using terminal selection semantics.
*

View File

@@ -194,6 +194,23 @@ typedef struct GhosttyOscCommandImpl* GhosttyOscCommand;
/* ---- Common value types ---- */
/**
* Terminal content output format.
*
* @ingroup formatter
*/
typedef enum GHOSTTY_ENUM_TYPED {
/** Plain text (no escape sequences). */
GHOSTTY_FORMATTER_FORMAT_PLAIN,
/** VT sequences preserving colors, styles, URLs, etc. */
GHOSTTY_FORMATTER_FORMAT_VT,
/** HTML with inline styles. */
GHOSTTY_FORMATTER_FORMAT_HTML,
GHOSTTY_FORMATTER_FORMAT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyFormatterFormat;
/**
* A borrowed byte string (pointer + length).
*