Add document and half-page motions
This commit is contained in:
@@ -184,6 +184,8 @@ such as arrow keys, Home/End, PageUp/PageDown, Escape, or `%`.
|
|||||||
| `O` or `Space o` `a` | open line above and enter Insert |
|
| `O` or `Space o` `a` | open line above and enter Insert |
|
||||||
| `h` `j` `k` `l` | left/down/up/right where comfortable; arrows are aliases |
|
| `h` `j` `k` `l` | left/down/up/right where comfortable; arrows are aliases |
|
||||||
| `w` `b` `e` | word forward/back/end |
|
| `w` `b` `e` | word forward/back/end |
|
||||||
|
| `gg` `G` | document start / bottom line |
|
||||||
|
| `Ctrl-u` `Ctrl-d` | half-page up/down when the SSH client exposes Ctrl; `g u` / `g d` are mobile fallback aliases |
|
||||||
| `H` `L` | mobile-reachable line start/end aliases |
|
| `H` `L` | mobile-reachable line start/end aliases |
|
||||||
| `0` `^` `$` | attached/Vim-style line start/first-nonblank/end aliases; `Space g` `l` opens line targets |
|
| `0` `^` `$` | attached/Vim-style line start/first-nonblank/end aliases; `Space g` `l` opens line targets |
|
||||||
| `u` | undo |
|
| `u` | undo |
|
||||||
|
|||||||
+2
-1
@@ -23,12 +23,13 @@ Rows are redgate TSV requirements: `ring<TAB>id<TAB>summary [tag]`.
|
|||||||
1 010 Select mode SHALL extend the active range with motions and keep semantic object selection behind an explicit object rail. [mobile]
|
1 010 Select mode SHALL extend the active range with motions and keep semantic object selection behind an explicit object rail. [mobile]
|
||||||
1 011 Vertical line motions SHALL preserve a preferred cursor cell across ragged lines, clamped to each target line until horizontal/editing motion resets the preference. [mobile]
|
1 011 Vertical line motions SHALL preserve a preferred cursor cell across ragged lines, clamped to each target line until horizontal/editing motion resets the preference. [mobile]
|
||||||
1 012 Line selections SHALL be able to include the line's newline boundary so linewise edits can preserve Vim-like newline semantics. [mobile]
|
1 012 Line selections SHALL be able to include the line's newline boundary so linewise edits can preserve Vim-like newline semantics. [mobile]
|
||||||
|
1 013 Document start/end and half-page motions SHALL be reachable from Normal mode with Ctrl-capable SSH keys and documented mobile fallback aliases. [mobile]
|
||||||
|
|
||||||
## ui
|
## ui
|
||||||
|
|
||||||
0 001 Narrow terminals SHALL use transient panels instead of permanent desktop splits. [mobile]
|
0 001 Narrow terminals SHALL use transient panels instead of permanent desktop splits. [mobile]
|
||||||
1 002 Files, git, diagnostics, LSP, build, terminal, and Pi surfaces SHALL share one panel navigation model. [panels]
|
1 002 Files, git, diagnostics, LSP, build, terminal, and Pi surfaces SHALL share one panel navigation model. [panels]
|
||||||
0 003 When the cursor moves beyond the visible horizontal viewport, the editor SHALL scroll the line horizontally enough to keep the cursor cell visible. [mobile]
|
0 003 When the cursor moves beyond the visible horizontal or vertical viewport, the editor SHALL scroll enough to keep the cursor cell visible. [mobile]
|
||||||
|
|
||||||
## coding
|
## coding
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ pub const Key = enum {
|
|||||||
end,
|
end,
|
||||||
page_up,
|
page_up,
|
||||||
page_down,
|
page_down,
|
||||||
|
ctrl_u,
|
||||||
|
ctrl_d,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Event = union(enum) {
|
pub const Event = union(enum) {
|
||||||
@@ -90,6 +92,8 @@ pub fn normalize(raw: []const u8) Event {
|
|||||||
if (std.mem.eql(u8, raw, "\x1b[F") or std.mem.eql(u8, raw, "\x1b[4~") or std.mem.eql(u8, raw, "\x1b[8~")) return .{ .key = .end };
|
if (std.mem.eql(u8, raw, "\x1b[F") or std.mem.eql(u8, raw, "\x1b[4~") or std.mem.eql(u8, raw, "\x1b[8~")) return .{ .key = .end };
|
||||||
if (std.mem.eql(u8, raw, "\x1b[5~")) return .{ .key = .page_up };
|
if (std.mem.eql(u8, raw, "\x1b[5~")) return .{ .key = .page_up };
|
||||||
if (std.mem.eql(u8, raw, "\x1b[6~")) return .{ .key = .page_down };
|
if (std.mem.eql(u8, raw, "\x1b[6~")) return .{ .key = .page_down };
|
||||||
|
if (std.mem.eql(u8, raw, "\x15")) return .{ .key = .ctrl_u };
|
||||||
|
if (std.mem.eql(u8, raw, "\x04")) return .{ .key = .ctrl_d };
|
||||||
|
|
||||||
if (std.unicode.utf8ValidateSlice(raw) and isPrintableText(raw)) return .{ .text = raw };
|
if (std.unicode.utf8ValidateSlice(raw) and isPrintableText(raw)) return .{ .text = raw };
|
||||||
return .{ .unknown = raw };
|
return .{ .unknown = raw };
|
||||||
|
|||||||
+1
-1
@@ -162,7 +162,7 @@ pub fn classifyEvent(profile: *const Profile, event: input.Event) Classified {
|
|||||||
const kind: Kind = switch (event) {
|
const kind: Kind = switch (event) {
|
||||||
.key => |key| switch (key) {
|
.key => |key| switch (key) {
|
||||||
.space, .tab => .whitespace,
|
.space, .tab => .whitespace,
|
||||||
.enter, .backspace, .escape, .arrow_left, .arrow_right, .arrow_up, .arrow_down, .home, .end, .page_up, .page_down => .control,
|
.enter, .backspace, .escape, .arrow_left, .arrow_right, .arrow_up, .arrow_down, .home, .end, .page_up, .page_down, .ctrl_u, .ctrl_d => .control,
|
||||||
},
|
},
|
||||||
.text => |text| lookupFact(profile, text) orelse .unknown,
|
.text => |text| lookupFact(profile, text) orelse .unknown,
|
||||||
.unknown => .unknown,
|
.unknown => .unknown,
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ fn commandResponse(allocator: std.mem.Allocator, session: *session_mod.Session,
|
|||||||
if (std.mem.eql(u8, command, "move_word_end")) return dispatchAndRespond(allocator, session, .move_word_end);
|
if (std.mem.eql(u8, command, "move_word_end")) return dispatchAndRespond(allocator, session, .move_word_end);
|
||||||
if (std.mem.eql(u8, command, "move_line_start")) return dispatchAndRespond(allocator, session, .move_line_start);
|
if (std.mem.eql(u8, command, "move_line_start")) return dispatchAndRespond(allocator, session, .move_line_start);
|
||||||
if (std.mem.eql(u8, command, "move_line_end")) return dispatchAndRespond(allocator, session, .move_line_end);
|
if (std.mem.eql(u8, command, "move_line_end")) return dispatchAndRespond(allocator, session, .move_line_end);
|
||||||
|
if (std.mem.eql(u8, command, "move_document_start")) return dispatchAndRespond(allocator, session, .move_document_start);
|
||||||
|
if (std.mem.eql(u8, command, "move_document_end")) return dispatchAndRespond(allocator, session, .move_document_end);
|
||||||
if (std.mem.eql(u8, command, "delete_backward")) return dispatchAndRespond(allocator, session, .delete_backward);
|
if (std.mem.eql(u8, command, "delete_backward")) return dispatchAndRespond(allocator, session, .delete_backward);
|
||||||
if (std.mem.eql(u8, command, "delete_forward")) return dispatchAndRespond(allocator, session, .delete_forward);
|
if (std.mem.eql(u8, command, "delete_forward")) return dispatchAndRespond(allocator, session, .delete_forward);
|
||||||
if (std.mem.eql(u8, command, "delete_line")) return dispatchAndRespond(allocator, session, .delete_line);
|
if (std.mem.eql(u8, command, "delete_line")) return dispatchAndRespond(allocator, session, .delete_line);
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ pub const Command = union(enum) {
|
|||||||
replace_char: []const u8,
|
replace_char: []const u8,
|
||||||
move_line_start,
|
move_line_start,
|
||||||
move_line_end,
|
move_line_end,
|
||||||
|
move_document_start,
|
||||||
|
move_document_end,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Snapshot = struct {
|
pub const Snapshot = struct {
|
||||||
@@ -104,6 +106,8 @@ pub const Buffer = struct {
|
|||||||
.replace_char => |text| try self.replaceChar(text),
|
.replace_char => |text| try self.replaceChar(text),
|
||||||
.move_line_start => self.moveLineStart(),
|
.move_line_start => self.moveLineStart(),
|
||||||
.move_line_end => self.moveLineEnd(),
|
.move_line_end => self.moveLineEnd(),
|
||||||
|
.move_document_start => self.moveDocumentStart(),
|
||||||
|
.move_document_end => self.moveDocumentEnd(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +267,24 @@ pub const Buffer = struct {
|
|||||||
self.refreshCellResetPreferred();
|
self.refreshCellResetPreferred();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn moveDocumentStart(self: *Buffer) void {
|
||||||
|
self.cursor.byte = 0;
|
||||||
|
self.refreshCellResetPreferred();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn moveDocumentEnd(self: *Buffer) void {
|
||||||
|
if (self.bytes.items.len == 0) {
|
||||||
|
self.cursor.byte = 0;
|
||||||
|
self.refreshCellResetPreferred();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var at = self.bytes.items.len;
|
||||||
|
if (at > 0 and self.bytes.items[at - 1] == '\n') at -= 1;
|
||||||
|
while (at > 0 and self.bytes.items[at - 1] != '\n') at -= 1;
|
||||||
|
self.cursor.byte = at;
|
||||||
|
self.refreshCellResetPreferred();
|
||||||
|
}
|
||||||
|
|
||||||
const LineRange = struct { start: usize, end: usize };
|
const LineRange = struct { start: usize, end: usize };
|
||||||
|
|
||||||
fn currentLineRange(self: *const Buffer, include_newline: bool) LineRange {
|
fn currentLineRange(self: *const Buffer, include_newline: bool) LineRange {
|
||||||
@@ -757,3 +779,19 @@ test "regular: line object selection includes the newline byte" {
|
|||||||
const snap = try session.snapshot();
|
const snap = try session.snapshot();
|
||||||
try std.testing.expectEqualStrings("abc\n", snap.bytes[snap.selection.?.anchor..snap.selection.?.cursor]);
|
try std.testing.expectEqualStrings("abc\n", snap.bytes[snap.selection.?.anchor..snap.selection.?.cursor]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "regular: document motions jump to top and bottom line" {
|
||||||
|
var session = Session.init(std.testing.allocator);
|
||||||
|
defer session.deinit();
|
||||||
|
|
||||||
|
try session.openFixtureAt("one\ntwo\nthree\n", 4);
|
||||||
|
try session.dispatch(.move_document_end);
|
||||||
|
var snap = try session.snapshot();
|
||||||
|
try std.testing.expectEqual(@as(usize, 8), snap.cursor_byte);
|
||||||
|
try std.testing.expectEqual(@as(usize, 0), snap.cursor_cell);
|
||||||
|
|
||||||
|
try session.dispatch(.move_document_start);
|
||||||
|
snap = try session.snapshot();
|
||||||
|
try std.testing.expectEqual(@as(usize, 0), snap.cursor_byte);
|
||||||
|
try std.testing.expectEqual(@as(usize, 0), snap.cursor_cell);
|
||||||
|
}
|
||||||
|
|||||||
+42
@@ -324,11 +324,16 @@ pub const Client = struct {
|
|||||||
const gutter_digits = @max(@as(usize, 2), decimalDigits(total_lines));
|
const gutter_digits = @max(@as(usize, 2), decimalDigits(total_lines));
|
||||||
const gutter_width = @min(self.viewport.width, gutter_digits + 2);
|
const gutter_width = @min(self.viewport.width, gutter_digits + 2);
|
||||||
const content_width = if (self.viewport.width > gutter_width) self.viewport.width - gutter_width else 0;
|
const content_width = if (self.viewport.width > gutter_width) self.viewport.width - gutter_width else 0;
|
||||||
|
const first_visible_line = firstVisibleLineForCursor(cursor_line, max_body_lines);
|
||||||
var visible_line_index: usize = 0;
|
var visible_line_index: usize = 0;
|
||||||
var body_lines_used: usize = 0;
|
var body_lines_used: usize = 0;
|
||||||
var line_start_byte: usize = 0;
|
var line_start_byte: usize = 0;
|
||||||
var line_iter = std.mem.splitScalar(u8, snap.bytes, '\n');
|
var line_iter = std.mem.splitScalar(u8, snap.bytes, '\n');
|
||||||
while (line_iter.next()) |line| : (visible_line_index += 1) {
|
while (line_iter.next()) |line| : (visible_line_index += 1) {
|
||||||
|
if (visible_line_index < first_visible_line) {
|
||||||
|
line_start_byte += line.len + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (body_lines_used >= max_body_lines) break;
|
if (body_lines_used >= max_body_lines) break;
|
||||||
try appendEditorLine(
|
try appendEditorLine(
|
||||||
allocator,
|
allocator,
|
||||||
@@ -1076,6 +1081,7 @@ pub const Client = struct {
|
|||||||
if (std.mem.eql(u8, text, "L") or std.mem.eql(u8, text, "$")) return self.applyProtocol("command move_line_end");
|
if (std.mem.eql(u8, text, "L") or 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, "%")) return self.jumpToMatch(null);
|
||||||
if (std.mem.eql(u8, text, "m")) return self.openPrefix(.match);
|
if (std.mem.eql(u8, text, "m")) return self.openPrefix(.match);
|
||||||
|
if (std.mem.eql(u8, text, "G")) return self.applyProtocol("command move_document_end");
|
||||||
if (std.mem.eql(u8, text, "g")) return self.openPrefix(.go);
|
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());
|
if (std.mem.eql(u8, text, "j")) return self.repeatProtocol("command move_down", self.takeRepeat());
|
||||||
if (std.mem.eql(u8, text, "k")) return self.repeatProtocol("command move_up", self.takeRepeat());
|
if (std.mem.eql(u8, text, "k")) return self.repeatProtocol("command move_up", self.takeRepeat());
|
||||||
@@ -1100,6 +1106,8 @@ pub const Client = struct {
|
|||||||
.end => try self.applyProtocol("command move_line_end"),
|
.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_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)),
|
.page_down => try self.repeatProtocol("command move_down", @max(@as(usize, 1), self.viewport.height - 2)),
|
||||||
|
.ctrl_u => try self.halfPage(.up),
|
||||||
|
.ctrl_d => try self.halfPage(.down),
|
||||||
else => self.unknownPrefixOrInput("normal"),
|
else => self.unknownPrefixOrInput("normal"),
|
||||||
},
|
},
|
||||||
.unknown => self.unknownPrefixOrInput("normal"),
|
.unknown => self.unknownPrefixOrInput("normal"),
|
||||||
@@ -1810,6 +1818,10 @@ pub const Client = struct {
|
|||||||
|
|
||||||
fn applyGoRail(self: *Client, event: input.Event) !void {
|
fn applyGoRail(self: *Client, event: input.Event) !void {
|
||||||
const text = eventText(event) orelse return self.unknownPrefixOrInput("normal");
|
const text = eventText(event) orelse return self.unknownPrefixOrInput("normal");
|
||||||
|
if (std.mem.eql(u8, text, "g")) return self.applyProtocol("command move_document_start");
|
||||||
|
if (std.mem.eql(u8, text, "G")) return self.applyProtocol("command move_document_end");
|
||||||
|
if (std.mem.eql(u8, text, "u")) return self.halfPage(.up);
|
||||||
|
if (std.mem.eql(u8, text, "d")) return self.halfPage(.down);
|
||||||
if (std.mem.eql(u8, text, "a")) return self.moveParameter(.next);
|
if (std.mem.eql(u8, text, "a")) return self.moveParameter(.next);
|
||||||
if (std.mem.eql(u8, text, "A")) return self.moveParameter(.previous);
|
if (std.mem.eql(u8, text, "A")) return self.moveParameter(.previous);
|
||||||
if (std.mem.eql(u8, text, "e")) return self.gotoDiagnostic(.next);
|
if (std.mem.eql(u8, text, "e")) return self.gotoDiagnostic(.next);
|
||||||
@@ -2201,6 +2213,17 @@ pub const Client = struct {
|
|||||||
self.noteDocumentChanged();
|
self.noteDocumentChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PageDirection = enum { up, down };
|
||||||
|
|
||||||
|
fn halfPage(self: *Client, direction: PageDirection) !void {
|
||||||
|
const rows = @max(@as(usize, 1), (self.viewport.height - 1) / 2);
|
||||||
|
const command = switch (direction) {
|
||||||
|
.up => "command move_up",
|
||||||
|
.down => "command move_down",
|
||||||
|
};
|
||||||
|
try self.repeatProtocol(command, rows);
|
||||||
|
}
|
||||||
|
|
||||||
fn repeatProtocol(self: *Client, line: []const u8, repeat: usize) !void {
|
fn repeatProtocol(self: *Client, line: []const u8, repeat: usize) !void {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < repeat) : (i += 1) try self.applyProtocol(line);
|
while (i < repeat) : (i += 1) try self.applyProtocol(line);
|
||||||
@@ -2571,6 +2594,12 @@ fn countDocumentLines(bytes: []const u8) usize {
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn firstVisibleLineForCursor(cursor_line: usize, max_body_lines: usize) usize {
|
||||||
|
if (max_body_lines == 0) return cursor_line;
|
||||||
|
if (cursor_line < max_body_lines) return 0;
|
||||||
|
return cursor_line - max_body_lines + 1;
|
||||||
|
}
|
||||||
|
|
||||||
fn decimalDigits(value: usize) usize {
|
fn decimalDigits(value: usize) usize {
|
||||||
var digits: usize = 1;
|
var digits: usize = 1;
|
||||||
var n = value;
|
var n = value;
|
||||||
@@ -5143,3 +5172,16 @@ test "regular: insert Enter copies current line indent and Tab follows tab-inden
|
|||||||
snap = try tabs.session.snapshot();
|
snap = try tabs.session.snapshot();
|
||||||
try std.testing.expectEqualStrings("\titem x", snap.bytes);
|
try std.testing.expectEqualStrings("\titem x", snap.bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "regular: vertical viewport follows cursor line" {
|
||||||
|
var client = try Client.init(std.testing.allocator, .{ .width = 32, .height = 6 });
|
||||||
|
defer client.deinit();
|
||||||
|
|
||||||
|
try client.handleTraceLine("open l1\nl2\nl3\nl4\nl5\nl6\nl7\nl8\nl9\nl10\nl11\nl12");
|
||||||
|
try client.applyProtocol("command move_document_end");
|
||||||
|
const frame = try client.render(std.testing.allocator);
|
||||||
|
defer std.testing.allocator.free(frame);
|
||||||
|
|
||||||
|
try std.testing.expect(std.mem.indexOf(u8, frame, "12│") != null);
|
||||||
|
try std.testing.expect(std.mem.indexOf(u8, frame, " 1│") == null);
|
||||||
|
}
|
||||||
|
|||||||
@@ -448,6 +448,13 @@ def setup_long(tmp: Path) -> tuple[Path, str | None]:
|
|||||||
return target, "l1\nl2\nl3\nl4\nl5\nl6\nl7\nl8\n"
|
return target, "l1\nl2\nl3\nl4\nl5\nl6\nl7\nl8\n"
|
||||||
|
|
||||||
|
|
||||||
|
def setup_tall(tmp: Path) -> tuple[Path, str | None]:
|
||||||
|
target = tmp / "tall.txt"
|
||||||
|
text = "".join(f"l{i}\n" for i in range(1, 17))
|
||||||
|
target.write_text(text, encoding="utf-8")
|
||||||
|
return target, text
|
||||||
|
|
||||||
|
|
||||||
def setup_long_line(tmp: Path) -> tuple[Path, str | None]:
|
def setup_long_line(tmp: Path) -> tuple[Path, str | None]:
|
||||||
target = tmp / "wide.txt"
|
target = tmp / "wide.txt"
|
||||||
target.write_text("abcdefghijklmnopqrstuvwxyz0123456789\n", encoding="utf-8")
|
target.write_text("abcdefghijklmnopqrstuvwxyz0123456789\n", encoding="utf-8")
|
||||||
@@ -514,6 +521,7 @@ SCENARIOS = [
|
|||||||
Scenario("select-mode-motions", 56, 12, "short", "attached-keyboard", "select", "truecolor", "file", setup_short, (b"L", b"s", b"H", b"L", b"n", b" ", b"q"), "abcdef\n", ("attr:selection", "░", "mode:normal")),
|
Scenario("select-mode-motions", 56, 12, "short", "attached-keyboard", "select", "truecolor", "file", setup_short, (b"L", b"s", b"H", b"L", b"n", b" ", b"q"), "abcdef\n", ("attr:selection", "░", "mode:normal")),
|
||||||
Scenario("horizontal-cursor-scroll", 24, 8, "wide-line", "attached-keyboard", "horizontal-scroll", "truecolor", "file", setup_long_line, (b"L", b" ", b"q"), "abcdefghijklmnopqrstuvwxyz0123456789\n", ("0123456789", "☻", "mode:normal")),
|
Scenario("horizontal-cursor-scroll", 24, 8, "wide-line", "attached-keyboard", "horizontal-scroll", "truecolor", "file", setup_long_line, (b"L", b" ", b"q"), "abcdefghijklmnopqrstuvwxyz0123456789\n", ("0123456789", "☻", "mode:normal")),
|
||||||
Scenario("vertical-motion-preferred-column", 56, 12, "ragged", "attached-keyboard", "motion", "truecolor", "file", setup_ragged, (b"L", b"j", b"j", b"i", b"X", b"\x1b", b" ", b"w", b" ", b"q"), "abcdef\nxy\n123456X", ("1│", "3│", "☻", "mode:normal")),
|
Scenario("vertical-motion-preferred-column", 56, 12, "ragged", "attached-keyboard", "motion", "truecolor", "file", setup_ragged, (b"L", b"j", b"j", b"i", b"X", b"\x1b", b" ", b"w", b" ", b"q"), "abcdef\nxy\n123456X", ("1│", "3│", "☻", "mode:normal")),
|
||||||
|
Scenario("document-half-page-motions", 56, 10, "tall", "attached-keyboard", "motion", "truecolor", "file", setup_tall, (b"G", b"i", b"X", b"\x1b", b"g", b"g", b"\x04", b"i", b"Y", b"\x1b", b"G", b"g", b"u", b"i", b"Z", b"\x1b", b" ", b"w", b" ", b"q"), "l1\nl2\nl3\nl4\nl5\nZl6\nl7\nl8\nl9\nl10\nYl11\nl12\nl13\nl14\nl15\nXl16", ("11│", "16│", "☻", "mode:normal")),
|
||||||
Scenario("multi-file-coding-loop", 72, 16, "repo-multifile", "attached-keyboard", "multi-file", "truecolor", "file", setup_multifile, (b"A", b"?", b"\x1b", b" ", b"w", b" ", b"o", b"r", b"e", b"p", b"o", b"/", b"a", b"l", b"p", b"h", b"a", b".", b"z", b"i", b"g", b"\r", b"A", b"!", b"\x1b", b" ", b"w", b" ", b"q"), None, ("alpha.zig", "beta", "☻", "mode:normal"), max_key_events=30, expect_files=(("alpha.zig", "alpha!\n"), ("beta.zig", "beta?"))),
|
Scenario("multi-file-coding-loop", 72, 16, "repo-multifile", "attached-keyboard", "multi-file", "truecolor", "file", setup_multifile, (b"A", b"?", b"\x1b", b" ", b"w", b" ", b"o", b"r", b"e", b"p", b"o", b"/", b"a", b"l", b"p", b"h", b"a", b".", b"z", b"i", b"g", b"\r", b"A", b"!", b"\x1b", b" ", b"w", b" ", b"q"), None, ("alpha.zig", "beta", "☻", "mode:normal"), max_key_events=30, expect_files=(("alpha.zig", "alpha!\n"), ("beta.zig", "beta?"))),
|
||||||
Scenario("lsp-assisted-coding", 60, 12, "lsp-fixture", "attached-keyboard", "lsp", "truecolor", "file", setup_lsp_assist, (b" ", b"l", b"h", b" ", b"l", b"s", b" ", b"d", b"q", b" ", b"d", b"n", b" ", b"l", b"f", b" ", b"w", b" ", b"q"), "ZLS", ("[zls] add(lhs, rhs)", "[zls] add(lhs: i32, rhs: i32) active=rhs", "diag:fresh:zls", "format:zls:applied", "ZLS", "mode:normal"), max_key_events=19, prelude=LSP_ASSIST_PRELUDE),
|
Scenario("lsp-assisted-coding", 60, 12, "lsp-fixture", "attached-keyboard", "lsp", "truecolor", "file", setup_lsp_assist, (b" ", b"l", b"h", b" ", b"l", b"s", b" ", b"d", b"q", b" ", b"d", b"n", b" ", b"l", b"f", b" ", b"w", b" ", b"q"), "ZLS", ("[zls] add(lhs, rhs)", "[zls] add(lhs: i32, rhs: i32) active=rhs", "diag:fresh:zls", "format:zls:applied", "ZLS", "mode:normal"), max_key_events=19, prelude=LSP_ASSIST_PRELUDE),
|
||||||
Scenario("project-search-panel", 60, 12, "repo-search", "attached-keyboard", "project-search", "truecolor", "file", setup_project_search, (b" ", b"s", b"p", b"f", b"i", b"n", b"d", b"m", b"e", b"\r", b"q", b" ", b"q"), "main\n", ("panel [search]", "target.zig", "findme", "mode:normal"), max_key_events=13),
|
Scenario("project-search-panel", 60, 12, "repo-search", "attached-keyboard", "project-search", "truecolor", "file", setup_project_search, (b" ", b"s", b"p", b"f", b"i", b"n", b"d", b"m", b"e", b"\r", b"q", b" ", b"q"), "main\n", ("panel [search]", "target.zig", "findme", "mode:normal"), max_key_events=13),
|
||||||
|
|||||||
Reference in New Issue
Block a user