pull/11711/merge
Alex Shi 2026-06-02 21:48:40 -07:00 committed by GitHub
commit 6d5e89709d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 72 additions and 2 deletions

View File

@ -3015,6 +3015,24 @@ fn promptClickLine(self: *Screen, click_pin: Pin) PromptClickMove {
const cursor_pin = self.cursor.page_pin.*;
if (cursor_pin.eql(click_pin)) return .zero;
const click_rac = click_pin.rowAndCell().row;
// If click pin is in the prompt area, traverse down the prompt rows.
// Allow cursor movement only if one of the rows contains input.
if (click_rac.semantic_prompt != .none) {
var row_pin = click_pin;
prompt: while (true) {
const rac = row_pin.rowAndCell();
const cells = row_pin.node.data.getCells(rac.row);
for (cells) |cell| {
if (cell.semantic_content == .input) break :prompt;
}
if (!rac.row.wrap) return .zero;
row_pin = row_pin.down(1) orelse return .zero;
}
}
// If our cursor is before our click, we're only emitting right inputs.
if (cursor_pin.before(click_pin)) {
var count: usize = 0;
@ -7480,7 +7498,7 @@ test "Screen: resize more cols with cursor at prompt" {
defer s.deinit();
// zig fmt: off
try s.testWriteString("ABCDE\n");
try s.testWriteString("ABCDE\n");
s.cursorSetSemanticContent(.{ .prompt = .initial });
try s.testWriteString("> ");
s.cursorSetSemanticContent(.{ .input = .clear_eol });
@ -7520,7 +7538,7 @@ test "Screen: resize more cols with cursor not at prompt" {
defer s.deinit();
// zig fmt: off
try s.testWriteString("ABCDE\n");
try s.testWriteString("ABCDE\n");
s.cursorSetSemanticContent(.{ .prompt = .initial });
try s.testWriteString("> ");
s.cursorSetSemanticContent(.{ .input = .clear_eol });
@ -10270,6 +10288,58 @@ test "Screen: promptClickMove line left basic" {
try testing.expectEqual(@as(usize, 0), result.right);
}
test "Screen: promptClickMove ignores click on prompt-only line" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 });
defer s.deinit();
s.semantic_prompt.click = .{ .cl = .line };
s.cursorSetSemanticContent(.{ .prompt = .initial });
try s.testWriteString("> \n");
s.cursorSetSemanticContent(.{ .input = .clear_explicit });
try s.testWriteString("hello");
const click_on_top_left = s.pages.pin(.{ .active = .{ .x = 0, .y = 0 } }).?;
const result = s.promptClickMove(click_on_top_left);
try testing.expectEqual(PromptClickMove.zero, result);
const click_on_blank_cell = s.pages.pin(.{ .active = .{ .x = 10, .y = 0 } }).?;
const blank_result = s.promptClickMove(click_on_blank_cell);
try testing.expectEqual(PromptClickMove.zero, blank_result);
}
test "Screen: promptClickMove click on wrapped multi-line prompt moves to input start" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 0 });
defer s.deinit();
s.semantic_prompt.click = .{ .cl = .line };
s.cursorSetSemanticContent(.{ .prompt = .initial });
try s.testWriteString(">>>>>>>>>>>>");
s.cursorSetSemanticContent(.{ .input = .clear_explicit });
try s.testWriteString("hi");
s.cursorAbsolute(4, 1);
const click_first_prompt_row = s.pages.pin(.{ .active = .{ .x = 0, .y = 0 } }).?;
const result_first_prompt_row = s.promptClickMove(click_first_prompt_row);
try testing.expectEqual(@as(usize, 2), result_first_prompt_row.left);
try testing.expectEqual(@as(usize, 0), result_first_prompt_row.right);
const click_second_prompt_row = s.pages.pin(.{ .active = .{ .x = 1, .y = 1 } }).?;
const result_second_prompt_row = s.promptClickMove(click_second_prompt_row);
try testing.expectEqual(@as(usize, 2), result_second_prompt_row.left);
try testing.expectEqual(@as(usize, 0), result_second_prompt_row.right);
}
test "Screen: promptClickMove line left skips non-input cells" {
const testing = std.testing;
const alloc = testing.allocator;