Add visible terminal control debug helpers
This commit is contained in:
@@ -17,6 +17,7 @@ const session = @import("session.zig");
|
|||||||
const socket = @import("socket.zig");
|
const socket = @import("socket.zig");
|
||||||
const symbol = @import("symbol.zig");
|
const symbol = @import("symbol.zig");
|
||||||
const syntax = @import("syntax.zig");
|
const syntax = @import("syntax.zig");
|
||||||
|
const terminal_debug = @import("terminal_debug.zig");
|
||||||
const tui = @import("tui.zig");
|
const tui = @import("tui.zig");
|
||||||
|
|
||||||
pub const version = "0.1.0-dev";
|
pub const version = "0.1.0-dev";
|
||||||
@@ -600,6 +601,10 @@ test "regular: local editor client exposes save and dirty quit guards" {
|
|||||||
try std.testing.expect(!client.requestedQuit());
|
try std.testing.expect(!client.requestedQuit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "terminal debug helpers are included in main test root" {
|
||||||
|
_ = terminal_debug;
|
||||||
|
}
|
||||||
|
|
||||||
test "regular: raw terminal output converts newline to carriage-return newline" {
|
test "regular: raw terminal output converts newline to carriage-return newline" {
|
||||||
const converted = try terminalCrlfAlloc(std.testing.allocator, "a\nb\n");
|
const converted = try terminalCrlfAlloc(std.testing.allocator, "a\nb\n");
|
||||||
defer std.testing.allocator.free(converted);
|
defer std.testing.allocator.free(converted);
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
/// Materialize terminal control characters as visible glyphs for failure output.
|
||||||
|
/// This is test/debug support only: product rendering still writes real CR/LF/ESC.
|
||||||
|
pub fn visibleControlsAlloc(allocator: std.mem.Allocator, bytes: []const u8) ![]u8 {
|
||||||
|
var out = std.ArrayList(u8).empty;
|
||||||
|
errdefer out.deinit(allocator);
|
||||||
|
for (bytes) |byte| switch (byte) {
|
||||||
|
'\r' => try out.appendSlice(allocator, "␍"),
|
||||||
|
'\n' => try out.appendSlice(allocator, "␊\n"),
|
||||||
|
0x1b => try out.appendSlice(allocator, "␛"),
|
||||||
|
'\t' => try out.appendSlice(allocator, "⇥"),
|
||||||
|
else => if (byte < 0x20) {
|
||||||
|
try out.appendSlice(allocator, "␀");
|
||||||
|
} else try out.append(allocator, byte),
|
||||||
|
};
|
||||||
|
return out.toOwnedSlice(allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hasBareLf(bytes: []const u8) bool {
|
||||||
|
for (bytes, 0..) |byte, i| {
|
||||||
|
if (byte == '\n' and (i == 0 or bytes[i - 1] != '\r')) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "regular: visible terminal controls expose newline and escape bytes" {
|
||||||
|
const debug = try visibleControlsAlloc(std.testing.allocator, "a\nb\r\n\x1b[31m");
|
||||||
|
defer std.testing.allocator.free(debug);
|
||||||
|
try std.testing.expectEqualStrings("a␊\nb␍␊\n␛[31m", debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "adversarial: bare LF detector catches raw-mode skew risk" {
|
||||||
|
try std.testing.expect(hasBareLf("a\nb"));
|
||||||
|
try std.testing.expect(!hasBareLf("a\r\nb"));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user