|
|
|
|
@@ -0,0 +1,498 @@
|
|
|
|
|
/**
|
|
|
|
|
* @file search.h
|
|
|
|
|
*
|
|
|
|
|
* Search terminal contents, including scrollback, for a string.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef GHOSTTY_VT_SEARCH_H
|
|
|
|
|
#define GHOSTTY_VT_SEARCH_H
|
|
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <ghostty/vt/allocator.h>
|
|
|
|
|
#include <ghostty/vt/selection.h>
|
|
|
|
|
#include <ghostty/vt/types.h>
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/** @defgroup search Search
|
|
|
|
|
*
|
|
|
|
|
* Search a terminal for a string, covering the active area and
|
|
|
|
|
* scrollback of both the primary and alternate screens.
|
|
|
|
|
*
|
|
|
|
|
* A GhosttySearch searches one terminal for one needle. It is bound to
|
|
|
|
|
* the terminal it was created with and handles the hard parts of
|
|
|
|
|
* terminal search internally: results stay in sync with the live
|
|
|
|
|
* screens, survive primary/alternate screen switches (entering and
|
|
|
|
|
* leaving a fullscreen app such as vim does not restart a scrollback
|
|
|
|
|
* search), and recover from resize, reflow, resets, and scrollback
|
|
|
|
|
* pruning.
|
|
|
|
|
*
|
|
|
|
|
* ## Driving a search
|
|
|
|
|
*
|
|
|
|
|
* Searching a large scrollback takes time, so the work is split into
|
|
|
|
|
* small steps the caller drives so that the caller can control
|
|
|
|
|
* performance more directly:
|
|
|
|
|
*
|
|
|
|
|
* - ghostty_search_tick() makes a bounded amount of progress on data
|
|
|
|
|
* the search has already copied. It never touches the terminal,
|
|
|
|
|
* meaning it can be safely called from a thread.
|
|
|
|
|
* - ghostty_search_feed() reads the terminal to copy in more data and
|
|
|
|
|
* pick up terminal changes. Feeding is the only way the search
|
|
|
|
|
* learns that the terminal changed, so keep feeding periodically
|
|
|
|
|
* while the search is in use. This requires exclusive terminal access.
|
|
|
|
|
* - ghostty_search_run() is a blocking convenience that feeds and
|
|
|
|
|
* ticks until the search is caught up.
|
|
|
|
|
*
|
|
|
|
|
* GHOSTTY_SEARCH_STATUS_COMPLETE means the search is caught up with
|
|
|
|
|
* the terminal as of the last feed. It never means finished forever,
|
|
|
|
|
* since later terminal writes require another feed to be seen.
|
|
|
|
|
*
|
|
|
|
|
* ## Matches are selections
|
|
|
|
|
*
|
|
|
|
|
* Every match is returned as a GhosttySelection snapshot with
|
|
|
|
|
* rectangle set to false, so the existing selection APIs all work on
|
|
|
|
|
* matches: ghostty_terminal_selection_format_buf() to copy the
|
|
|
|
|
* matched text, ghostty_terminal_point_from_grid_ref() with
|
|
|
|
|
* GHOSTTY_POINT_TAG_VIEWPORT to position highlight rectangles,
|
|
|
|
|
* ghostty_terminal_selection_contains() for hit testing, and
|
|
|
|
|
* ghostty_terminal_set() with GHOSTTY_TERMINAL_OPT_SELECTION to make
|
|
|
|
|
* a match the terminal's selection.
|
|
|
|
|
*
|
|
|
|
|
* Returned matches follow the usual snapshot lifetime rules: they are
|
|
|
|
|
* only valid until the next operation that modifies the terminal,
|
|
|
|
|
* including ghostty_terminal_vt_write(), resize, reset, and free.
|
|
|
|
|
* Read matches after a feed, use them before the terminal changes
|
|
|
|
|
* again, and re-read them rather than caching them. The selected
|
|
|
|
|
* match is kept accurate internally across terminal changes, so the
|
|
|
|
|
* safe way to follow a match is to re-read
|
|
|
|
|
* GHOSTTY_SEARCH_DATA_SELECTED_MATCH after each feed.
|
|
|
|
|
*
|
|
|
|
|
* ## Lifetime
|
|
|
|
|
*
|
|
|
|
|
* The search borrows the terminal it was created with and never frees
|
|
|
|
|
* it. Any number of searches, alongside other terminal readers such
|
|
|
|
|
* as formatters and render states, may share one terminal.
|
|
|
|
|
*
|
|
|
|
|
* The search and its terminal can be freed in either order. Freeing
|
|
|
|
|
* the search first releases tracked state it holds within the
|
|
|
|
|
* terminal. If the terminal is freed first, the search detects this:
|
|
|
|
|
* calls that need the terminal return GHOSTTY_INVALID_VALUE, reads
|
|
|
|
|
* return whatever the search last saw, and ghostty_search_free()
|
|
|
|
|
* releases only search-owned memory. A search cannot be rebound, so
|
|
|
|
|
* searching another terminal means creating a new search.
|
|
|
|
|
*
|
|
|
|
|
* ## Threading
|
|
|
|
|
*
|
|
|
|
|
* The library creates no threads. Calls on one GhosttySearch are not
|
|
|
|
|
* safe to make concurrently with each other, so the caller must
|
|
|
|
|
* serialize them.
|
|
|
|
|
*
|
|
|
|
|
* Functions that touch the terminal (ghostty_search_new(),
|
|
|
|
|
* ghostty_search_feed(), ghostty_search_run(), ghostty_search_set()
|
|
|
|
|
* with the select options, and ghostty_search_free()) must also be
|
|
|
|
|
* serialized with all other access to the same terminal.
|
|
|
|
|
*
|
|
|
|
|
* Everything else (ghostty_search_tick(), ghostty_search_get(), and
|
|
|
|
|
* ghostty_search_get_multi()) only touches memory owned by the search
|
|
|
|
|
* and is safe to call while another thread modifies the terminal.
|
|
|
|
|
* This split is how Ghostty runs search on a background thread: tick
|
|
|
|
|
* freely, and take the terminal lock only to feed. Reading returned
|
|
|
|
|
* match values is always safe, but passing them to APIs that take the
|
|
|
|
|
* terminal follows the terminal serialization rule above.
|
|
|
|
|
*
|
|
|
|
|
* ## Example
|
|
|
|
|
*
|
|
|
|
|
* @snippet c-vt-search/src/main.c search-main
|
|
|
|
|
*
|
|
|
|
|
* @{
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Progress state of a search.
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
typedef enum GHOSTTY_ENUM_TYPED {
|
|
|
|
|
/**
|
|
|
|
|
* ghostty_search_tick() can make progress without terminal access.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_STATUS_RUNNING = 0,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Blocked until ghostty_search_feed(). This is also the initial
|
|
|
|
|
* state, since a search that has never been fed has never seen the
|
|
|
|
|
* terminal.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_STATUS_FEED_REQUIRED = 1,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Caught up with the terminal state as of the last feed. This never
|
|
|
|
|
* means finished forever, since later terminal writes require
|
|
|
|
|
* another feed to be seen.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_STATUS_COMPLETE = 2,
|
|
|
|
|
|
|
|
|
|
GHOSTTY_SEARCH_STATUS_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
|
|
|
|
} GhosttySearchStatus;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Scroll policy applied when a match becomes selected via
|
|
|
|
|
* GHOSTTY_SEARCH_OPT_SELECT_NEXT or GHOSTTY_SEARCH_OPT_SELECT_PREV.
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
typedef enum GHOSTTY_ENUM_TYPED {
|
|
|
|
|
/** Scroll the viewport so the match is visible, only if it is not
|
|
|
|
|
* already visible. This is the default. */
|
|
|
|
|
GHOSTTY_SEARCH_SCROLL_IF_NEEDED = 0,
|
|
|
|
|
|
|
|
|
|
/** Never scroll the viewport. */
|
|
|
|
|
GHOSTTY_SEARCH_SCROLL_NONE = 1,
|
|
|
|
|
|
|
|
|
|
GHOSTTY_SEARCH_SCROLL_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
|
|
|
|
} GhosttySearchScroll;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Data fields readable with ghostty_search_get(). The output value
|
|
|
|
|
* type is documented per field.
|
|
|
|
|
*
|
|
|
|
|
* All reads reflect the terminal's active screen as of the last feed.
|
|
|
|
|
* When the running application switches to the alternate screen, the
|
|
|
|
|
* next feed switches counts, matches, and selection to that screen's
|
|
|
|
|
* results. Primary screen results, including completed scrollback
|
|
|
|
|
* searches, are retained and restored on the way back.
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
typedef enum GHOSTTY_ENUM_TYPED {
|
|
|
|
|
/** Current search status: GhosttySearchStatus*. */
|
|
|
|
|
GHOSTTY_SEARCH_DATA_STATUS = 0,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The needle this search is looking for: GhosttyString*. The bytes
|
|
|
|
|
* are borrowed from the search and remain valid until
|
|
|
|
|
* ghostty_search_free().
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_DATA_NEEDLE = 1,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Total matches found so far on the active screen: size_t*. Zero
|
|
|
|
|
* until the first feed.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_DATA_TOTAL_MATCHES = 2,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Index of the selected match: size_t*. This indexes the newest to
|
|
|
|
|
* oldest ordering of GHOSTTY_SEARCH_DATA_MATCHES, where 0 is the
|
|
|
|
|
* newest match, so a "k of n" find bar renders index + 1 of
|
|
|
|
|
* GHOSTTY_SEARCH_DATA_TOTAL_MATCHES. Returns GHOSTTY_NO_VALUE when
|
|
|
|
|
* nothing is selected.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_DATA_SELECTED_INDEX = 3,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The selected match: GhosttySelection*. This is an untracked
|
|
|
|
|
* snapshot with standard GhosttySelection lifetime rules. Returns
|
|
|
|
|
* GHOSTTY_NO_VALUE when nothing is selected.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_DATA_SELECTED_MATCH = 4,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* All matches on the active screen, ordered newest to oldest, from
|
|
|
|
|
* the bottom of the active area up through scrollback:
|
|
|
|
|
* GhosttySelectionBuffer*. Set ptr to NULL with cap 0 to query the
|
|
|
|
|
* required capacity. An undersized buffer returns
|
|
|
|
|
* GHOSTTY_OUT_OF_SPACE with the required capacity in len.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_DATA_MATCHES = 5,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Matches on the pages covering the viewport, for drawing highlight
|
|
|
|
|
* rectangles: GhosttySelectionBuffer*. The list is computed during
|
|
|
|
|
* feeds and cached, so it reflects the viewport as of the last
|
|
|
|
|
* feed.
|
|
|
|
|
*
|
|
|
|
|
* Matches are found a page at a time, so the list can include
|
|
|
|
|
* matches slightly outside the visible viewport when they share a
|
|
|
|
|
* page with it. Ghostty's own renderer behaves the same way.
|
|
|
|
|
* Converting each match to viewport coordinates with
|
|
|
|
|
* ghostty_terminal_point_from_grid_ref() clips this naturally: skip
|
|
|
|
|
* matches that fail the conversion or whose row is beyond the
|
|
|
|
|
* visible row count.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_DATA_VIEWPORT_MATCHES = 6,
|
|
|
|
|
|
|
|
|
|
/** Current scroll policy: GhosttySearchScroll*. */
|
|
|
|
|
GHOSTTY_SEARCH_DATA_SELECT_SCROLL = 7,
|
|
|
|
|
|
|
|
|
|
GHOSTTY_SEARCH_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
|
|
|
|
} GhosttySearchData;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Options writable with ghostty_search_set(). The value type, and
|
|
|
|
|
* what a NULL value means, is documented per option.
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
typedef enum GHOSTTY_ENUM_TYPED {
|
|
|
|
|
/**
|
|
|
|
|
* Select the next match, moving toward older content: from the
|
|
|
|
|
* bottom of the screen upward into history, the direction a search
|
|
|
|
|
* from the prompt usually wants. Wraps around past the oldest
|
|
|
|
|
* match.
|
|
|
|
|
*
|
|
|
|
|
* The value must be NULL. It is reserved for future use.
|
|
|
|
|
*
|
|
|
|
|
* This catches up with the terminal first, so it is safe to call at
|
|
|
|
|
* any time relative to feeds. The viewport scrolls to the newly
|
|
|
|
|
* selected match according to GHOSTTY_SEARCH_OPT_SELECT_SCROLL.
|
|
|
|
|
* This reads the terminal, so the caller must serialize it with all
|
|
|
|
|
* other access to the same terminal. Returns GHOSTTY_NO_VALUE when
|
|
|
|
|
* there are no matches.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_OPT_SELECT_NEXT = 0,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Select the previous match, moving toward newer content, wrapping
|
|
|
|
|
* around past the newest match. Otherwise identical to
|
|
|
|
|
* GHOSTTY_SEARCH_OPT_SELECT_NEXT.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_OPT_SELECT_PREV = 1,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the scroll policy applied by the select options: const
|
|
|
|
|
* GhosttySearchScroll*. The policy persists until changed. A NULL
|
|
|
|
|
* value resets it to GHOSTTY_SEARCH_SCROLL_IF_NEEDED. This only
|
|
|
|
|
* modifies search-owned state and never reads the terminal.
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_SEARCH_OPT_SELECT_SCROLL = 2,
|
|
|
|
|
|
|
|
|
|
GHOSTTY_SEARCH_OPT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
|
|
|
|
} GhosttySearchOption;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Options for creating a search.
|
|
|
|
|
*
|
|
|
|
|
* This is a sized struct. Use GHOSTTY_INIT_SIZED() to initialize it.
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
typedef struct {
|
|
|
|
|
/** Size of this struct in bytes. Must be set to sizeof(GhosttySearchOptions). */
|
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The bytes to search for. This is copied, so the caller's memory
|
|
|
|
|
* does not need to outlive the create call. Must not be empty.
|
|
|
|
|
*
|
|
|
|
|
* Matching is byte-exact except ASCII letters, which compare
|
|
|
|
|
* case-insensitively.
|
|
|
|
|
*
|
|
|
|
|
* The needle cannot be changed after the search is created. To
|
|
|
|
|
* change the query, free the search and create a new one. This is
|
|
|
|
|
* also how Ghostty's own find bar handles retyping.
|
|
|
|
|
*/
|
|
|
|
|
GhosttyString needle;
|
|
|
|
|
} GhosttySearchOptions;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a search bound to a terminal.
|
|
|
|
|
*
|
|
|
|
|
* The search borrows the terminal and never frees it. The search and
|
|
|
|
|
* the terminal can be freed in either order; see ghostty_search_free().
|
|
|
|
|
*
|
|
|
|
|
* Creation is cheap and does not read terminal contents (the first
|
|
|
|
|
* feed does), but it registers the search with the terminal so the
|
|
|
|
|
* two can be freed in any order. The caller must serialize this call
|
|
|
|
|
* with all other access to the same terminal.
|
|
|
|
|
*
|
|
|
|
|
* @param allocator Allocator, or NULL for the default allocator
|
|
|
|
|
* @param out_search Receives the created search handle
|
|
|
|
|
* @param terminal Terminal to bind the search to
|
|
|
|
|
* @param options Search options (the needle is copied)
|
|
|
|
|
* @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if
|
|
|
|
|
* out_search, terminal, or options are invalid or the needle
|
|
|
|
|
* is empty, or GHOSTTY_OUT_OF_MEMORY if allocation fails
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_API GhosttyResult ghostty_search_new(
|
|
|
|
|
const GhosttyAllocator* allocator,
|
|
|
|
|
GhosttySearch* out_search,
|
|
|
|
|
GhosttyTerminal terminal,
|
|
|
|
|
const GhosttySearchOptions* options);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Free a search.
|
|
|
|
|
*
|
|
|
|
|
* If the bound terminal is still alive, this releases tracked state
|
|
|
|
|
* the search holds within it, so the caller must serialize this call
|
|
|
|
|
* with all other access to the same terminal. If the terminal was
|
|
|
|
|
* already freed, the search has been detached and this releases only
|
|
|
|
|
* search-owned memory. Passing NULL is allowed and is a no-op.
|
|
|
|
|
*
|
|
|
|
|
* @param search Search handle to free
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_API void ghostty_search_free(GhosttySearch search);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Make a bounded amount of search progress.
|
|
|
|
|
*
|
|
|
|
|
* This only works on data the search has already copied and never
|
|
|
|
|
* reads the terminal, so it is safe to call while another thread
|
|
|
|
|
* modifies the terminal. Call it in a loop while the status is
|
|
|
|
|
* GHOSTTY_SEARCH_STATUS_RUNNING. When the status becomes
|
|
|
|
|
* GHOSTTY_SEARCH_STATUS_FEED_REQUIRED, call ghostty_search_feed() to
|
|
|
|
|
* unblock it.
|
|
|
|
|
*
|
|
|
|
|
* @param search Search handle (NULL returns GHOSTTY_INVALID_VALUE)
|
|
|
|
|
* @param[out] out_status Receives the status after the tick (may be NULL)
|
|
|
|
|
* @return GHOSTTY_SUCCESS on success, or GHOSTTY_INVALID_VALUE if
|
|
|
|
|
* search is NULL
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_API GhosttyResult ghostty_search_tick(
|
|
|
|
|
GhosttySearch search,
|
|
|
|
|
GhosttySearchStatus* out_status);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Read the terminal to update the search.
|
|
|
|
|
*
|
|
|
|
|
* Each feed catches the search up with the terminal: it reconciles
|
|
|
|
|
* the tracked screens against the live ones, re-scans the active
|
|
|
|
|
* area, refreshes the viewport match list, gives the scrollback
|
|
|
|
|
* searcher its next chunk of data, and prunes results that scrollback
|
|
|
|
|
* eviction invalidated. Feeding is also the only way the search
|
|
|
|
|
* learns about terminal changes, so keep feeding periodically while
|
|
|
|
|
* the search is in use, even after it reports complete.
|
|
|
|
|
*
|
|
|
|
|
* This reads the terminal, so the caller must serialize it with all
|
|
|
|
|
* other access to the same terminal. Each call does a bounded amount
|
|
|
|
|
* of work so that any caller-held terminal lock is held only briefly.
|
|
|
|
|
*
|
|
|
|
|
* @param search Search handle (NULL returns GHOSTTY_INVALID_VALUE)
|
|
|
|
|
* @return GHOSTTY_SUCCESS on success, or GHOSTTY_INVALID_VALUE if
|
|
|
|
|
* search is NULL or the terminal was freed
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_API GhosttyResult ghostty_search_feed(GhosttySearch search);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Feed and tick until the search is caught up with the terminal.
|
|
|
|
|
*
|
|
|
|
|
* This is a blocking convenience for one-shot and single-threaded
|
|
|
|
|
* embedders. It always performs at least one feed, so it also picks
|
|
|
|
|
* up any terminal changes since the last feed, then loops until the
|
|
|
|
|
* status is GHOSTTY_SEARCH_STATUS_COMPLETE. Searching a large
|
|
|
|
|
* scrollback can take a while, so interactive embedders should drive
|
|
|
|
|
* ghostty_search_tick() and ghostty_search_feed() themselves.
|
|
|
|
|
*
|
|
|
|
|
* This reads the terminal for the entire call, so the caller must
|
|
|
|
|
* serialize it with all other access to the same terminal.
|
|
|
|
|
*
|
|
|
|
|
* @param search Search handle (NULL returns GHOSTTY_INVALID_VALUE)
|
|
|
|
|
* @return GHOSTTY_SUCCESS on success, or GHOSTTY_INVALID_VALUE if
|
|
|
|
|
* search is NULL or the terminal was freed
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_API GhosttyResult ghostty_search_run(GhosttySearch search);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write an option to a search.
|
|
|
|
|
*
|
|
|
|
|
* The value type, and what a NULL value means, depends on the option
|
|
|
|
|
* and is documented by GhosttySearchOption. The select options read
|
|
|
|
|
* the terminal, so the caller must serialize those calls with all
|
|
|
|
|
* other access to the same terminal.
|
|
|
|
|
* GHOSTTY_SEARCH_OPT_SELECT_SCROLL only modifies search-owned state.
|
|
|
|
|
*
|
|
|
|
|
* @param search Search handle (NULL returns GHOSTTY_INVALID_VALUE)
|
|
|
|
|
* @param option Option to write
|
|
|
|
|
* @param value Pointer to the input value for the option. The meaning
|
|
|
|
|
* of NULL is documented per option.
|
|
|
|
|
* @return GHOSTTY_SUCCESS on success, GHOSTTY_NO_VALUE if a select
|
|
|
|
|
* option found no matches, GHOSTTY_OUT_OF_MEMORY if selection
|
|
|
|
|
* tracking fails, or GHOSTTY_INVALID_VALUE if search, option,
|
|
|
|
|
* or value is invalid or a select option is used after the
|
|
|
|
|
* terminal was freed
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_API GhosttyResult ghostty_search_set(
|
|
|
|
|
GhosttySearch search,
|
|
|
|
|
GhosttySearchOption option,
|
|
|
|
|
const void* value);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Read a data field from a search.
|
|
|
|
|
*
|
|
|
|
|
* The output value type depends on data and is documented by
|
|
|
|
|
* GhosttySearchData. This never reads the terminal, so it is safe to
|
|
|
|
|
* call while another thread modifies the terminal. Returned
|
|
|
|
|
* selections are untracked snapshots with standard GhosttySelection
|
|
|
|
|
* lifetime rules.
|
|
|
|
|
*
|
|
|
|
|
* @param search Search handle (NULL returns GHOSTTY_INVALID_VALUE)
|
|
|
|
|
* @param data Data field to read
|
|
|
|
|
* @param value Output pointer whose type depends on data
|
|
|
|
|
* @return GHOSTTY_SUCCESS on success, GHOSTTY_NO_VALUE if the
|
|
|
|
|
* requested data has no value, GHOSTTY_OUT_OF_SPACE if a
|
|
|
|
|
* provided GhosttySelectionBuffer is too small (required
|
|
|
|
|
* capacity in its len), GHOSTTY_OUT_OF_MEMORY if collecting
|
|
|
|
|
* viewport matches fails, or GHOSTTY_INVALID_VALUE if search,
|
|
|
|
|
* data, or value is invalid
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_API GhosttyResult ghostty_search_get(
|
|
|
|
|
GhosttySearch search,
|
|
|
|
|
GhosttySearchData data,
|
|
|
|
|
void* value);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Read multiple data fields from a search in a single call.
|
|
|
|
|
*
|
|
|
|
|
* This is an optimization over calling ghostty_search_get() multiple
|
|
|
|
|
* times. Each entry in values must point to storage of the type
|
|
|
|
|
* documented by the corresponding GhosttySearchData key.
|
|
|
|
|
*
|
|
|
|
|
* If any individual read fails, the function returns that error and
|
|
|
|
|
* writes the index of the failing key to out_written when out_written
|
|
|
|
|
* is non-NULL. Earlier keys have already been written. On success,
|
|
|
|
|
* out_written receives count when non-NULL. A too-small
|
|
|
|
|
* GhosttySelectionBuffer stops the batch with GHOSTTY_OUT_OF_SPACE at
|
|
|
|
|
* that key's index with the required capacity in its len, so order
|
|
|
|
|
* buffer-valued keys after scalar keys.
|
|
|
|
|
*
|
|
|
|
|
* @param search Search handle (NULL returns GHOSTTY_INVALID_VALUE)
|
|
|
|
|
* @param count Number of data fields to read
|
|
|
|
|
* @param keys Data fields to read (must not be NULL)
|
|
|
|
|
* @param values Output pointers corresponding to keys (must not be NULL)
|
|
|
|
|
* @param out_written Optional number of fields read, or failing index
|
|
|
|
|
* on error
|
|
|
|
|
* @return GHOSTTY_SUCCESS on success, or the first failing read's
|
|
|
|
|
* result
|
|
|
|
|
*
|
|
|
|
|
* @ingroup search
|
|
|
|
|
*/
|
|
|
|
|
GHOSTTY_API GhosttyResult ghostty_search_get_multi(
|
|
|
|
|
GhosttySearch search,
|
|
|
|
|
size_t count,
|
|
|
|
|
const GhosttySearchData* keys,
|
|
|
|
|
void** values,
|
|
|
|
|
size_t* out_written);
|
|
|
|
|
|
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif /* GHOSTTY_VT_SEARCH_H */
|