handle upper case in input buffers
This commit is contained in:
parent
8986537d93
commit
8b85dcb9ea
1 changed files with 97 additions and 8 deletions
|
|
@ -80,12 +80,9 @@ pub fn handleKey(buf: []u8, len: *usize, key: vaxis.Key) Result {
|
|||
len.* = 0;
|
||||
return .edited;
|
||||
}
|
||||
// Accept printable ASCII (letters, digits, common punctuation).
|
||||
if (key.codepoint < std.math.maxInt(u7) and std.ascii.isPrint(@intCast(key.codepoint)) and len.* < buf.len) {
|
||||
buf[len.*] = @intCast(key.codepoint);
|
||||
len.* += 1;
|
||||
return .edited;
|
||||
}
|
||||
// Printable input. Prefer the terminal-resolved text so Shift /
|
||||
// Caps Lock produce the right case (see `appendPrintable`).
|
||||
if (appendPrintable(buf, len, key)) return .edited;
|
||||
return .ignored;
|
||||
}
|
||||
|
||||
|
|
@ -155,12 +152,45 @@ pub fn handleKeyMulti(buf: []u8, len: *usize, key: vaxis.Key) MultiResult {
|
|||
len.* = 0;
|
||||
return .edited;
|
||||
}
|
||||
if (appendPrintable(buf, len, key)) return .edited;
|
||||
return .ignored;
|
||||
}
|
||||
|
||||
/// Append the character a key produced to `buf`, returning true on
|
||||
/// success. Callers handle the special keys (Esc, Enter, Backspace,
|
||||
/// Ctrl+*) before this runs, so anything reaching here is ordinary
|
||||
/// text input.
|
||||
///
|
||||
/// We prefer `key.text` - the terminal's resolved text for the
|
||||
/// event - over the raw codepoint. Under the Kitty keyboard protocol
|
||||
/// (which vaxis turns on), a Shift+a press reports `codepoint = 'a'`
|
||||
/// (the base-layout key) with `text = "A"`; keying off the codepoint
|
||||
/// alone silently downcases everything and turns shifted symbols
|
||||
/// (`!@#`) back into their digits. Only single printable-ASCII text
|
||||
/// bytes are taken: these buffers are ASCII (ticker symbols, ack-note
|
||||
/// reasoning), so a stray multibyte grapheme or control sequence
|
||||
/// shouldn't land in them. When no text is reported (legacy terminal,
|
||||
/// no Kitty protocol) we fall back to the codepoint, which already
|
||||
/// carries the shifted value in that mode.
|
||||
fn appendPrintable(buf: []u8, len: *usize, key: vaxis.Key) bool {
|
||||
if (key.text) |text| {
|
||||
if (text.len == 1 and std.ascii.isPrint(text[0]) and len.* < buf.len) {
|
||||
buf[len.*] = text[0];
|
||||
len.* += 1;
|
||||
return true;
|
||||
}
|
||||
// Text was reported but isn't a single printable ASCII byte
|
||||
// (multibyte grapheme, control char, or the buffer is full).
|
||||
// Do NOT fall through to the codepoint path: that would
|
||||
// re-append a downcased/duplicate byte.
|
||||
return false;
|
||||
}
|
||||
if (key.codepoint < std.math.maxInt(u7) and std.ascii.isPrint(@intCast(key.codepoint)) and len.* < buf.len) {
|
||||
buf[len.*] = @intCast(key.codepoint);
|
||||
len.* += 1;
|
||||
return .edited;
|
||||
return true;
|
||||
}
|
||||
return .ignored;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ── Tests ─────────────────────────────────────────────────────
|
||||
|
|
@ -194,6 +224,49 @@ test "handleKey: printable ASCII appends and increments len" {
|
|||
try testing.expectEqual(@as(u8, 'x'), buf[0]);
|
||||
}
|
||||
|
||||
test "handleKey: Shift+letter appends the uppercase text, not the base codepoint" {
|
||||
// Kitty keyboard protocol reports the base-layout key in
|
||||
// `codepoint` and the resolved character in `text`. Shift+a must
|
||||
// land 'A', not 'a'.
|
||||
var buf: [16]u8 = undefined;
|
||||
var len: usize = 0;
|
||||
const result = handleKey(&buf, &len, .{ .codepoint = 'a', .text = "A", .mods = .{ .shift = true } });
|
||||
try testing.expectEqual(Result.edited, result);
|
||||
try testing.expectEqual(@as(usize, 1), len);
|
||||
try testing.expectEqual(@as(u8, 'A'), buf[0]);
|
||||
}
|
||||
|
||||
test "handleKey: shifted symbol appends the symbol, not the digit" {
|
||||
// Shift+1 => '!' : codepoint stays '1', text is "!".
|
||||
var buf: [16]u8 = undefined;
|
||||
var len: usize = 0;
|
||||
const result = handleKey(&buf, &len, .{ .codepoint = '1', .text = "!", .mods = .{ .shift = true } });
|
||||
try testing.expectEqual(Result.edited, result);
|
||||
try testing.expectEqual(@as(u8, '!'), buf[0]);
|
||||
}
|
||||
|
||||
test "handleKey: legacy terminal (no text) falls back to the codepoint" {
|
||||
// Without the Kitty protocol, vaxis reports the shifted value
|
||||
// directly in `codepoint` and leaves `text` null.
|
||||
var buf: [16]u8 = undefined;
|
||||
var len: usize = 0;
|
||||
const result = handleKey(&buf, &len, .{ .codepoint = 'A' });
|
||||
try testing.expectEqual(Result.edited, result);
|
||||
try testing.expectEqual(@as(u8, 'A'), buf[0]);
|
||||
}
|
||||
|
||||
test "handleKey: multibyte/control text is not appended" {
|
||||
// A non-ASCII grapheme or control sequence in `text` must not
|
||||
// corrupt the ASCII buffer, and must not fall through to the
|
||||
// codepoint path.
|
||||
var buf: [16]u8 = undefined;
|
||||
var len: usize = 0;
|
||||
try testing.expectEqual(Result.ignored, handleKey(&buf, &len, .{ .codepoint = 0x2014, .text = "\u{2014}" }));
|
||||
try testing.expectEqual(@as(usize, 0), len);
|
||||
try testing.expectEqual(Result.ignored, handleKey(&buf, &len, .{ .codepoint = vaxis.Key.tab, .text = "\t" }));
|
||||
try testing.expectEqual(@as(usize, 0), len);
|
||||
}
|
||||
|
||||
test "handleKey: backspace decrements len" {
|
||||
var buf: [16]u8 = undefined;
|
||||
var len: usize = 3;
|
||||
|
|
@ -296,6 +369,22 @@ test "handleKeyMulti: printable ASCII appends" {
|
|||
try testing.expectEqual(@as(u8, 'x'), buf[0]);
|
||||
}
|
||||
|
||||
test "handleKeyMulti: Shift+letter appends uppercase text (the ack-note bug)" {
|
||||
var buf: [64]u8 = undefined;
|
||||
var len: usize = 0;
|
||||
const result = handleKeyMulti(&buf, &len, .{ .codepoint = 'a', .text = "A", .mods = .{ .shift = true } });
|
||||
try testing.expectEqual(MultiResult.edited, result);
|
||||
try testing.expectEqual(@as(u8, 'A'), buf[0]);
|
||||
}
|
||||
|
||||
test "handleKeyMulti: legacy terminal (no text) falls back to the codepoint" {
|
||||
var buf: [64]u8 = undefined;
|
||||
var len: usize = 0;
|
||||
const result = handleKeyMulti(&buf, &len, .{ .codepoint = 'Z' });
|
||||
try testing.expectEqual(MultiResult.edited, result);
|
||||
try testing.expectEqual(@as(u8, 'Z'), buf[0]);
|
||||
}
|
||||
|
||||
test "handleKeyMulti: backspace decrements len" {
|
||||
var buf: [64]u8 = undefined;
|
||||
var len: usize = 3;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue