Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/inspector/termio.zig
Original file line number Diff line number Diff line change
Expand Up @@ -286,18 +286,19 @@ pub const VTEvent = struct {
),

else => switch (Value) {
u8, u16 => try md.put(
key,
try std.fmt.allocPrintSentinel(alloc, "{}", .{value}, 0),
),

[]const u8,
[:0]const u8,
=> try md.put(key, try alloc.dupeZ(u8, value)),

else => |T| {
@compileLog(T);
@compileError("unsupported type, see log");
else => switch (@typeInfo(Value)) {
.int => try md.put(
key,
try std.fmt.allocPrintSentinel(alloc, "{}", .{value}, 0),
),
else => {
@compileLog(Value);
@compileError("unsupported type, see log");
},
},
},
}
Expand Down
3 changes: 3 additions & 0 deletions src/terminal/kitty.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ const build_options = @import("terminal_options");
const key = @import("kitty/key.zig");
pub const color = @import("kitty/color.zig");
pub const graphics = if (build_options.kitty_graphics) @import("kitty/graphics.zig") else struct {};
pub const text_sizing = @import("kitty/text_sizing.zig");
pub const encoding = @import("kitty/encoding.zig");
pub const notification = @import("kitty/notification.zig");

pub const KeyFlags = key.Flags;
pub const KeyFlagStack = key.FlagStack;
Expand Down
21 changes: 21 additions & 0 deletions src/terminal/kitty/encoding.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! Encodings used by various Kitty protocol extensions.
const std = @import("std");

/// Kitty defines "URL-safe UTF-8" as valid UTF-8 with the additional
/// requirement of not containing any C0 escape codes (0x00-0x1f)
pub fn isUrlSafeUtf8(s: []const u8) bool {
if (!std.unicode.utf8ValidateSlice(s)) {
@branchHint(.cold);
return false;
}

for (s) |c| switch (c) {
0x00...0x1f => {
@branchHint(.cold);
return false;
},
else => {},
};

return true;
}
81 changes: 81 additions & 0 deletions src/terminal/kitty/text_sizing.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//! Kitty's text sizing protocol (OSC 66)
//! Specification: https://sw.kovidgoyal.net/kitty/text-sizing-protocol/

const std = @import("std");
const build_options = @import("terminal_options");

const encoding = @import("encoding.zig");
const lib = @import("../../lib/main.zig");
const lib_target: lib.Target = if (build_options.c_abi) .c else .zig;

const log = std.log.scoped(.kitty_text_sizing);

pub const max_payload_length = 4096;

pub const VAlign = lib.Enum(lib_target, &.{
"top",
"bottom",
"center",
});

pub const HAlign = lib.Enum(lib_target, &.{
"left",
"right",
"center",
});

pub const OSC = struct {
scale: u3 = 1, // 1 - 7
width: u3 = 0, // 0 - 7 (0 means default)
numerator: u4 = 0,
denominator: u4 = 0,
valign: VAlign = .top,
halign: HAlign = .left,
text: [:0]const u8,

/// We don't currently support encoding this to C in any way.
pub const C = void;

pub fn cval(_: OSC) C {
return {};
}

pub fn set(self: *OSC, key: u8, value: []const u8) !void {
const v = std.fmt.parseInt(
u4,
value,
10,
) catch return error.InvalidValue;

switch (key) {
's' => self.scale = std.math.cast(u3, v) orelse return error.InvalidValue,
'w' => self.width = std.math.cast(u3, v) orelse return error.InvalidValue,
'n' => self.numerator = v,
'd' => self.denominator = v,
'v' => self.valign = std.enums.fromInt(VAlign, v) orelse return error.InvalidValue,
'h' => self.halign = std.enums.fromInt(HAlign, v) orelse return error.InvalidValue,
else => return error.UnknownKey,
}
}

pub fn validate(self: OSC) bool {
if (self.text.len > max_payload_length) {
@branchHint(.cold);
log.warn("kitty text sizing payload exceeds maximum size", .{});
return false;
}

if (!encoding.isUrlSafeUtf8(self.text)) {
@branchHint(.cold);
log.warn("kitty text sizing payload is not URL-safe UTF-8", .{});
return false;
}

if (self.scale == 0) {
@branchHint(.cold);
log.warn("kitty text sizing cannot have 0 scale", .{});
return false;
}
return true;
}
};
Loading
Loading