mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-14 03:25:50 +00:00
vt: expose ghostty_terminal_new/free
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
* @section groups_sec API Reference
|
||||
*
|
||||
* The API is organized into the following groups:
|
||||
* - @ref terminal "Terminal Lifecycle" - Create and destroy terminal instances
|
||||
* - @ref key "Key Encoding" - Encode key events into terminal sequences
|
||||
* - @ref osc "OSC Parser" - Parse OSC (Operating System Command) sequences
|
||||
* - @ref sgr "SGR Parser" - Parse SGR (Select Graphic Rendition) sequences
|
||||
@@ -74,6 +75,7 @@ extern "C" {
|
||||
|
||||
#include <ghostty/vt/result.h>
|
||||
#include <ghostty/vt/allocator.h>
|
||||
#include <ghostty/vt/terminal.h>
|
||||
#include <ghostty/vt/osc.h>
|
||||
#include <ghostty/vt/sgr.h>
|
||||
#include <ghostty/vt/key.h>
|
||||
|
||||
88
include/ghostty/vt/terminal.h
Normal file
88
include/ghostty/vt/terminal.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @file terminal.h
|
||||
*
|
||||
* Terminal lifecycle management.
|
||||
*/
|
||||
|
||||
#ifndef GHOSTTY_VT_TERMINAL_H
|
||||
#define GHOSTTY_VT_TERMINAL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <ghostty/vt/result.h>
|
||||
#include <ghostty/vt/allocator.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup terminal Terminal Lifecycle
|
||||
*
|
||||
* Minimal API for creating and destroying terminal instances.
|
||||
*
|
||||
* This currently only exposes lifecycle operations. Additional terminal
|
||||
* APIs will be added over time.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Opaque handle to a terminal instance.
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
typedef struct GhosttyTerminal* GhosttyTerminal;
|
||||
|
||||
/**
|
||||
* Terminal initialization options.
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
typedef struct {
|
||||
/** Terminal width in cells. Must be greater than zero. */
|
||||
uint16_t cols;
|
||||
|
||||
/** Terminal height in cells. Must be greater than zero. */
|
||||
uint16_t rows;
|
||||
|
||||
/** Maximum number of lines to keep in scrollback history. */
|
||||
size_t max_scrollback;
|
||||
|
||||
// TODO: Consider ABI compatibility implications of this struct.
|
||||
// We may want to artificially pad it significantly to support
|
||||
// future options.
|
||||
} GhosttyTerminalOptions;
|
||||
|
||||
/**
|
||||
* Create a new terminal instance.
|
||||
*
|
||||
* @param allocator Pointer to allocator, or NULL to use the default allocator
|
||||
* @param terminal Pointer to store the created terminal handle
|
||||
* @param options Terminal initialization options
|
||||
* @return GHOSTTY_SUCCESS on success, or an error code on failure
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
GhosttyResult ghostty_terminal_new(const GhosttyAllocator* allocator,
|
||||
GhosttyTerminal* terminal,
|
||||
GhosttyTerminalOptions options);
|
||||
|
||||
/**
|
||||
* Free a terminal instance.
|
||||
*
|
||||
* Releases all resources associated with the terminal. After this call,
|
||||
* the terminal handle becomes invalid and must not be used.
|
||||
*
|
||||
* @param terminal The terminal handle to free (may be NULL)
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
void ghostty_terminal_free(GhosttyTerminal terminal);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GHOSTTY_VT_TERMINAL_H */
|
||||
@@ -143,6 +143,8 @@ comptime {
|
||||
@export(&c.sgr_unknown_partial, .{ .name = "ghostty_sgr_unknown_partial" });
|
||||
@export(&c.sgr_attribute_tag, .{ .name = "ghostty_sgr_attribute_tag" });
|
||||
@export(&c.sgr_attribute_value, .{ .name = "ghostty_sgr_attribute_value" });
|
||||
@export(&c.terminal_new, .{ .name = "ghostty_terminal_new" });
|
||||
@export(&c.terminal_free, .{ .name = "ghostty_terminal_free" });
|
||||
|
||||
// On Wasm we need to export our allocator convenience functions.
|
||||
if (builtin.target.cpu.arch.isWasm()) {
|
||||
|
||||
@@ -271,7 +271,7 @@ pub fn vtHandler(self: *Terminal) ReadonlyHandler {
|
||||
}
|
||||
|
||||
/// The general allocator we should use for this terminal.
|
||||
fn gpa(self: *Terminal) Allocator {
|
||||
pub fn gpa(self: *Terminal) Allocator {
|
||||
return self.screens.active.alloc;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ pub const key_event = @import("key_event.zig");
|
||||
pub const key_encode = @import("key_encode.zig");
|
||||
pub const paste = @import("paste.zig");
|
||||
pub const sgr = @import("sgr.zig");
|
||||
pub const terminal = @import("terminal.zig");
|
||||
|
||||
// The full C API, unexported.
|
||||
pub const osc_new = osc.new;
|
||||
@@ -52,6 +53,9 @@ pub const key_encoder_encode = key_encode.encode;
|
||||
|
||||
pub const paste_is_safe = paste.is_safe;
|
||||
|
||||
pub const terminal_new = terminal.new;
|
||||
pub const terminal_free = terminal.free;
|
||||
|
||||
test {
|
||||
_ = color;
|
||||
_ = osc;
|
||||
@@ -59,6 +63,7 @@ test {
|
||||
_ = key_encode;
|
||||
_ = paste;
|
||||
_ = sgr;
|
||||
_ = terminal;
|
||||
|
||||
// We want to make sure we run the tests for the C allocator interface.
|
||||
_ = @import("../../lib/allocator.zig");
|
||||
|
||||
112
src/terminal/c/terminal.zig
Normal file
112
src/terminal/c/terminal.zig
Normal file
@@ -0,0 +1,112 @@
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const lib_alloc = @import("../../lib/allocator.zig");
|
||||
const CAllocator = lib_alloc.Allocator;
|
||||
const ZigTerminal = @import("../Terminal.zig");
|
||||
const size = @import("../size.zig");
|
||||
const Result = @import("result.zig").Result;
|
||||
|
||||
/// C: GhosttyTerminal
|
||||
pub const Terminal = ?*ZigTerminal;
|
||||
|
||||
/// C: GhosttyTerminalOptions
|
||||
pub const Options = extern struct {
|
||||
cols: size.CellCountInt,
|
||||
rows: size.CellCountInt,
|
||||
max_scrollback: usize,
|
||||
};
|
||||
|
||||
const NewError = error{
|
||||
InvalidValue,
|
||||
OutOfMemory,
|
||||
};
|
||||
|
||||
pub fn new(
|
||||
alloc_: ?*const CAllocator,
|
||||
result: *Terminal,
|
||||
opts: Options,
|
||||
) callconv(.c) Result {
|
||||
result.* = new_(alloc_, opts) catch |err| {
|
||||
result.* = null;
|
||||
return switch (err) {
|
||||
error.InvalidValue => .invalid_value,
|
||||
error.OutOfMemory => .out_of_memory,
|
||||
};
|
||||
};
|
||||
|
||||
return .success;
|
||||
}
|
||||
|
||||
fn new_(
|
||||
alloc_: ?*const CAllocator,
|
||||
opts: Options,
|
||||
) NewError!*ZigTerminal {
|
||||
if (opts.cols == 0 or opts.rows == 0) return error.InvalidValue;
|
||||
|
||||
const alloc = lib_alloc.default(alloc_);
|
||||
const ptr = alloc.create(ZigTerminal) catch
|
||||
return error.OutOfMemory;
|
||||
errdefer alloc.destroy(ptr);
|
||||
|
||||
ptr.* = try .init(alloc, .{
|
||||
.cols = opts.cols,
|
||||
.rows = opts.rows,
|
||||
.max_scrollback = opts.max_scrollback,
|
||||
});
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
pub fn free(terminal_: Terminal) callconv(.c) void {
|
||||
const t = terminal_ orelse return;
|
||||
|
||||
const alloc = t.gpa();
|
||||
t.deinit(alloc);
|
||||
alloc.destroy(t);
|
||||
}
|
||||
|
||||
test "new/free" {
|
||||
var t: Terminal = null;
|
||||
try testing.expectEqual(Result.success, new(
|
||||
&lib_alloc.test_allocator,
|
||||
&t,
|
||||
.{
|
||||
.cols = 80,
|
||||
.rows = 24,
|
||||
.max_scrollback = 10_000,
|
||||
},
|
||||
));
|
||||
|
||||
try testing.expect(t != null);
|
||||
free(t);
|
||||
}
|
||||
|
||||
test "new invalid value" {
|
||||
var t: Terminal = null;
|
||||
|
||||
try testing.expectEqual(Result.invalid_value, new(
|
||||
&lib_alloc.test_allocator,
|
||||
&t,
|
||||
.{
|
||||
.cols = 0,
|
||||
.rows = 24,
|
||||
.max_scrollback = 10_000,
|
||||
},
|
||||
));
|
||||
try testing.expect(t == null);
|
||||
|
||||
try testing.expectEqual(Result.invalid_value, new(
|
||||
&lib_alloc.test_allocator,
|
||||
&t,
|
||||
.{
|
||||
.cols = 80,
|
||||
.rows = 0,
|
||||
.max_scrollback = 10_000,
|
||||
},
|
||||
));
|
||||
try testing.expect(t == null);
|
||||
}
|
||||
|
||||
test "free null" {
|
||||
free(null);
|
||||
}
|
||||
Reference in New Issue
Block a user