mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
terminal: yeet usingnamespace
This commit is contained in:
@ -1,7 +1,11 @@
|
||||
//! Types and functions related to Kitty protocols.
|
||||
|
||||
const key = @import("kitty/key.zig");
|
||||
pub const graphics = @import("kitty/graphics.zig");
|
||||
pub usingnamespace @import("kitty/key.zig");
|
||||
|
||||
pub const KeyFlags = key.Flags;
|
||||
pub const KeyFlagStack = key.FlagStack;
|
||||
pub const KeySetMode = key.SetMode;
|
||||
|
||||
test {
|
||||
@import("std").testing.refAllDecls(@This());
|
||||
|
@ -17,12 +17,19 @@
|
||||
//! though and I think we can go back through and fix this up.
|
||||
|
||||
const render = @import("graphics_render.zig");
|
||||
pub usingnamespace @import("graphics_command.zig");
|
||||
pub usingnamespace @import("graphics_exec.zig");
|
||||
pub usingnamespace @import("graphics_image.zig");
|
||||
pub usingnamespace @import("graphics_storage.zig");
|
||||
const command = @import("graphics_command.zig");
|
||||
const exec = @import("graphics_exec.zig");
|
||||
const image = @import("graphics_image.zig");
|
||||
const storage = @import("graphics_storage.zig");
|
||||
pub const unicode = @import("graphics_unicode.zig");
|
||||
pub const Command = command.Command;
|
||||
pub const CommandParser = command.Parser;
|
||||
pub const Image = image.Image;
|
||||
pub const ImageStorage = storage.ImageStorage;
|
||||
pub const RenderPlacement = render.Placement;
|
||||
pub const Response = command.Response;
|
||||
|
||||
pub const execute = exec.execute;
|
||||
|
||||
test {
|
||||
@import("std").testing.refAllDecls(@This());
|
||||
|
@ -15,7 +15,7 @@ const log = std.log.scoped(.kitty_gfx);
|
||||
const KV = std.AutoHashMapUnmanaged(u8, u32);
|
||||
|
||||
/// Command parser parses the Kitty graphics protocol escape sequence.
|
||||
pub const CommandParser = struct {
|
||||
pub const Parser = struct {
|
||||
/// The memory used by the parser is stored in an arena because it is
|
||||
/// all freed at the end of the command.
|
||||
arena: ArenaAllocator,
|
||||
@ -54,7 +54,7 @@ pub const CommandParser = struct {
|
||||
|
||||
/// Initialize the parser. The allocator given will be used for both
|
||||
/// temporary data and long-lived values such as the final image blob.
|
||||
pub fn init(alloc: Allocator) CommandParser {
|
||||
pub fn init(alloc: Allocator) Parser {
|
||||
var arena = ArenaAllocator.init(alloc);
|
||||
errdefer arena.deinit();
|
||||
return .{
|
||||
@ -63,7 +63,7 @@ pub const CommandParser = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *CommandParser) void {
|
||||
pub fn deinit(self: *Parser) void {
|
||||
// We don't free the hash map because its in the arena
|
||||
self.arena.deinit();
|
||||
self.data.deinit();
|
||||
@ -74,7 +74,7 @@ pub const CommandParser = struct {
|
||||
/// The first byte to start parsing should be the byte immediately following
|
||||
/// the "G" in the APC sequence, i.e. "\x1b_G123" the first byte should
|
||||
/// be "1".
|
||||
pub fn feed(self: *CommandParser, c: u8) !void {
|
||||
pub fn feed(self: *Parser, c: u8) !void {
|
||||
switch (self.state) {
|
||||
.control_key => switch (c) {
|
||||
// '=' means the key is complete and we're moving to the value.
|
||||
@ -119,7 +119,7 @@ pub const CommandParser = struct {
|
||||
///
|
||||
/// The allocator given will be used for the long-lived data
|
||||
/// of the final command.
|
||||
pub fn complete(self: *CommandParser) !Command {
|
||||
pub fn complete(self: *Parser) !Command {
|
||||
switch (self.state) {
|
||||
// We can't ever end in the control key state and be valid.
|
||||
// This means the command looked something like "a=1,b"
|
||||
@ -175,7 +175,7 @@ pub const CommandParser = struct {
|
||||
/// Decodes the payload data from base64 and returns it as a slice.
|
||||
/// This function will destroy the contents of self.data, it should
|
||||
/// only be used once we are done collecting payload bytes.
|
||||
fn decodeData(self: *CommandParser) ![]const u8 {
|
||||
fn decodeData(self: *Parser) ![]const u8 {
|
||||
if (self.data.items.len == 0) {
|
||||
return "";
|
||||
}
|
||||
@ -202,7 +202,7 @@ pub const CommandParser = struct {
|
||||
return try self.data.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn accumulateValue(self: *CommandParser, c: u8, overflow_state: State) !void {
|
||||
fn accumulateValue(self: *Parser, c: u8, overflow_state: State) !void {
|
||||
const idx = self.kv_temp_len;
|
||||
self.kv_temp_len += 1;
|
||||
if (self.kv_temp_len > self.kv_temp.len) {
|
||||
@ -213,7 +213,7 @@ pub const CommandParser = struct {
|
||||
self.kv_temp[idx] = c;
|
||||
}
|
||||
|
||||
fn finishValue(self: *CommandParser, next_state: State) !void {
|
||||
fn finishValue(self: *Parser, next_state: State) !void {
|
||||
const alloc = self.arena.allocator();
|
||||
|
||||
// We can move states right away, we don't use it.
|
||||
@ -896,7 +896,7 @@ pub const CompositionMode = enum {
|
||||
test "transmission command" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
var p = CommandParser.init(alloc);
|
||||
var p = Parser.init(alloc);
|
||||
defer p.deinit();
|
||||
|
||||
const input = "f=24,s=10,v=20";
|
||||
@ -914,7 +914,7 @@ test "transmission command" {
|
||||
test "query command" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
var p = CommandParser.init(alloc);
|
||||
var p = Parser.init(alloc);
|
||||
defer p.deinit();
|
||||
|
||||
const input = "i=31,s=1,v=1,a=q,t=d,f=24;QUFBQQ";
|
||||
@ -934,7 +934,7 @@ test "query command" {
|
||||
test "display command" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
var p = CommandParser.init(alloc);
|
||||
var p = Parser.init(alloc);
|
||||
defer p.deinit();
|
||||
|
||||
const input = "a=p,U=1,i=31,c=80,r=120";
|
||||
@ -952,7 +952,7 @@ test "display command" {
|
||||
test "delete command" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
var p = CommandParser.init(alloc);
|
||||
var p = Parser.init(alloc);
|
||||
defer p.deinit();
|
||||
|
||||
const input = "a=d,d=p,x=3,y=4";
|
||||
@ -972,7 +972,7 @@ test "delete command" {
|
||||
test "ignore unknown keys (long)" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
var p = CommandParser.init(alloc);
|
||||
var p = Parser.init(alloc);
|
||||
defer p.deinit();
|
||||
|
||||
const input = "f=24,s=10,v=20,hello=world";
|
||||
@ -990,7 +990,7 @@ test "ignore unknown keys (long)" {
|
||||
test "ignore very long values" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
var p = CommandParser.init(alloc);
|
||||
var p = Parser.init(alloc);
|
||||
defer p.deinit();
|
||||
|
||||
const input = "f=24,s=10,v=2000000000000000000000000000000000000000";
|
||||
|
@ -5,23 +5,23 @@ const std = @import("std");
|
||||
/// Stack for the key flags. This implements the push/pop behavior
|
||||
/// of the CSI > u and CSI < u sequences. We implement the stack as
|
||||
/// fixed size to avoid heap allocation.
|
||||
pub const KeyFlagStack = struct {
|
||||
pub const FlagStack = struct {
|
||||
const len = 8;
|
||||
|
||||
flags: [len]KeyFlags = .{.{}} ** len,
|
||||
flags: [len]Flags = .{.{}} ** len,
|
||||
idx: u3 = 0,
|
||||
|
||||
/// Return the current stack value
|
||||
pub fn current(self: KeyFlagStack) KeyFlags {
|
||||
pub fn current(self: FlagStack) Flags {
|
||||
return self.flags[self.idx];
|
||||
}
|
||||
|
||||
/// Perform the "set" operation as described in the spec for
|
||||
/// the CSI = u sequence.
|
||||
pub fn set(
|
||||
self: *KeyFlagStack,
|
||||
mode: KeySetMode,
|
||||
v: KeyFlags,
|
||||
self: *FlagStack,
|
||||
mode: SetMode,
|
||||
v: Flags,
|
||||
) void {
|
||||
switch (mode) {
|
||||
.set => self.flags[self.idx] = v,
|
||||
@ -36,7 +36,7 @@ pub const KeyFlagStack = struct {
|
||||
|
||||
/// Push a new set of flags onto the stack. If the stack is full
|
||||
/// then the oldest entry is evicted.
|
||||
pub fn push(self: *KeyFlagStack, flags: KeyFlags) void {
|
||||
pub fn push(self: *FlagStack, flags: Flags) void {
|
||||
// Overflow and wrap around if we're full, which evicts
|
||||
// the oldest entry.
|
||||
self.idx +%= 1;
|
||||
@ -45,7 +45,7 @@ pub const KeyFlagStack = struct {
|
||||
|
||||
/// Pop `n` entries from the stack. This will just wrap around
|
||||
/// if `n` is greater than the amount in the stack.
|
||||
pub fn pop(self: *KeyFlagStack, n: usize) void {
|
||||
pub fn pop(self: *FlagStack, n: usize) void {
|
||||
// If n is more than our length then we just reset the stack.
|
||||
// This also avoids a DoS vector where a malicious client
|
||||
// could send a huge number of pop commands to waste cpu.
|
||||
@ -64,7 +64,7 @@ pub const KeyFlagStack = struct {
|
||||
// Make sure we the overflow works as expected
|
||||
test {
|
||||
const testing = std.testing;
|
||||
var stack: KeyFlagStack = .{};
|
||||
var stack: FlagStack = .{};
|
||||
stack.idx = stack.flags.len - 1;
|
||||
stack.idx +%= 1;
|
||||
try testing.expect(stack.idx == 0);
|
||||
@ -76,14 +76,14 @@ pub const KeyFlagStack = struct {
|
||||
};
|
||||
|
||||
/// The possible flags for the Kitty keyboard protocol.
|
||||
pub const KeyFlags = packed struct(u5) {
|
||||
pub const Flags = packed struct(u5) {
|
||||
disambiguate: bool = false,
|
||||
report_events: bool = false,
|
||||
report_alternates: bool = false,
|
||||
report_all: bool = false,
|
||||
report_associated: bool = false,
|
||||
|
||||
pub fn int(self: KeyFlags) u5 {
|
||||
pub fn int(self: Flags) u5 {
|
||||
return @bitCast(self);
|
||||
}
|
||||
|
||||
@ -93,50 +93,50 @@ pub const KeyFlags = packed struct(u5) {
|
||||
|
||||
try testing.expectEqual(
|
||||
@as(u5, 0b1),
|
||||
(KeyFlags{ .disambiguate = true }).int(),
|
||||
(Flags{ .disambiguate = true }).int(),
|
||||
);
|
||||
try testing.expectEqual(
|
||||
@as(u5, 0b10),
|
||||
(KeyFlags{ .report_events = true }).int(),
|
||||
(Flags{ .report_events = true }).int(),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/// The possible modes for setting the key flags.
|
||||
pub const KeySetMode = enum { set, @"or", not };
|
||||
pub const SetMode = enum { set, @"or", not };
|
||||
|
||||
test "KeyFlagStack: push pop" {
|
||||
test "FlagStack: push pop" {
|
||||
const testing = std.testing;
|
||||
var stack: KeyFlagStack = .{};
|
||||
var stack: FlagStack = .{};
|
||||
stack.push(.{ .disambiguate = true });
|
||||
try testing.expectEqual(
|
||||
KeyFlags{ .disambiguate = true },
|
||||
Flags{ .disambiguate = true },
|
||||
stack.current(),
|
||||
);
|
||||
|
||||
stack.pop(1);
|
||||
try testing.expectEqual(KeyFlags{}, stack.current());
|
||||
try testing.expectEqual(Flags{}, stack.current());
|
||||
}
|
||||
|
||||
test "KeyFlagStack: pop big number" {
|
||||
test "FlagStack: pop big number" {
|
||||
const testing = std.testing;
|
||||
var stack: KeyFlagStack = .{};
|
||||
var stack: FlagStack = .{};
|
||||
stack.pop(100);
|
||||
try testing.expectEqual(KeyFlags{}, stack.current());
|
||||
try testing.expectEqual(Flags{}, stack.current());
|
||||
}
|
||||
|
||||
test "KeyFlagStack: set" {
|
||||
test "FlagStack: set" {
|
||||
const testing = std.testing;
|
||||
var stack: KeyFlagStack = .{};
|
||||
var stack: FlagStack = .{};
|
||||
stack.set(.set, .{ .disambiguate = true });
|
||||
try testing.expectEqual(
|
||||
KeyFlags{ .disambiguate = true },
|
||||
Flags{ .disambiguate = true },
|
||||
stack.current(),
|
||||
);
|
||||
|
||||
stack.set(.@"or", .{ .report_events = true });
|
||||
try testing.expectEqual(
|
||||
KeyFlags{
|
||||
Flags{
|
||||
.disambiguate = true,
|
||||
.report_events = true,
|
||||
},
|
||||
@ -145,7 +145,7 @@ test "KeyFlagStack: set" {
|
||||
|
||||
stack.set(.not, .{ .report_events = true });
|
||||
try testing.expectEqual(
|
||||
KeyFlags{ .disambiguate = true },
|
||||
Flags{ .disambiguate = true },
|
||||
stack.current(),
|
||||
);
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub usingnamespace @import("sanitize.zig");
|
||||
|
||||
const charsets = @import("charsets.zig");
|
||||
const sanitize = @import("sanitize.zig");
|
||||
const stream = @import("stream.zig");
|
||||
const ansi = @import("ansi.zig");
|
||||
const csi = @import("csi.zig");
|
||||
@ -57,6 +56,8 @@ pub const EraseLine = csi.EraseLine;
|
||||
pub const TabClear = csi.TabClear;
|
||||
pub const Attribute = sgr.Attribute;
|
||||
|
||||
pub const isSafePaste = sanitize.isSafePaste;
|
||||
|
||||
test {
|
||||
@import("std").testing.refAllDecls(@This());
|
||||
|
||||
|
Reference in New Issue
Block a user