fix: correctly read inputs from *stdin* when not using *raw mode*
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 1m6s

This commit is contained in:
2026-01-23 12:44:48 +01:00
parent 4441f1b933
commit eb36c7c410

View File

@@ -443,43 +443,49 @@ pub fn App(comptime M: type, comptime E: type) type {
}, },
} }
} else { } else {
const b = buf[0]; if (this.config.rawMode) {
const key: Key = switch (b) { const b = buf[0];
0x00 => .{ .cp = '@', .mod = .{ .ctrl = true } }, const key: Key = switch (b) {
0x08 => .{ .cp = input.Backspace }, 0x00 => .{ .cp = '@', .mod = .{ .ctrl = true } },
0x09 => .{ .cp = input.Tab }, 0x08 => .{ .cp = input.Backspace },
0x0a => .{ .cp = 'j', .mod = .{ .ctrl = true } }, 0x09 => .{ .cp = input.Tab },
0x0d => .{ .cp = input.Enter }, 0x0a => .{ .cp = 'j', .mod = .{ .ctrl = true } },
0x01...0x07, 0x0b...0x0c, 0x0e...0x1a => .{ .cp = b + 0x60, .mod = .{ .ctrl = true } }, 0x0d => .{ .cp = input.Enter },
0x1b => escape: { 0x01...0x07, 0x0b...0x0c, 0x0e...0x1a => .{ .cp = b + 0x60, .mod = .{ .ctrl = true } },
assert(read_bytes == 1); 0x1b => escape: {
break :escape .{ .cp = input.Escape }; assert(read_bytes == 1);
}, break :escape .{ .cp = input.Escape };
0x7f => .{ .cp = input.Backspace }, },
else => { 0x7f => .{ .cp = input.Backspace },
var len = read_bytes; else => {
while (!std.unicode.utf8ValidateSlice(buf[0..len])) len -= 1; var len = read_bytes;
remaining_bytes = read_bytes - len; while (!std.unicode.utf8ValidateSlice(buf[0..len])) len -= 1;
remaining_bytes = read_bytes - len;
if (this.config.rawMode) {
var iter: std.unicode.Utf8Iterator = .{ .bytes = buf[0..len], .i = 0 }; var iter: std.unicode.Utf8Iterator = .{ .bytes = buf[0..len], .i = 0 };
while (iter.nextCodepoint()) |cp| this.postEvent(.{ .key = .{ .cp = cp } }); while (iter.nextCodepoint()) |cp| this.postEvent(.{ .key = .{ .cp = cp } });
} else try lines.appendSlice(this.gpa, buf[0..len]); if (remaining_bytes > 0) {
@memmove(buf[0..remaining_bytes], buf[len .. len + remaining_bytes]);
if (remaining_bytes > 0) {
@memmove(buf[0..remaining_bytes], buf[len .. len + remaining_bytes]);
} else {
if (read_bytes != 512 and buf[len - 1] == '\n') this.postEvent(.{ .line = try lines.toOwnedSlice(this.gpa) });
// NOTE line did not end with `\n` but with EOF, meaning the user canceled
if (read_bytes != 512 and buf[len - 1] != '\n') {
lines.clearRetainingCapacity();
this.postEvent(.cancel);
} }
continue; // this switch block does not return a `Key` we continue with loop
},
};
this.postEvent(.{ .key = key });
} else {
var len = read_bytes;
while (!std.unicode.utf8ValidateSlice(buf[0..len])) len -= 1;
remaining_bytes = read_bytes - len;
try lines.appendSlice(this.gpa, buf[0..len]);
if (remaining_bytes > 0) {
@memmove(buf[0..remaining_bytes], buf[len .. len + remaining_bytes]);
} else {
if (read_bytes != 512 and buf[len - 1] == '\n') this.postEvent(.{ .line = try lines.toOwnedSlice(this.gpa) });
// NOTE line did not end with `\n` but with EOF, meaning the user canceled
if (read_bytes != 512 and buf[len - 1] != '\n') {
lines.clearRetainingCapacity();
this.postEvent(.cancel);
} }
continue; // this switch block does not return a `Key` we continue with loop }
}, }
};
this.postEvent(.{ .key = key });
} }
continue; continue;
}; };