chor: use new Writer interface for terminal's Writer; fix test cases
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 3m38s
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 3m38s
This commit is contained in:
22
src/cell.zig
22
src/cell.zig
@@ -13,7 +13,7 @@ pub fn reset(this: *Cell) void {
|
|||||||
this.cp = ' ';
|
this.cp = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value(this: Cell, writer: anytype) !void {
|
pub fn value(this: Cell, writer: *std.Io.Writer) !void {
|
||||||
try this.style.value(writer, this.cp);
|
try this.style.value(writer, this.cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,17 +29,15 @@ test "ascii styled text" {
|
|||||||
.{ .cp = 's', .style = .{ .fg = .light_green, .bg = .black, .emphasis = &.{.underline} } },
|
.{ .cp = 's', .style = .{ .fg = .light_green, .bg = .black, .emphasis = &.{.underline} } },
|
||||||
};
|
};
|
||||||
|
|
||||||
var string = try std.ArrayList(u8).initCapacity(std.testing.allocator, 4);
|
var writer = std.Io.Writer.Allocating.init(std.testing.allocator);
|
||||||
defer string.deinit(std.testing.allocator);
|
defer writer.deinit();
|
||||||
|
|
||||||
const writer = string.writer(std.testing.allocator);
|
|
||||||
for (cells) |cell| {
|
for (cells) |cell| {
|
||||||
try cell.value(writer);
|
try cell.value(&writer.writer);
|
||||||
}
|
}
|
||||||
try std.testing.expectEqualSlices(
|
try std.testing.expectEqualSlices(
|
||||||
u8,
|
u8,
|
||||||
"\x1b[38;5;10;48;5;8;59mY\x1b[0m\x1b[39;49;59;1;4mv\x1b[0m\x1b[39;49;59;3me\x1b[0m\x1b[38;5;2;48;5;16;59;4ms\x1b[0m",
|
"\x1b[38;5;10;48;5;8;59mY\x1b[0m\x1b[39;49;59;1;4mv\x1b[0m\x1b[39;49;59;3me\x1b[0m\x1b[38;5;2;48;5;16;59;4ms\x1b[0m",
|
||||||
string.items,
|
writer.writer.buffer[0..writer.writer.end],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,16 +49,14 @@ test "utf-8 styled text" {
|
|||||||
.{ .cp = '┘', .style = .{ .fg = .light_green, .bg = .black, .emphasis = &.{.underline} } },
|
.{ .cp = '┘', .style = .{ .fg = .light_green, .bg = .black, .emphasis = &.{.underline} } },
|
||||||
};
|
};
|
||||||
|
|
||||||
var string = try std.ArrayList(u8).initCapacity(std.testing.allocator, 4);
|
var writer = std.Io.Writer.Allocating.init(std.testing.allocator);
|
||||||
defer string.deinit(std.testing.allocator);
|
defer writer.deinit();
|
||||||
|
|
||||||
const writer = string.writer(std.testing.allocator);
|
|
||||||
for (cells) |cell| {
|
for (cells) |cell| {
|
||||||
try cell.value(writer);
|
try cell.value(&writer.writer);
|
||||||
}
|
}
|
||||||
try std.testing.expectEqualSlices(
|
try std.testing.expectEqualSlices(
|
||||||
u8,
|
u8,
|
||||||
"\x1b[38;5;10;48;5;8;59m╭\x1b[0m\x1b[39;49;59m─\x1b[0m\x1b[39;49;59m┄\x1b[0m\x1b[38;5;2;48;5;16;59;4m┘\x1b[0m",
|
"\x1b[38;5;10;48;5;8;59m╭\x1b[0m\x1b[39;49;59m─\x1b[0m\x1b[39;49;59m┄\x1b[0m\x1b[38;5;2;48;5;16;59;4m┘\x1b[0m",
|
||||||
string.items,
|
writer.writer.buffer[0..writer.writer.end],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,22 +20,21 @@ pub const Color = enum(u8) {
|
|||||||
|
|
||||||
// TODO might be useful to use the std.ascii stuff!
|
// TODO might be useful to use the std.ascii stuff!
|
||||||
|
|
||||||
pub inline fn write(this: Color, writer: anytype, comptime coloring: enum { fg, bg, ul }) !void {
|
pub inline fn write(this: Color, writer: *std.Io.Writer, comptime coloring: enum { fg, bg, ul }) !void {
|
||||||
if (this == .default) {
|
if (this == .default) {
|
||||||
switch (coloring) {
|
switch (coloring) {
|
||||||
.fg => try format(writer, "39", .{}),
|
.fg => try writer.printAscii("39", .{}),
|
||||||
.bg => try format(writer, "49", .{}),
|
.bg => try writer.printAscii("49", .{}),
|
||||||
.ul => try format(writer, "59", .{}),
|
.ul => try writer.printAscii("59", .{}),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (coloring) {
|
switch (coloring) {
|
||||||
.fg => try format(writer, "38;5;{d}", .{@intFromEnum(this)}),
|
.fg => try writer.print("38;5;{d}", .{@intFromEnum(this)}),
|
||||||
.bg => try format(writer, "48;5;{d}", .{@intFromEnum(this)}),
|
.bg => try writer.print("48;5;{d}", .{@intFromEnum(this)}),
|
||||||
.ul => try format(writer, "58;5;{d}", .{@intFromEnum(this)}),
|
.ul => try writer.print("58;5;{d}", .{@intFromEnum(this)}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const format = std.fmt.format;
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ pub const Buffered = struct {
|
|||||||
try terminal.hideCursor();
|
try terminal.hideCursor();
|
||||||
// TODO measure timings of rendered frames?
|
// TODO measure timings of rendered frames?
|
||||||
var cursor_position: ?Point = null;
|
var cursor_position: ?Point = null;
|
||||||
const writer = terminal.writer();
|
var writer = terminal.writer();
|
||||||
const s = this.screen;
|
const s = this.screen;
|
||||||
const vs = this.virtual_screen;
|
const vs = this.virtual_screen;
|
||||||
for (0..this.size.y) |row| {
|
for (0..this.size.y) |row| {
|
||||||
@@ -110,7 +110,7 @@ pub const Buffered = struct {
|
|||||||
|
|
||||||
// render differences found in virtual screen
|
// render differences found in virtual screen
|
||||||
try terminal.setCursorPosition(.{ .y = @truncate(row), .x = @truncate(col) });
|
try terminal.setCursorPosition(.{ .y = @truncate(row), .x = @truncate(col) });
|
||||||
try cvs.value(writer);
|
try cvs.value(&writer);
|
||||||
// update screen to be the virtual screen for the next frame
|
// update screen to be the virtual screen for the next frame
|
||||||
s[idx] = vs[idx];
|
s[idx] = vs[idx];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,27 +42,27 @@ pub fn eql(this: Style, other: Style) bool {
|
|||||||
|
|
||||||
// TODO might be useful to use the std.ascii stuff!
|
// TODO might be useful to use the std.ascii stuff!
|
||||||
|
|
||||||
pub fn value(this: Style, writer: anytype, cp: u21) !void {
|
pub fn value(this: Style, writer: *std.Io.Writer, cp: u21) !void {
|
||||||
var buffer: [4]u8 = undefined;
|
var buffer: [4]u8 = undefined;
|
||||||
const bytes = try unicode.utf8Encode(cp, &buffer);
|
const bytes = try unicode.utf8Encode(cp, &buffer);
|
||||||
assert(bytes > 0);
|
assert(bytes > 0);
|
||||||
// build ansi sequence for 256 colors ...
|
// build ansi sequence for 256 colors ...
|
||||||
// foreground
|
// foreground
|
||||||
try format(writer, "\x1b[", .{});
|
try writer.printAscii("\x1b[", .{});
|
||||||
try this.fg.write(writer, .fg);
|
try this.fg.write(writer, .fg);
|
||||||
// background
|
// background
|
||||||
try format(writer, ";", .{});
|
try writer.printAsciiChar(';', .{});
|
||||||
try this.bg.write(writer, .bg);
|
try this.bg.write(writer, .bg);
|
||||||
// underline
|
// underline
|
||||||
// FIX assert that if the underline property is set that the ul style and the attribute for underlining is available
|
// FIX assert that if the underline property is set that the ul style and the attribute for underlining is available
|
||||||
try format(writer, ";", .{});
|
try writer.printAsciiChar(';', .{});
|
||||||
try this.ul.write(writer, .ul);
|
try this.ul.write(writer, .ul);
|
||||||
// append styles (aka attributes like bold, italic, strikethrough, etc.)
|
// append styles (aka attributes like bold, italic, strikethrough, etc.)
|
||||||
for (this.emphasis) |attribute| try format(writer, ";{d}", .{@intFromEnum(attribute)});
|
for (this.emphasis) |attribute| try writer.print(";{d}", .{@intFromEnum(attribute)});
|
||||||
try format(writer, "m", .{});
|
try writer.printAsciiChar('m', .{});
|
||||||
// content
|
// content
|
||||||
try format(writer, "{s}", .{buffer[0..bytes]});
|
try writer.printAscii(buffer[0..bytes], .{});
|
||||||
try format(writer, "\x1b[0m", .{});
|
try writer.printAscii("\x1b[0m", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO implement helper functions for terminal capabilities:
|
// TODO implement helper functions for terminal capabilities:
|
||||||
@@ -73,6 +73,5 @@ const std = @import("std");
|
|||||||
const unicode = std.unicode;
|
const unicode = std.unicode;
|
||||||
const meta = std.meta;
|
const meta = std.meta;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const format = std.fmt.format;
|
|
||||||
const Color = @import("color.zig").Color;
|
const Color = @import("color.zig").Color;
|
||||||
const Style = @This();
|
const Style = @This();
|
||||||
|
|||||||
@@ -62,17 +62,24 @@ pub fn write(buf: []const u8) !usize {
|
|||||||
return try posix.write(posix.STDIN_FILENO, buf);
|
return try posix.write(posix.STDIN_FILENO, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contextWrite(context: *const anyopaque, data: []const u8) anyerror!usize {
|
fn drainFn(w: *std.Io.Writer, data: []const []const u8, splat: usize) error{WriteFailed}!usize {
|
||||||
_ = context;
|
_ = w;
|
||||||
return try posix.write(posix.STDOUT_FILENO, data);
|
if (data.len == 0 or splat == 0) return 0;
|
||||||
|
var len: usize = 0;
|
||||||
|
|
||||||
|
for (data) |bytes| len += posix.write(posix.STDOUT_FILENO, bytes) catch return error.WriteFailed;
|
||||||
|
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Writer = std.io.AnyWriter;
|
// TODO I now need to add that much, for just the one function above?
|
||||||
|
pub fn writer() std.Io.Writer {
|
||||||
pub fn writer() Writer {
|
|
||||||
return .{
|
return .{
|
||||||
.context = &.{},
|
.vtable = &.{
|
||||||
.writeFn = contextWrite,
|
.drain = drainFn,
|
||||||
|
.flush = std.Io.Writer.noopFlush,
|
||||||
|
},
|
||||||
|
.buffer = &.{},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,6 +238,7 @@ const log = std.log.scoped(.terminal);
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const posix = std.posix;
|
const posix = std.posix;
|
||||||
|
const assert = std.debug.assert;
|
||||||
const ctlseqs = @import("ctlseqs.zig");
|
const ctlseqs = @import("ctlseqs.zig");
|
||||||
const input = @import("input.zig");
|
const input = @import("input.zig");
|
||||||
const Key = input.Key;
|
const Key = input.Key;
|
||||||
|
|||||||
@@ -167,10 +167,10 @@ pub fn expectEqualCells(origin: Point, size: Point, expected: []const Cell, actu
|
|||||||
var actual_cps = try std.ArrayList(Cell).initCapacity(allocator, size.x);
|
var actual_cps = try std.ArrayList(Cell).initCapacity(allocator, size.x);
|
||||||
defer actual_cps.deinit(allocator);
|
defer actual_cps.deinit(allocator);
|
||||||
|
|
||||||
var output = try std.ArrayList(u8).initCapacity(allocator, expected_cps.capacity * actual_cps.capacity + 5 * size.y);
|
var allocating_writer = std.Io.Writer.Allocating.init(allocator);
|
||||||
defer output.deinit(allocator);
|
defer allocating_writer.deinit();
|
||||||
|
|
||||||
const writer = output.writer(allocator);
|
var writer = &allocating_writer.writer;
|
||||||
var differ = false;
|
var differ = false;
|
||||||
|
|
||||||
const expected_centered = try center(allocator, "Expected Screen", size.x, " ");
|
const expected_centered = try center(allocator, "Expected Screen", size.x, " ");
|
||||||
@@ -212,7 +212,7 @@ pub fn expectEqualCells(origin: Point, size: Point, expected: []const Cell, actu
|
|||||||
var stdout_buffer: [1024]u8 = undefined;
|
var stdout_buffer: [1024]u8 = undefined;
|
||||||
var stdout = std.fs.File.stdout().writer(&stdout_buffer);
|
var stdout = std.fs.File.stdout().writer(&stdout_buffer);
|
||||||
const stdout_writer = &stdout.interface;
|
const stdout_writer = &stdout.interface;
|
||||||
try stdout_writer.writeAll(output.items);
|
try stdout_writer.writeAll(writer.buffer[0..writer.end]);
|
||||||
try stdout_writer.flush();
|
try stdout_writer.flush();
|
||||||
return error.TestExpectEqualCells;
|
return error.TestExpectEqualCells;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user