Expose panel rails with mobile aliases
This commit is contained in:
@@ -295,17 +295,16 @@ Opening a result returns to the editor without leaving behind permanent splits.
|
||||
| Keys | Surface |
|
||||
| --- | --- |
|
||||
| `Space f` | files panel / file tree / finder / recent |
|
||||
| `Space P` | Pi/local trusted tool panel |
|
||||
| `Space a` or `Space P` | Pi/local trusted assistant/tool panel (`a` is the no-shift mobile path; `P` is the attached-keyboard mnemonic) |
|
||||
| `Space s` | search: file/project/symbol |
|
||||
| `Space d` | diagnostics |
|
||||
| `Space g` | go/navigation |
|
||||
| `g` rail | go/navigation (`gg`, `G`, `g u/d`, `g a/A`, diagnostics) |
|
||||
| `Space l` | language/LSP tools |
|
||||
| `Space t` | tasks: build/test/check/lint jobs |
|
||||
| `Space j` or `Space t` | jobs/tasks: build/test/check/lint output and cancellation (`j` is the no-shift mobile path; `t` remains the task mnemonic) |
|
||||
| `Space b` | buffers/build output depending on rail label |
|
||||
| `Space v` | version control/git workbench |
|
||||
| `Space !` | terminal escape hatch/job command |
|
||||
| `Space p` | coding symbol rail |
|
||||
| `Space P` | Pi/local trusted tool panel |
|
||||
| `Space y` or `Space p` | coding symbol rail (`y` is the no-shift alternate kept free for symbols; `p` is the historical/programming mnemonic) |
|
||||
|
||||
Panel controls are consistent:
|
||||
|
||||
@@ -334,11 +333,11 @@ Tool operations are first-class commands, not hidden side effects.
|
||||
| `Space l` `f` | format current buffer |
|
||||
| `Space l` `F` or `Space l` `w` | toggle/show format-on-save policy for this source build |
|
||||
| `Space l` `d` | show provider details for symbol/diagnostic under cursor |
|
||||
| `Space t` `l` | lint current file |
|
||||
| `Space t` `L` | lint project/workspace |
|
||||
| `Space t` `b` | build |
|
||||
| `Space t` `t` | test |
|
||||
| `Space t` `c` | check/typecheck |
|
||||
| `Space j`/`Space t` `l` | lint current file |
|
||||
| `Space j`/`Space t` `L` | lint project/workspace |
|
||||
| `Space j`/`Space t` `b` | build |
|
||||
| `Space j`/`Space t` `t` | test |
|
||||
| `Space j`/`Space t` `c` | check/typecheck |
|
||||
| `Space d` | diagnostics panel |
|
||||
| `Space d` `n` | next diagnostic |
|
||||
| `Space d` `p` | previous diagnostic |
|
||||
|
||||
@@ -30,6 +30,7 @@ Rows are redgate TSV requirements: `ring<TAB>id<TAB>summary [tag]`.
|
||||
1 017 Insert and Select mode SHALL return to Normal via Escape and Ctrl-[ as equivalent terminal events while preserving literal Insert-mode Space. [mobile]
|
||||
1 018 Select mode SHALL keep bare movement keys as selection-extending motions and provide a non-conflicting mobile object-selection rail for word, line, indent, parameter, enclosing form, and diagnostic ranges. [mobile]
|
||||
1 019 Hover, signature help, and parameter navigation SHALL share a discoverable language rail, with any attached-keyboard accelerator documented as an alias rather than the only path. [mobile]
|
||||
1 020 Files, search, jobs, Pi/assistant, and symbol panels SHALL have documented top-rail mobile paths, with shifted or mnemonic aliases treated as accelerators rather than the only discoverable path. [mobile]
|
||||
|
||||
## ui
|
||||
|
||||
|
||||
+27
-5
@@ -105,7 +105,7 @@ pub const Leader = struct {
|
||||
if (self.message) |message| return message;
|
||||
return switch (self.mode) {
|
||||
.idle => "",
|
||||
.rail => "leader: w save q quit Q discard f files P Pi o open p symbols s search r repeat",
|
||||
.rail => "leader: w save q quit f files s search j jobs a/P Pi p/y symbols",
|
||||
.symbol_rail => symbol_mod.rail_status,
|
||||
.search_rail => "search: f current file p project s symbols",
|
||||
.language_rail => "language: h hover s sig n/p param f fmt o imports a actions",
|
||||
@@ -163,7 +163,7 @@ pub const Leader = struct {
|
||||
self.mode = .diagnostic_rail;
|
||||
return .diagnostics_open;
|
||||
}
|
||||
if (std.mem.eql(u8, text, "t")) {
|
||||
if (std.mem.eql(u8, text, "t") or std.mem.eql(u8, text, "j")) {
|
||||
self.mode = .tool_rail;
|
||||
return .none;
|
||||
}
|
||||
@@ -184,11 +184,11 @@ pub const Leader = struct {
|
||||
self.mode = .idle;
|
||||
return .file_picker;
|
||||
}
|
||||
if (std.mem.eql(u8, text, "P")) {
|
||||
if (std.mem.eql(u8, text, "P") or std.mem.eql(u8, text, "a")) {
|
||||
self.mode = .idle;
|
||||
return .pi_panel;
|
||||
}
|
||||
if (std.mem.eql(u8, text, "p")) {
|
||||
if (std.mem.eql(u8, text, "p") or std.mem.eql(u8, text, "y")) {
|
||||
self.mode = .symbol_rail;
|
||||
return .none;
|
||||
}
|
||||
@@ -457,7 +457,7 @@ test "regular: space opens a visible leader rail and write dispatches" {
|
||||
defer leader.deinit();
|
||||
|
||||
try expectActionTag(.none, try leader.handleEvent(input.normalize(" ")));
|
||||
try std.testing.expectEqualStrings("leader: w save q quit Q discard f files P Pi o open p symbols s search r repeat", leader.status());
|
||||
try std.testing.expectEqualStrings("leader: w save q quit f files s search j jobs a/P Pi p/y symbols", leader.status());
|
||||
|
||||
try expectActionTag(.save, try leader.handleEvent(input.normalize("w")));
|
||||
try std.testing.expect(!leader.isActive());
|
||||
@@ -622,3 +622,25 @@ test "regular: language rail groups hover signature and parameter navigation" {
|
||||
try expectActionTag(.none, try leader.handleEvent(input.normalize("l")));
|
||||
try expectActionTag(.language_parameter_previous, try leader.handleEvent(input.normalize("p")));
|
||||
}
|
||||
|
||||
test "regular: top rail exposes unshifted panel aliases" {
|
||||
var leader = Leader.init(std.testing.allocator);
|
||||
defer leader.deinit();
|
||||
|
||||
try expectActionTag(.none, try leader.handleEvent(input.normalize(" ")));
|
||||
try std.testing.expect(std.mem.indexOf(u8, leader.status(), "f files") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, leader.status(), "s search") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, leader.status(), "j jobs") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, leader.status(), "a/P Pi") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, leader.status(), "p/y symbols") != null);
|
||||
try expectActionTag(.pi_panel, try leader.handleEvent(input.normalize("a")));
|
||||
|
||||
try expectActionTag(.none, try leader.handleEvent(input.normalize(" ")));
|
||||
try expectActionTag(.none, try leader.handleEvent(input.normalize("j")));
|
||||
try std.testing.expect(std.mem.indexOf(u8, leader.status(), "tools:") != null);
|
||||
try expectActionTag(.job_build, try leader.handleEvent(input.normalize("b")));
|
||||
|
||||
try expectActionTag(.none, try leader.handleEvent(input.normalize(" ")));
|
||||
try expectActionTag(.none, try leader.handleEvent(input.normalize("y")));
|
||||
try std.testing.expect(std.mem.indexOf(u8, leader.status(), "symbols:") != null);
|
||||
}
|
||||
|
||||
+2
-1
@@ -5278,7 +5278,8 @@ test "adversarial: unknown physical key names stay rejected and leader help stay
|
||||
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(), "Q discard") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, client.leader.status(), "j jobs") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, client.leader.status(), "a/P Pi") != null);
|
||||
const frame = try client.render(std.testing.allocator);
|
||||
defer std.testing.allocator.free(frame);
|
||||
try assertLinesFit(frame, 72);
|
||||
|
||||
@@ -560,8 +560,8 @@ SCENARIOS = [
|
||||
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"l", b"n", b"q", b" ", b"l", b"p", b"q", 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", "panel [lsp-parameter]", "diag:fresh:zls", "format:zls:applied", "ZLS", "mode:normal"), max_key_events=27, 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("file-and-pi-panels", 60, 12, "repo-multifile", "attached-keyboard", "panels", "truecolor", "file", setup_multifile, (b" ", b"f", b"q", b" ", b"P", b"q", b" ", b"q"), "beta\n", ("panel [files]", "alpha.zig", "panel [pi]", "pi_ask:explain_current_buffer", "mode:normal"), required_attrs=("panel-header", "current-line"), max_key_events=8),
|
||||
Scenario("job-cancel-output-panel", 60, 12, "job", "attached-keyboard", "job-output", "truecolor", "file", setup_empty, (b" ", b"t", b"x", b"q", b" ", b"q"), "", ("panel [job-output]", "job:profile:build", "job:status:cancelled:user", "mode:normal"), max_key_events=6),
|
||||
Scenario("file-and-pi-panels", 60, 12, "repo-multifile", "attached-keyboard", "panels", "truecolor", "file", setup_multifile, (b" ", b"f", b"q", b" ", b"a", b"q", b" ", b"q"), "beta\n", ("panel [files]", "alpha.zig", "panel [pi]", "pi_ask:explain_current_buffer", "mode:normal"), required_attrs=("panel-header", "current-line"), max_key_events=8),
|
||||
Scenario("job-cancel-output-panel", 60, 12, "job", "attached-keyboard", "job-output", "truecolor", "file", setup_empty, (b" ", b"j", b"x", b"q", b" ", b"q"), "", ("panel [job-output]", "job:profile:build", "job:status:cancelled:user", "mode:normal"), max_key_events=6),
|
||||
Scenario("dirty-discard-shift-q", 52, 12, "empty", "ios-default-qwertz-space-path", "dirty-discard", "truecolor", "file", setup_empty, tuple(bytes([b]) for b in b" ps Q"), "", ("1│", "☻")),
|
||||
Scenario("directory-panel-narrow", 52, 12, "directory", "ios-default-qwertz-space-path", "panel", "mono", "directory", setup_directory, PANEL_QUIT, None, ("file", "one.zig"), required_attrs=()),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user