diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/config/formatter.zig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/config/formatter.zig')
| -rw-r--r-- | vendor/libghostty-vt/src/config/formatter.zig | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/config/formatter.zig b/vendor/libghostty-vt/src/config/formatter.zig new file mode 100644 index 00000000..00d946f8 --- /dev/null +++ b/vendor/libghostty-vt/src/config/formatter.zig @@ -0,0 +1,232 @@ +const formatter = @This(); + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const Key = @import("key.zig").Key; + +/// Returns a single entry formatter for the given field name and writer. +pub fn entryFormatter( + name: []const u8, + writer: *std.Io.Writer, +) EntryFormatter { + return .{ .name = name, .writer = writer }; +} + +/// The entry formatter type for a given writer. +pub const EntryFormatter = struct { + name: []const u8, + writer: *std.Io.Writer, + + pub fn formatEntry( + self: @This(), + comptime T: type, + value: T, + ) !void { + return formatter.formatEntry( + T, + self.name, + value, + self.writer, + ); + } +}; + +/// Format a single type with the given name and value. +pub fn formatEntry( + comptime T: type, + name: []const u8, + value: T, + writer: *std.Io.Writer, +) !void { + switch (@typeInfo(T)) { + .bool, .int => { + try writer.print("{s} = {}\n", .{ name, value }); + return; + }, + + .float => { + try writer.print("{s} = {d}\n", .{ name, value }); + return; + }, + + .@"enum" => { + try writer.print("{s} = {t}\n", .{ name, value }); + return; + }, + + .void => { + try writer.print("{s} = \n", .{name}); + return; + }, + + .optional => |info| { + if (value) |inner| { + try formatEntry( + info.child, + name, + inner, + writer, + ); + } else { + try writer.print("{s} = \n", .{name}); + } + + return; + }, + + .pointer => switch (T) { + []const u8, + [:0]const u8, + => { + try writer.print("{s} = {s}\n", .{ name, value }); + return; + }, + + else => {}, + }, + + // Structs of all types require a "formatEntry" function + // to be defined which will be called to format the value. + // This is given the formatter in use so that they can + // call BACK to our formatEntry to write each primitive + // value. + .@"struct" => |info| if (@hasDecl(T, "formatEntry")) { + try value.formatEntry(entryFormatter(name, writer)); + return; + } else switch (info.layout) { + // Packed structs we special case. + .@"packed" => { + try writer.print("{s} = ", .{name}); + inline for (info.fields, 0..) |field, i| { + if (i > 0) try writer.print(",", .{}); + try writer.print("{s}{s}", .{ + if (!@field(value, field.name)) "no-" else "", + field.name, + }); + } + try writer.print("\n", .{}); + return; + }, + + else => {}, + }, + + .@"union" => if (@hasDecl(T, "formatEntry")) { + try value.formatEntry(entryFormatter(name, writer)); + return; + }, + + else => {}, + } + + // Compile error so that we can catch missing cases. + @compileLog(T); + @compileError("missing case for type"); +} + +test "formatEntry bool" { + const testing = std.testing; + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(bool, "a", true, &buf.writer); + try testing.expectEqualStrings("a = true\n", buf.written()); + } + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(bool, "a", false, &buf.writer); + try testing.expectEqualStrings("a = false\n", buf.written()); + } +} + +test "formatEntry int" { + const testing = std.testing; + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(u8, "a", 123, &buf.writer); + try testing.expectEqualStrings("a = 123\n", buf.written()); + } +} + +test "formatEntry float" { + const testing = std.testing; + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(f64, "a", 0.7, &buf.writer); + try testing.expectEqualStrings("a = 0.7\n", buf.written()); + } +} + +test "formatEntry enum" { + const testing = std.testing; + const Enum = enum { one, two, three }; + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(Enum, "a", .two, &buf.writer); + try testing.expectEqualStrings("a = two\n", buf.written()); + } +} + +test "formatEntry void" { + const testing = std.testing; + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(void, "a", {}, &buf.writer); + try testing.expectEqualStrings("a = \n", buf.written()); + } +} + +test "formatEntry optional" { + const testing = std.testing; + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(?bool, "a", null, &buf.writer); + try testing.expectEqualStrings("a = \n", buf.written()); + } + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(?bool, "a", false, &buf.writer); + try testing.expectEqualStrings("a = false\n", buf.written()); + } +} + +test "formatEntry string" { + const testing = std.testing; + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry([]const u8, "a", "hello", &buf.writer); + try testing.expectEqualStrings("a = hello\n", buf.written()); + } +} + +test "formatEntry packed struct" { + const testing = std.testing; + const Value = packed struct { + one: bool = true, + two: bool = false, + }; + + { + var buf: std.Io.Writer.Allocating = .init(testing.allocator); + defer buf.deinit(); + try formatEntry(Value, "a", .{}, &buf.writer); + try testing.expectEqualStrings("a = one,no-two\n", buf.written()); + } +} |
