Ensure all examples in libghostty C docs build and run in CI (#11609)
This moves all our examples away from embedded source to `@snippet` and files so that we can use our CI to actually run the builds and keep them working. Note: I used AI to extract the examples, and it did some weird merging stuff. It all works but I want to make sure all these examples are still human friendly so I need to go back and review all that. I clicked through the web docs and they look good, just need to verify the GitHub flow.pull/11643/head
commit
9e6c875f33
|
|
@ -167,23 +167,30 @@ jobs:
|
|||
- name: Build Benchmarks
|
||||
run: nix develop -c zig build -Demit-bench
|
||||
|
||||
list-examples:
|
||||
if: github.repository == 'ghostty-org/ghostty' && needs.skip.outputs.skip != 'true'
|
||||
needs: skip
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
outputs:
|
||||
dirs: ${{ steps.list.outputs.dirs }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- id: list
|
||||
name: List example directories
|
||||
run: |
|
||||
dirs=$(ls example/*/build.zig.zon 2>/dev/null | xargs -n1 dirname | xargs -n1 basename | jq -R -s -c 'split("\n") | map(select(. != ""))')
|
||||
echo "$dirs" | jq .
|
||||
echo "dirs=$dirs" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build-examples:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
dir:
|
||||
[
|
||||
c-vt,
|
||||
c-vt-key-encode,
|
||||
c-vt-paste,
|
||||
c-vt-sgr,
|
||||
zig-formatter,
|
||||
zig-vt,
|
||||
zig-vt-stream,
|
||||
]
|
||||
dir: ${{ fromJSON(needs.list-examples.outputs.dirs) }}
|
||||
name: Example ${{ matrix.dir }}
|
||||
runs-on: namespace-profile-ghostty-sm
|
||||
needs: test
|
||||
runs-on: namespace-profile-ghostty-xsm
|
||||
needs: [test, list-examples]
|
||||
env:
|
||||
ZIG_LOCAL_CACHE_DIR: /zig/local-cache
|
||||
ZIG_GLOBAL_CACHE_DIR: /zig/global-cache
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
# Example Libghostty Projects
|
||||
|
||||
Each example is a standalone project with its own `build.zig`,
|
||||
`build.zig.zon`, `README.md`, and `src/main.c` (or `.zig`). Examples are
|
||||
auto-discovered by CI via `example/*/build.zig.zon`, so no workflow file
|
||||
edits are needed when adding a new example.
|
||||
|
||||
## Adding a New Example
|
||||
|
||||
1. Copy an existing example directory (e.g., `c-vt-encode-focus/`) as a
|
||||
starting point.
|
||||
2. Update `build.zig.zon`: change `.name`, generate a **new unique**
|
||||
`.fingerprint` value (a random `u64` hex literal), and keep
|
||||
`.minimum_zig_version` matching the others.
|
||||
3. Update `build.zig`: change the executable `.name` to match the directory.
|
||||
4. Write a `README.md` following the existing format.
|
||||
|
||||
## Doxygen Snippet Tags
|
||||
|
||||
Example source files use Doxygen `@snippet` tags so the corresponding
|
||||
header in `include/ghostty/vt/` can reference them. Wrap the relevant
|
||||
code with `//! [snippet-name]` markers:
|
||||
|
||||
```c
|
||||
//! [my-snippet]
|
||||
int main() { ... }
|
||||
//! [my-snippet]
|
||||
```
|
||||
|
||||
The header then uses `@snippet <dir>/src/main.c my-snippet` instead of
|
||||
inline `@code` blocks. Never duplicate example code inline in the
|
||||
headers — always use `@snippet`. When modifying example code, keep the
|
||||
snippet markers in sync with the headers in `include/ghostty/vt/`.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Executable names use underscores: `c_vt_encode_focus` (not hyphens).
|
||||
- All C examples link `ghostty-vt` via `lazyDependency("ghostty", ...)`.
|
||||
- `build.zig` files follow a common template — keep them consistent.
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Examples
|
||||
|
||||
Standalone projects demonstrating the Ghostty library APIs.
|
||||
The directories starting with `c-` use the C API and the directories
|
||||
starting with `zig-` use the Zig API.
|
||||
|
||||
Every example can be built and run using `zig build` and `zig build run`
|
||||
from within the respective example directory.
|
||||
Even the C API examples use the Zig build system (not the language) to
|
||||
build the project.
|
||||
|
||||
## Running an Example
|
||||
|
||||
```shell-session
|
||||
cd example/<dir>
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Example: `ghostty-vt` Encode Focus
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` focus
|
||||
encoding API to encode focus gained/lost events into escape sequences.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -29,7 +29,7 @@ pub fn build(b: *std.Build) void {
|
|||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_mouse_encode",
|
||||
.name = "c_vt_encode_focus",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_encode_focus,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x89f01fd829fcc550,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [focus-encode]
|
||||
int main() {
|
||||
char buf[8];
|
||||
size_t written = 0;
|
||||
|
||||
GhosttyResult result = ghostty_focus_encode(
|
||||
GHOSTTY_FOCUS_GAINED, buf, sizeof(buf), &written);
|
||||
|
||||
if (result == GHOSTTY_SUCCESS) {
|
||||
printf("Encoded %zu bytes: ", written);
|
||||
fwrite(buf, 1, written, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [focus-encode]
|
||||
|
|
@ -29,7 +29,7 @@ pub fn build(b: *std.Build) void {
|
|||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_key_encode",
|
||||
.name = "c_vt_encode_key",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [key-encode]
|
||||
int main() {
|
||||
// Create encoder
|
||||
GhosttyKeyEncoder encoder;
|
||||
GhosttyResult result = ghostty_key_encoder_new(NULL, &encoder);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Enable Kitty keyboard protocol with all features
|
||||
ghostty_key_encoder_setopt(encoder, GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS,
|
||||
&(uint8_t){GHOSTTY_KITTY_KEY_ALL});
|
||||
|
||||
// Create and configure key event for Ctrl+C press
|
||||
GhosttyKeyEvent event;
|
||||
result = ghostty_key_event_new(NULL, &event);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
ghostty_key_event_set_action(event, GHOSTTY_KEY_ACTION_PRESS);
|
||||
ghostty_key_event_set_key(event, GHOSTTY_KEY_C);
|
||||
ghostty_key_event_set_mods(event, GHOSTTY_MODS_CTRL);
|
||||
|
||||
// Encode the key event
|
||||
char buf[128];
|
||||
size_t written = 0;
|
||||
result = ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Use the encoded sequence (e.g., write to terminal)
|
||||
fwrite(buf, 1, written, stdout);
|
||||
|
||||
// Cleanup
|
||||
ghostty_key_event_free(event);
|
||||
ghostty_key_encoder_free(encoder);
|
||||
return 0;
|
||||
}
|
||||
//! [key-encode]
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_encode_mouse",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [mouse-encode]
|
||||
int main() {
|
||||
// Create encoder
|
||||
GhosttyMouseEncoder encoder;
|
||||
GhosttyResult result = ghostty_mouse_encoder_new(NULL, &encoder);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Configure SGR format with normal tracking
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_EVENT,
|
||||
&(GhosttyMouseTrackingMode){GHOSTTY_MOUSE_TRACKING_NORMAL});
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_FORMAT,
|
||||
&(GhosttyMouseFormat){GHOSTTY_MOUSE_FORMAT_SGR});
|
||||
|
||||
// Set terminal geometry for coordinate mapping
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_SIZE,
|
||||
&(GhosttyMouseEncoderSize){
|
||||
.size = sizeof(GhosttyMouseEncoderSize),
|
||||
.screen_width = 800, .screen_height = 600,
|
||||
.cell_width = 10, .cell_height = 20,
|
||||
});
|
||||
|
||||
// Create and configure a left button press event
|
||||
GhosttyMouseEvent event;
|
||||
result = ghostty_mouse_event_new(NULL, &event);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
ghostty_mouse_event_set_action(event, GHOSTTY_MOUSE_ACTION_PRESS);
|
||||
ghostty_mouse_event_set_button(event, GHOSTTY_MOUSE_BUTTON_LEFT);
|
||||
ghostty_mouse_event_set_position(event,
|
||||
(GhosttyMousePosition){.x = 50.0f, .y = 40.0f});
|
||||
|
||||
// Encode the mouse event
|
||||
char buf[128];
|
||||
size_t written = 0;
|
||||
result = ghostty_mouse_encoder_encode(encoder, event,
|
||||
buf, sizeof(buf), &written);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Use the encoded sequence (e.g., write to terminal)
|
||||
fwrite(buf, 1, written, stdout);
|
||||
|
||||
// Cleanup
|
||||
ghostty_mouse_event_free(event);
|
||||
ghostty_mouse_encoder_free(encoder);
|
||||
return 0;
|
||||
}
|
||||
//! [mouse-encode]
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
GhosttyKeyEncoder encoder;
|
||||
GhosttyResult result = ghostty_key_encoder_new(NULL, &encoder);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Set kitty flags with all features enabled
|
||||
ghostty_key_encoder_setopt(encoder, GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS, &(uint8_t){GHOSTTY_KITTY_KEY_ALL});
|
||||
|
||||
// Create key event
|
||||
GhosttyKeyEvent event;
|
||||
result = ghostty_key_event_new(NULL, &event);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
ghostty_key_event_set_action(event, GHOSTTY_KEY_ACTION_RELEASE);
|
||||
ghostty_key_event_set_key(event, GHOSTTY_KEY_CONTROL_LEFT);
|
||||
ghostty_key_event_set_mods(event, GHOSTTY_MODS_CTRL);
|
||||
printf("Encoding event: left ctrl release with all Kitty flags enabled\n");
|
||||
|
||||
// Optionally, encode with null buffer to get required size. You can
|
||||
// skip this step and provide a sufficiently large buffer directly.
|
||||
// If there isn't enoug hspace, the function will return an out of memory
|
||||
// error.
|
||||
size_t required = 0;
|
||||
result = ghostty_key_encoder_encode(encoder, event, NULL, 0, &required);
|
||||
assert(result == GHOSTTY_OUT_OF_MEMORY);
|
||||
printf("Required buffer size: %zu bytes\n", required);
|
||||
|
||||
// Encode the key event. We don't use our required size above because
|
||||
// that was just an example; we know 128 bytes is enough.
|
||||
char buf[128];
|
||||
size_t written = 0;
|
||||
result = ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
printf("Encoded %zu bytes\n", written);
|
||||
|
||||
// Print the encoded sequence (hex and string)
|
||||
printf("Hex: ");
|
||||
for (size_t i = 0; i < written; i++) printf("%02x ", (unsigned char)buf[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("String: ");
|
||||
for (size_t i = 0; i < written; i++) {
|
||||
if (buf[i] == 0x1b) {
|
||||
printf("\\x1b");
|
||||
} else {
|
||||
printf("%c", buf[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
ghostty_key_event_free(event);
|
||||
ghostty_key_encoder_free(encoder);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Example: `ghostty-vt` Mode Utilities
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` mode
|
||||
utilities to pack and unpack terminal mode identifiers and encode
|
||||
DECRPM responses.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_modes",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_modes,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x67ce079ebc70a02a,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [modes-pack-unpack]
|
||||
void modes_example() {
|
||||
// Create a mode for DEC mode 25 (cursor visible)
|
||||
GhosttyMode tag = ghostty_mode_new(25, false);
|
||||
printf("value=%u ansi=%d packed=0x%04x\n",
|
||||
ghostty_mode_value(tag),
|
||||
ghostty_mode_ansi(tag),
|
||||
tag);
|
||||
|
||||
// Create a mode for ANSI mode 4 (insert mode)
|
||||
GhosttyMode ansi_tag = ghostty_mode_new(4, true);
|
||||
printf("value=%u ansi=%d packed=0x%04x\n",
|
||||
ghostty_mode_value(ansi_tag),
|
||||
ghostty_mode_ansi(ansi_tag),
|
||||
ansi_tag);
|
||||
}
|
||||
//! [modes-pack-unpack]
|
||||
|
||||
//! [modes-decrpm]
|
||||
void decrpm_example() {
|
||||
char buf[32];
|
||||
size_t written = 0;
|
||||
|
||||
// Encode a report that DEC mode 25 (cursor visible) is set
|
||||
GhosttyResult result = ghostty_mode_report_encode(
|
||||
GHOSTTY_MODE_CURSOR_VISIBLE,
|
||||
GHOSTTY_MODE_REPORT_SET,
|
||||
buf, sizeof(buf), &written);
|
||||
|
||||
if (result == GHOSTTY_SUCCESS) {
|
||||
printf("Encoded %zu bytes: ", written);
|
||||
fwrite(buf, 1, written, stdout);
|
||||
printf("\n"); // prints: ESC[?25;1$y
|
||||
}
|
||||
}
|
||||
//! [modes-decrpm]
|
||||
|
||||
int main() {
|
||||
modes_example();
|
||||
decrpm_example();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
GhosttyMouseEncoder encoder;
|
||||
GhosttyResult result = ghostty_mouse_encoder_new(NULL, &encoder);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Set tracking mode to normal (button press/release)
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_EVENT,
|
||||
&(GhosttyMouseTrackingMode){GHOSTTY_MOUSE_TRACKING_NORMAL});
|
||||
|
||||
// Set output format to SGR
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_FORMAT,
|
||||
&(GhosttyMouseFormat){GHOSTTY_MOUSE_FORMAT_SGR});
|
||||
|
||||
// Set terminal geometry so the encoder can map pixel positions to cells
|
||||
ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_SIZE,
|
||||
&(GhosttyMouseEncoderSize){
|
||||
.size = sizeof(GhosttyMouseEncoderSize),
|
||||
.screen_width = 800,
|
||||
.screen_height = 600,
|
||||
.cell_width = 10,
|
||||
.cell_height = 20,
|
||||
.padding_top = 0,
|
||||
.padding_bottom = 0,
|
||||
.padding_right = 0,
|
||||
.padding_left = 0,
|
||||
});
|
||||
|
||||
// Create mouse event: left button press at pixel position (50, 40)
|
||||
GhosttyMouseEvent event;
|
||||
result = ghostty_mouse_event_new(NULL, &event);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
ghostty_mouse_event_set_action(event, GHOSTTY_MOUSE_ACTION_PRESS);
|
||||
ghostty_mouse_event_set_button(event, GHOSTTY_MOUSE_BUTTON_LEFT);
|
||||
ghostty_mouse_event_set_position(event, (GhosttyMousePosition){.x = 50.0f, .y = 40.0f});
|
||||
printf("Encoding event: left button press at (50, 40) in SGR format\n");
|
||||
|
||||
// Optionally, encode with null buffer to get required size. You can
|
||||
// skip this step and provide a sufficiently large buffer directly.
|
||||
// If there isn't enough space, the function will return an out of memory
|
||||
// error.
|
||||
size_t required = 0;
|
||||
result = ghostty_mouse_encoder_encode(encoder, event, NULL, 0, &required);
|
||||
assert(result == GHOSTTY_OUT_OF_MEMORY);
|
||||
printf("Required buffer size: %zu bytes\n", required);
|
||||
|
||||
// Encode the mouse event. We don't use our required size above because
|
||||
// that was just an example; we know 128 bytes is enough.
|
||||
char buf[128];
|
||||
size_t written = 0;
|
||||
result = ghostty_mouse_encoder_encode(encoder, event, buf, sizeof(buf), &written);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
printf("Encoded %zu bytes\n", written);
|
||||
|
||||
// Print the encoded sequence (hex and string)
|
||||
printf("Hex: ");
|
||||
for (size_t i = 0; i < written; i++) printf("%02x ", (unsigned char)buf[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("String: ");
|
||||
for (size_t i = 0; i < written; i++) {
|
||||
if (buf[i] == 0x1b) {
|
||||
printf("\\x1b");
|
||||
} else {
|
||||
printf("%c", buf[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
ghostty_mouse_event_free(event);
|
||||
ghostty_mouse_encoder_free(encoder);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2,18 +2,23 @@
|
|||
#include <string.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
// Test safe paste data
|
||||
const char *safe_data = "hello world";
|
||||
//! [paste-safety]
|
||||
void basic_example() {
|
||||
const char* safe_data = "hello world";
|
||||
const char* unsafe_data = "rm -rf /\n";
|
||||
|
||||
if (ghostty_paste_is_safe(safe_data, strlen(safe_data))) {
|
||||
printf("'%s' is safe to paste\n", safe_data);
|
||||
printf("Safe to paste\n");
|
||||
}
|
||||
|
||||
// Test unsafe paste data with newline
|
||||
const char *unsafe_newline = "rm -rf /\n";
|
||||
if (!ghostty_paste_is_safe(unsafe_newline, strlen(unsafe_newline))) {
|
||||
printf("'%s' is UNSAFE - contains newline\n", unsafe_newline);
|
||||
if (!ghostty_paste_is_safe(unsafe_data, strlen(unsafe_data))) {
|
||||
printf("Unsafe! Contains newline\n");
|
||||
}
|
||||
}
|
||||
//! [paste-safety]
|
||||
|
||||
int main() {
|
||||
basic_example();
|
||||
|
||||
// Test unsafe paste data with bracketed paste end sequence
|
||||
const char *unsafe_escape = "evil\x1b[201~code";
|
||||
|
|
|
|||
|
|
@ -2,12 +2,43 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
int main() {
|
||||
//! [sgr-basic]
|
||||
void basic_example() {
|
||||
// Create parser
|
||||
GhosttySgrParser parser;
|
||||
GhosttyResult result = ghostty_sgr_new(NULL, &parser);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Parse "bold, red foreground" sequence: ESC[1;31m
|
||||
uint16_t params[] = {1, 31};
|
||||
result = ghostty_sgr_set_params(parser, params, NULL, 2);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Iterate through attributes
|
||||
GhosttySgrAttribute attr;
|
||||
while (ghostty_sgr_next(parser, &attr)) {
|
||||
switch (attr.tag) {
|
||||
case GHOSTTY_SGR_ATTR_BOLD:
|
||||
printf("Bold enabled\n");
|
||||
break;
|
||||
case GHOSTTY_SGR_ATTR_FG_8:
|
||||
printf("Foreground color: %d\n", attr.value.fg_8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ghostty_sgr_free(parser);
|
||||
}
|
||||
//! [sgr-basic]
|
||||
|
||||
void advanced_example() {
|
||||
GhosttySgrParser parser;
|
||||
GhosttyResult result = ghostty_sgr_new(NULL, &parser);
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
// Parse a complex SGR sequence from Kakoune
|
||||
// This corresponds to the escape sequence:
|
||||
// ESC[4:3;38;2;51;51;51;48;2;170;170;170;58;2;255;97;136m
|
||||
|
|
@ -26,10 +57,9 @@ int main() {
|
|||
result = ghostty_sgr_set_params(parser, params, separators, sizeof(params) / sizeof(params[0]));
|
||||
assert(result == GHOSTTY_SUCCESS);
|
||||
|
||||
printf("Parsing Kakoune SGR sequence:\n");
|
||||
printf("\nParsing Kakoune SGR sequence:\n");
|
||||
printf("ESC[4:3;38;2;51;51;51;48;2;170;170;170;58;2;255;97;136m\n\n");
|
||||
|
||||
// Iterate through attributes
|
||||
GhosttySgrAttribute attr;
|
||||
int count = 0;
|
||||
while (ghostty_sgr_next(parser, &attr)) {
|
||||
|
|
@ -124,8 +154,11 @@ int main() {
|
|||
}
|
||||
|
||||
printf("\nTotal attributes parsed: %d\n", count);
|
||||
|
||||
// Cleanup
|
||||
ghostty_sgr_free(parser);
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_example();
|
||||
advanced_example();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# Example: `ghostty-vt` Size Report Encoding
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` size report
|
||||
encoding API to encode terminal size reports into escape sequences.
|
||||
|
||||
This uses a `build.zig` and `Zig` to build the C program so that we
|
||||
can reuse a lot of our build logic and depend directly on our source
|
||||
tree, but Ghostty emits a standard C library that can be used with any
|
||||
C tooling.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the program:
|
||||
|
||||
```shell-session
|
||||
zig build run
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe_mod.addCSourceFiles(.{
|
||||
.root = b.path("src"),
|
||||
.files = &.{"main.c"},
|
||||
});
|
||||
|
||||
// You'll want to use a lazy dependency here so that ghostty is only
|
||||
// downloaded if you actually need it.
|
||||
if (b.lazyDependency("ghostty", .{
|
||||
// Setting simd to false will force a pure static build that
|
||||
// doesn't even require libc, but it has a significant performance
|
||||
// penalty. If your embedding app requires libc anyway, you should
|
||||
// always keep simd enabled.
|
||||
// .simd = false,
|
||||
})) |dep| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_size_report",
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Run
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| run_cmd.addArgs(args);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_size_report,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x17e8cdb658fab232,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.dependencies = .{
|
||||
// Ghostty dependency. In reality, you'd probably use a URL-based
|
||||
// dependency like the one showed (and commented out) below this one.
|
||||
// We use a path dependency here for simplicity and to ensure our
|
||||
// examples always test against the source they're bundled with.
|
||||
.ghostty = .{ .path = "../../" },
|
||||
|
||||
// Example of what a URL-based dependency looks like:
|
||||
// .ghostty = .{
|
||||
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
|
||||
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
|
||||
// },
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [size-report-encode]
|
||||
int main() {
|
||||
GhosttySizeReportSize size = {
|
||||
.rows = 24,
|
||||
.columns = 80,
|
||||
.cell_width = 9,
|
||||
.cell_height = 18,
|
||||
};
|
||||
|
||||
char buf[64];
|
||||
size_t written = 0;
|
||||
|
||||
GhosttyResult result = ghostty_size_report_encode(
|
||||
GHOSTTY_SIZE_REPORT_MODE_2048, size, buf, sizeof(buf), &written);
|
||||
|
||||
if (result == GHOSTTY_SUCCESS) {
|
||||
printf("Encoded %zu bytes: ", written);
|
||||
fwrite(buf, 1, written, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [size-report-encode]
|
||||
|
|
@ -45,8 +45,8 @@
|
|||
*
|
||||
* Complete working examples:
|
||||
* - @ref c-vt/src/main.c - OSC parser example
|
||||
* - @ref c-vt-key-encode/src/main.c - Key encoding example
|
||||
* - @ref c-vt-mouse-encode/src/main.c - Mouse encoding example
|
||||
* - @ref c-vt-encode-key/src/main.c - Key encoding example
|
||||
* - @ref c-vt-encode-mouse/src/main.c - Mouse encoding example
|
||||
* - @ref c-vt-paste/src/main.c - Paste safety check example
|
||||
* - @ref c-vt-sgr/src/main.c - SGR parser example
|
||||
* - @ref c-vt-formatter/src/main.c - Terminal formatter example
|
||||
|
|
@ -58,12 +58,12 @@
|
|||
* extract command information, and retrieve command-specific data like window titles.
|
||||
*/
|
||||
|
||||
/** @example c-vt-key-encode/src/main.c
|
||||
/** @example c-vt-encode-key/src/main.c
|
||||
* This example demonstrates how to use the key encoder to convert key events
|
||||
* into terminal escape sequences using the Kitty keyboard protocol.
|
||||
*/
|
||||
|
||||
/** @example c-vt-mouse-encode/src/main.c
|
||||
/** @example c-vt-encode-mouse/src/main.c
|
||||
* This example demonstrates how to use the mouse encoder to convert mouse events
|
||||
* into terminal escape sequences using the SGR mouse format.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -20,26 +20,7 @@
|
|||
*
|
||||
* ## Example
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <stdio.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* char buf[8];
|
||||
* size_t written = 0;
|
||||
*
|
||||
* GhosttyResult result = ghostty_focus_encode(
|
||||
* GHOSTTY_FOCUS_GAINED, buf, sizeof(buf), &written);
|
||||
*
|
||||
* if (result == GHOSTTY_SUCCESS) {
|
||||
* printf("Encoded %zu bytes: ", written);
|
||||
* fwrite(buf, 1, written, stdout);
|
||||
* printf("\n");
|
||||
* }
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* @snippet c-vt-encode-focus/src/main.c focus-encode
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -27,49 +27,12 @@
|
|||
* changing its properties.
|
||||
* 4. Free the encoder with ghostty_key_encoder_free() when done
|
||||
*
|
||||
* For a complete working example, see example/c-vt-key-encode in the
|
||||
* For a complete working example, see example/c-vt-encode-key in the
|
||||
* repository.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <assert.h>
|
||||
* #include <stdio.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* // Create encoder
|
||||
* GhosttyKeyEncoder encoder;
|
||||
* GhosttyResult result = ghostty_key_encoder_new(NULL, &encoder);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
*
|
||||
* // Enable Kitty keyboard protocol with all features
|
||||
* ghostty_key_encoder_setopt(encoder, GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS,
|
||||
* &(uint8_t){GHOSTTY_KITTY_KEY_ALL});
|
||||
*
|
||||
* // Create and configure key event for Ctrl+C press
|
||||
* GhosttyKeyEvent event;
|
||||
* result = ghostty_key_event_new(NULL, &event);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
* ghostty_key_event_set_action(event, GHOSTTY_KEY_ACTION_PRESS);
|
||||
* ghostty_key_event_set_key(event, GHOSTTY_KEY_C);
|
||||
* ghostty_key_event_set_mods(event, GHOSTTY_MODS_CTRL);
|
||||
*
|
||||
* // Encode the key event
|
||||
* char buf[128];
|
||||
* size_t written = 0;
|
||||
* result = ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
*
|
||||
* // Use the encoded sequence (e.g., write to terminal)
|
||||
* fwrite(buf, 1, written, stdout);
|
||||
*
|
||||
* // Cleanup
|
||||
* ghostty_key_event_free(event);
|
||||
* ghostty_key_encoder_free(encoder);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* @snippet c-vt-encode-key/src/main.c key-encode
|
||||
*
|
||||
* ## Example: Encoding with Terminal State
|
||||
*
|
||||
|
|
|
|||
|
|
@ -20,57 +20,14 @@
|
|||
*
|
||||
* ## Example
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <stdio.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* // Create a mode for DEC mode 25 (cursor visible)
|
||||
* GhosttyMode tag = ghostty_mode_new(25, false);
|
||||
* printf("value=%u ansi=%d packed=0x%04x\n",
|
||||
* ghostty_mode_value(tag),
|
||||
* ghostty_mode_ansi(tag),
|
||||
* tag);
|
||||
*
|
||||
* // Create a mode for ANSI mode 4 (insert mode)
|
||||
* GhosttyMode ansi_tag = ghostty_mode_new(4, true);
|
||||
* printf("value=%u ansi=%d packed=0x%04x\n",
|
||||
* ghostty_mode_value(ansi_tag),
|
||||
* ghostty_mode_ansi(ansi_tag),
|
||||
* ansi_tag);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* @snippet c-vt-modes/src/main.c modes-pack-unpack
|
||||
*
|
||||
* ## DECRPM Report Encoding
|
||||
*
|
||||
* Use ghostty_mode_report_encode() to encode a DECRPM response into a
|
||||
* caller-provided buffer:
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <stdio.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* char buf[32];
|
||||
* size_t written = 0;
|
||||
*
|
||||
* // Encode a report that DEC mode 25 (cursor visible) is set
|
||||
* GhosttyResult result = ghostty_mode_report_encode(
|
||||
* GHOSTTY_MODE_CURSOR_VISIBLE,
|
||||
* GHOSTTY_MODE_REPORT_SET,
|
||||
* buf, sizeof(buf), &written);
|
||||
*
|
||||
* if (result == GHOSTTY_SUCCESS) {
|
||||
* printf("Encoded %zu bytes: ", written);
|
||||
* fwrite(buf, 1, written, stdout);
|
||||
* printf("\n"); // prints: ESC[?25;1$y
|
||||
* }
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* @snippet c-vt-modes/src/main.c modes-decrpm
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -24,61 +24,12 @@
|
|||
* - Free the event with ghostty_mouse_event_free() or reuse it.
|
||||
* 4. Free the encoder with ghostty_mouse_encoder_free() when done.
|
||||
*
|
||||
* For a complete working example, see example/c-vt-mouse-encode in the
|
||||
* For a complete working example, see example/c-vt-encode-mouse in the
|
||||
* repository.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <assert.h>
|
||||
* #include <stdio.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* // Create encoder
|
||||
* GhosttyMouseEncoder encoder;
|
||||
* GhosttyResult result = ghostty_mouse_encoder_new(NULL, &encoder);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
*
|
||||
* // Configure SGR format with normal tracking
|
||||
* ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_EVENT,
|
||||
* &(GhosttyMouseTrackingMode){GHOSTTY_MOUSE_TRACKING_NORMAL});
|
||||
* ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_FORMAT,
|
||||
* &(GhosttyMouseFormat){GHOSTTY_MOUSE_FORMAT_SGR});
|
||||
*
|
||||
* // Set terminal geometry for coordinate mapping
|
||||
* ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_SIZE,
|
||||
* &(GhosttyMouseEncoderSize){
|
||||
* .size = sizeof(GhosttyMouseEncoderSize),
|
||||
* .screen_width = 800, .screen_height = 600,
|
||||
* .cell_width = 10, .cell_height = 20,
|
||||
* });
|
||||
*
|
||||
* // Create and configure a left button press event
|
||||
* GhosttyMouseEvent event;
|
||||
* result = ghostty_mouse_event_new(NULL, &event);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
* ghostty_mouse_event_set_action(event, GHOSTTY_MOUSE_ACTION_PRESS);
|
||||
* ghostty_mouse_event_set_button(event, GHOSTTY_MOUSE_BUTTON_LEFT);
|
||||
* ghostty_mouse_event_set_position(event,
|
||||
* (GhosttyMousePosition){.x = 50.0f, .y = 40.0f});
|
||||
*
|
||||
* // Encode the mouse event
|
||||
* char buf[128];
|
||||
* size_t written = 0;
|
||||
* result = ghostty_mouse_encoder_encode(encoder, event,
|
||||
* buf, sizeof(buf), &written);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
*
|
||||
* // Use the encoded sequence (e.g., write to terminal)
|
||||
* fwrite(buf, 1, written, stdout);
|
||||
*
|
||||
* // Cleanup
|
||||
* ghostty_mouse_event_free(event);
|
||||
* ghostty_mouse_encoder_free(encoder);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* @snippet c-vt-encode-mouse/src/main.c mouse-encode
|
||||
*
|
||||
* ## Example: Encoding with Terminal State
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,26 +18,7 @@
|
|||
*
|
||||
* ## Example
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <stdio.h>
|
||||
* #include <string.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* const char* safe_data = "hello world";
|
||||
* const char* unsafe_data = "rm -rf /\n";
|
||||
*
|
||||
* if (ghostty_paste_is_safe(safe_data, strlen(safe_data))) {
|
||||
* printf("Safe to paste\n");
|
||||
* }
|
||||
*
|
||||
* if (!ghostty_paste_is_safe(unsafe_data, strlen(unsafe_data))) {
|
||||
* printf("Unsafe! Contains newline\n");
|
||||
* }
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* @snippet c-vt-paste/src/main.c paste-safety
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -31,42 +31,7 @@
|
|||
*
|
||||
* ## Example
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <assert.h>
|
||||
* #include <stdio.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* // Create parser
|
||||
* GhosttySgrParser parser;
|
||||
* GhosttyResult result = ghostty_sgr_new(NULL, &parser);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
*
|
||||
* // Parse "bold, red foreground" sequence: ESC[1;31m
|
||||
* uint16_t params[] = {1, 31};
|
||||
* result = ghostty_sgr_set_params(parser, params, NULL, 2);
|
||||
* assert(result == GHOSTTY_SUCCESS);
|
||||
*
|
||||
* // Iterate through attributes
|
||||
* GhosttySgrAttribute attr;
|
||||
* while (ghostty_sgr_next(parser, &attr)) {
|
||||
* switch (attr.tag) {
|
||||
* case GHOSTTY_SGR_ATTR_BOLD:
|
||||
* printf("Bold enabled\n");
|
||||
* break;
|
||||
* case GHOSTTY_SGR_ATTR_FG_8:
|
||||
* printf("Foreground color: %d\n", attr.value.fg_8);
|
||||
* break;
|
||||
* default:
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Cleanup
|
||||
* ghostty_sgr_free(parser);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* @snippet c-vt-sgr/src/main.c sgr-basic
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -22,33 +22,7 @@
|
|||
*
|
||||
* ## Example
|
||||
*
|
||||
* @code{.c}
|
||||
* #include <stdio.h>
|
||||
* #include <ghostty/vt.h>
|
||||
*
|
||||
* int main() {
|
||||
* GhosttySizeReportSize size = {
|
||||
* .rows = 24,
|
||||
* .columns = 80,
|
||||
* .cell_width = 9,
|
||||
* .cell_height = 18,
|
||||
* };
|
||||
*
|
||||
* char buf[64];
|
||||
* size_t written = 0;
|
||||
*
|
||||
* GhosttyResult result = ghostty_size_report_encode(
|
||||
* GHOSTTY_SIZE_REPORT_MODE_2048, size, buf, sizeof(buf), &written);
|
||||
*
|
||||
* if (result == GHOSTTY_SUCCESS) {
|
||||
* printf("Encoded %zu bytes: ", written);
|
||||
* fwrite(buf, 1, written, stdout);
|
||||
* printf("\n");
|
||||
* }
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* @snippet c-vt-size-report/src/main.c size-report-encode
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue