Add physical keyboard parity aliases
This commit is contained in:
+131
@@ -928,6 +928,12 @@ pub const Client = struct {
|
||||
if (std.mem.eql(u8, key_name, "escape")) return self.handleInput("\x1b");
|
||||
if (std.mem.eql(u8, key_name, "left")) return self.handleInput("\x1b[D");
|
||||
if (std.mem.eql(u8, key_name, "right")) return self.handleInput("\x1b[C");
|
||||
if (std.mem.eql(u8, key_name, "up")) return self.handleInput("\x1b[A");
|
||||
if (std.mem.eql(u8, key_name, "down")) return self.handleInput("\x1b[B");
|
||||
if (std.mem.eql(u8, key_name, "home")) return self.handleInput("\x1b[H");
|
||||
if (std.mem.eql(u8, key_name, "end")) return self.handleInput("\x1b[F");
|
||||
if (std.mem.eql(u8, key_name, "page_up")) return self.handleInput("\x1b[5~");
|
||||
if (std.mem.eql(u8, key_name, "page_down")) return self.handleInput("\x1b[6~");
|
||||
if (key_name.len == 1) return self.handleInput(key_name);
|
||||
return Error.UnknownTraceEvent;
|
||||
}
|
||||
@@ -1021,6 +1027,7 @@ pub const Client = struct {
|
||||
if (std.mem.eql(u8, text, "U")) return self.redoEdit();
|
||||
if (std.mem.eql(u8, text, "0")) return self.applyProtocol("command move_line_start");
|
||||
if (std.mem.eql(u8, text, "$")) return self.applyProtocol("command move_line_end");
|
||||
if (std.mem.eql(u8, text, "%")) return self.jumpToMatch(null);
|
||||
if (std.mem.eql(u8, text, "m")) return self.openPrefix(.match);
|
||||
if (std.mem.eql(u8, text, "g")) return self.openPrefix(.go);
|
||||
if (std.mem.eql(u8, text, "j")) return self.repeatProtocol("command move_down", self.takeRepeat());
|
||||
@@ -1042,6 +1049,10 @@ pub const Client = struct {
|
||||
.arrow_right => try self.repeatProtocol("command move_right", self.takeRepeat()),
|
||||
.arrow_up => try self.repeatProtocol("command move_up", self.takeRepeat()),
|
||||
.arrow_down => try self.repeatProtocol("command move_down", self.takeRepeat()),
|
||||
.home => try self.applyProtocol("command move_line_start"),
|
||||
.end => try self.applyProtocol("command move_line_end"),
|
||||
.page_up => try self.repeatProtocol("command move_up", @max(@as(usize, 1), self.viewport.height - 2)),
|
||||
.page_down => try self.repeatProtocol("command move_down", @max(@as(usize, 1), self.viewport.height - 2)),
|
||||
else => self.unknownPrefixOrInput("normal"),
|
||||
},
|
||||
.unknown => self.unknownPrefixOrInput("normal"),
|
||||
@@ -1060,6 +1071,10 @@ pub const Client = struct {
|
||||
.backspace => try self.applyMutatingProtocol("command delete_backward"),
|
||||
.arrow_left => try self.applyProtocol("command move_left"),
|
||||
.arrow_right => try self.applyProtocol("command move_right"),
|
||||
.arrow_up => try self.applyProtocol("command move_up"),
|
||||
.arrow_down => try self.applyProtocol("command move_down"),
|
||||
.home => try self.applyProtocol("command move_line_start"),
|
||||
.end => try self.applyProtocol("command move_line_end"),
|
||||
else => {},
|
||||
},
|
||||
.unknown => {},
|
||||
@@ -1074,6 +1089,7 @@ pub const Client = struct {
|
||||
self.message = "normal";
|
||||
return;
|
||||
}
|
||||
if (std.mem.eql(u8, text, "%")) return self.jumpToMatch(null);
|
||||
if (std.mem.eql(u8, text, "m")) return self.openPrefix(.match);
|
||||
if (std.mem.eql(u8, text, "g")) return self.openPrefix(.go);
|
||||
if (text.len == 1) {
|
||||
@@ -1092,6 +1108,10 @@ pub const Client = struct {
|
||||
},
|
||||
.arrow_left => try self.applyProtocol("command move_left"),
|
||||
.arrow_right => try self.applyProtocol("command move_right"),
|
||||
.arrow_up => try self.applyProtocol("command move_up"),
|
||||
.arrow_down => try self.applyProtocol("command move_down"),
|
||||
.home => try self.applyProtocol("command move_line_start"),
|
||||
.end => try self.applyProtocol("command move_line_end"),
|
||||
else => {},
|
||||
},
|
||||
.unknown => self.unknownPrefixOrInput("select"),
|
||||
@@ -1110,6 +1130,8 @@ pub const Client = struct {
|
||||
.key => |key| switch (key) {
|
||||
.arrow_down => try self.applyProtocol("command list_down"),
|
||||
.arrow_up => try self.applyProtocol("command list_up"),
|
||||
.page_down => try self.repeatProtocol("command list_down", @max(@as(usize, 1), self.viewport.height - 2)),
|
||||
.page_up => try self.repeatProtocol("command list_up", @max(@as(usize, 1), self.viewport.height - 2)),
|
||||
.enter => try self.openActivePanelItem(),
|
||||
.escape => try self.closeActivePanel(),
|
||||
else => {},
|
||||
@@ -4581,3 +4603,112 @@ test "regular: provider edit rows parse source scope and replacement" {
|
||||
defer std.testing.allocator.free(action_row);
|
||||
try std.testing.expectEqualStrings("zls", try lsp_mod.providerFromActionPanelRow(action_row));
|
||||
}
|
||||
|
||||
test "regular: physical arrows home end page and escape match editor movement" {
|
||||
var client = try Client.init(std.testing.allocator, .{ .width = 64, .height = 5 });
|
||||
defer client.deinit();
|
||||
try client.handleTraceLine("open one\ntwo\nthree\nfour\nfive");
|
||||
|
||||
var snap = try client.session.snapshot();
|
||||
const start = snap.cursor_byte;
|
||||
try client.handleTraceLine("key page_down");
|
||||
snap = try client.session.snapshot();
|
||||
try std.testing.expect(snap.cursor_byte > start);
|
||||
|
||||
try client.handleTraceLine("key home");
|
||||
snap = try client.session.snapshot();
|
||||
const line_start = snap.cursor_byte;
|
||||
try client.handleTraceLine("key end");
|
||||
snap = try client.session.snapshot();
|
||||
try std.testing.expect(snap.cursor_byte >= line_start);
|
||||
|
||||
try client.handleTraceLine("key page_up");
|
||||
snap = try client.session.snapshot();
|
||||
try std.testing.expect(snap.cursor_byte <= line_start);
|
||||
|
||||
try client.handleInput("i");
|
||||
try client.handleInput("x");
|
||||
try client.handleTraceLine("key escape");
|
||||
try client.handleInput("u");
|
||||
snap = try client.session.snapshot();
|
||||
try std.testing.expect(std.mem.indexOf(u8, snap.bytes, "onxe") == null);
|
||||
}
|
||||
|
||||
test "regular: physical digit count matches repeated arrow movement" {
|
||||
var physical = try Client.init(std.testing.allocator, .{ .width = 64, .height = 6 });
|
||||
defer physical.deinit();
|
||||
try physical.handleTraceLine("open a\nb\nc\nd");
|
||||
try physical.handleInput("3");
|
||||
try physical.handleTraceLine("key down");
|
||||
const physical_snap = try physical.session.snapshot();
|
||||
|
||||
var repeated = try Client.init(std.testing.allocator, .{ .width = 64, .height = 6 });
|
||||
defer repeated.deinit();
|
||||
try repeated.handleTraceLine("open a\nb\nc\nd");
|
||||
try repeated.handleTraceLine("key down");
|
||||
try repeated.handleTraceLine("key down");
|
||||
try repeated.handleTraceLine("key down");
|
||||
const repeated_snap = try repeated.session.snapshot();
|
||||
try std.testing.expectEqual(repeated_snap.cursor_byte, physical_snap.cursor_byte);
|
||||
}
|
||||
|
||||
test "regular: physical percent and mobile match rail jump to same pair" {
|
||||
var physical = try Client.init(std.testing.allocator, .{ .width = 64, .height = 6 });
|
||||
defer physical.deinit();
|
||||
try physical.handleTraceLine("open (abc)");
|
||||
try physical.handleInput("%");
|
||||
var snap = try physical.session.snapshot();
|
||||
try std.testing.expectEqual(@as(usize, 4), snap.cursor_byte);
|
||||
|
||||
var mobile = try Client.init(std.testing.allocator, .{ .width = 64, .height = 6 });
|
||||
defer mobile.deinit();
|
||||
try mobile.handleTraceLine("open (abc)");
|
||||
try mobile.handleInput("m");
|
||||
try mobile.handleInput("m");
|
||||
snap = try mobile.session.snapshot();
|
||||
try std.testing.expectEqual(@as(usize, 4), snap.cursor_byte);
|
||||
}
|
||||
|
||||
test "regular: insert/select modes accept arrows while Space n remains mobile escape" {
|
||||
var client = try Client.init(std.testing.allocator, .{ .width = 64, .height = 6 });
|
||||
defer client.deinit();
|
||||
try client.handleTraceLine("open ab\ncd");
|
||||
try client.handleInput("i");
|
||||
try client.handleTraceLine("key end");
|
||||
try client.handleInput("X");
|
||||
try client.handleInput(" ");
|
||||
try client.handleInput("n");
|
||||
var snap = try client.session.snapshot();
|
||||
try std.testing.expectEqualStrings("abX\ncd", snap.bytes);
|
||||
|
||||
try client.handleInput("s");
|
||||
try client.handleTraceLine("key up");
|
||||
try client.handleTraceLine("key home");
|
||||
try client.handleInput("n");
|
||||
snap = try client.session.snapshot();
|
||||
try std.testing.expect(snap.selection != null or snap.cursor_byte == 0);
|
||||
}
|
||||
|
||||
test "regular: panels accept physical page keys and enter without breaking arrows" {
|
||||
var client = try Client.init(std.testing.allocator, .{ .width = 64, .height = 4 });
|
||||
defer client.deinit();
|
||||
try client.handleTraceLine("list_open files a.zig|b.zig|c.zig|d.zig|e.zig");
|
||||
try client.handleTraceLine("key page_down");
|
||||
const after_down = try client.session.activeListItem();
|
||||
try std.testing.expect(!std.mem.eql(u8, after_down, "a.zig"));
|
||||
|
||||
try client.handleTraceLine("key up");
|
||||
const after_up = try client.session.activeListItem();
|
||||
try std.testing.expect(!std.mem.eql(u8, after_down, after_up));
|
||||
}
|
||||
|
||||
test "adversarial: unknown physical key names stay rejected and leader help stays narrow" {
|
||||
var client = try Client.init(std.testing.allocator, .{ .width = 72, .height = 5 });
|
||||
defer client.deinit();
|
||||
try std.testing.expectError(Error.UnknownTraceEvent, client.handleTraceLine("key f1"));
|
||||
try client.handleInput(" ");
|
||||
try std.testing.expect(std.mem.indexOf(u8, client.leader.status(), "digits/%/Esc ok") != null);
|
||||
const frame = try client.render(std.testing.allocator);
|
||||
defer std.testing.allocator.free(frame);
|
||||
try assertLinesFit(frame, 72);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user