summaryrefslogtreecommitdiff
path: root/src/mouse.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/mouse.zig')
-rw-r--r--src/mouse.zig130
1 files changed, 65 insertions, 65 deletions
diff --git a/src/mouse.zig b/src/mouse.zig
index 2a00bded..a840c8fc 100644
--- a/src/mouse.zig
+++ b/src/mouse.zig
@@ -378,7 +378,7 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void {
// next cursor move or left wheel pulls it back
} else if (pane.file != null and !p.settings.wrap) {
// wrapped there is nothing off to the right to reach
- const line = panes.File.sourceLine(pane, pane.cur_row);
+ const line = panes.File.sourceLine(pane, pane.body.cur_row);
const visual = panes.File.rawDisplayCol(line, @intCast(@max(0, pane.hscroll)));
const next: usize = if (m.button == .wheel_right)
visual +| @as(usize, @intCast(config.wheel_cols))
@@ -682,7 +682,7 @@ fn gestureRange(p: *Pardes, id: usize, text: []const u8, on_tag: bool, operand:
const top = @min(sel.r0, sel.r1) - @as(i32, BOX_H);
if (top < 0) break :lead null;
const w = pane.wrapAt(top);
- const col = edit.paneByteAtDisplay(p, pane, w.line, w.at, @min(sel.c0, sel.c1) - panes.File.gutterWidth(pane));
+ const col = edit.paneByteAtDisplay(p, &pane.body, w.line, w.at, @min(sel.c0, sel.c1) - panes.File.gutterWidth(pane));
break :lead .{
.row = @intCast(@max(0, w.line)),
.col = @intCast(@max(0, col)),
@@ -720,22 +720,22 @@ fn mirrorTtySelection(p: *Pardes, pane: *Pane) void {
const body = body_layer.bodyText(p, p.scratch.allocator(), pane) catch return;
const line = modal.lineSlice(body, @intCast(@max(0, endpoint.row - panes.Terminal.gridOffset(pane))));
const byte = if (gesture.c1 >= gesture.c0) modal.prevGrapheme(line, @min(endpoint.hi, line.len)) else endpoint.lo;
- pane.cur_row = pane.surfRow(endpoint.row);
+ pane.body.cur_row = pane.surfRow(endpoint.row);
var shown = std.mem.trimEnd(u8, line[@min(endpoint.prompt_bytes, line.len)..], " \t");
if (pane.ovl) |overlay| {
- const relative = pane.cur_row - overlay.row;
+ const relative = pane.body.cur_row - overlay.row;
if (relative >= 0 and relative < modal.lineCount(overlay.text))
shown = modal.lineSlice(overlay.text, @intCast(relative));
}
- pane.cur_col = @intCast(modal.graphemeStart(shown, @min(shown.len, byte -| endpoint.prompt_bytes)));
- pane.cur_pinned = true;
- pane.msel.active = false;
- pane.vsel.active = false;
- pane.nsel = 0;
- pane.select = false;
- pane.append_at = null;
- pane.sticky_col = -1;
- pane.normal.clear();
+ pane.body.cur_col = @intCast(modal.graphemeStart(shown, @min(shown.len, byte -| endpoint.prompt_bytes)));
+ pane.body.cur_pinned = true;
+ pane.body.msel.active = false;
+ pane.body.vsel.active = false;
+ pane.body.nsel = 0;
+ pane.body.select = false;
+ pane.body.append_at = null;
+ pane.body.sticky_col = -1;
+ pane.body.normal.clear();
edit.setYank(p, text);
}
@@ -813,27 +813,27 @@ fn dragRelease(p: *Pardes, button: Mouse.Button) void {
const dragged = sl.c0 != sl.c1 or sl.r0 != sl.r1;
if (!dragged) pane.sel[sel_slot].state = .none;
if (dragged) edit.capturePointerSelection(p, pane, sel_slot) catch {};
- if (dragged and pane.mode == .tty) mirrorTtySelection(p, pane);
+ if (dragged and pane.body.mode == .tty) mirrorTtySelection(p, pane);
const body_vis = sl.r1 - @as(i32, BOX_H);
- if (body_vis >= 0 and pane.mode != .tty) {
+ if (body_vis >= 0 and pane.body.mode != .tty) {
const w = pane.wrapAt(body_vis);
- pane.cur_row = w.line;
- pane.cur_col = edit.paneByteAtDisplay(
+ pane.body.cur_row = w.line;
+ pane.body.cur_col = edit.paneByteAtDisplay(
p,
- pane,
+ &pane.body,
w.line,
w.at,
sl.c1 - (if (pane.file != null) @as(i32, panes.File.gutterWidth(pane)) else 0),
);
- pane.cur_pinned = true;
- if (edit.clampFileCursor(pane)) pane.ensureCursorVisible();
- pane.msel.active = false;
- pane.normal.clear();
- pane.vsel.active = false;
- pane.nsel = 0; // a click says WHERE the one cursor is
- pane.select = false;
- pane.append_at = null;
- pane.sticky_col = -1;
+ pane.body.cur_pinned = true;
+ if (edit.clampFileCursor(&pane.body)) pane.ensureCursorVisible();
+ pane.body.msel.active = false;
+ pane.body.normal.clear();
+ pane.body.vsel.active = false;
+ pane.body.nsel = 0; // a click says WHERE the one cursor is
+ pane.body.select = false;
+ pane.body.append_at = null;
+ pane.body.sticky_col = -1;
if (s.ctrl) p.lspRequest(s.id, .definition, "");
}
} else {
@@ -842,7 +842,7 @@ fn dragRelease(p: *Pardes, button: Mouse.Button) void {
// this file -- a sticky context header's number included,
// since the row map holds each header's own source line.
if (s.button == config.look_button and clk.r0 >= BOX_H and clk.r0 == clk.r1 and
- clk.c0 == clk.c1 and clk.c0 >= 0 and pane.mode != .tty)
+ clk.c0 == clk.c1 and clk.c0 >= 0 and pane.body.mode != .tty)
if (pane.file) |f| if (f.output == null and clk.c0 < panes.File.gutterWidth(pane)) {
const line = pane.wrapAt(clk.r0 - BOX_H).line;
if (line >= 0) {
@@ -858,10 +858,10 @@ fn dragRelease(p: *Pardes, button: Mouse.Button) void {
pane.sel[b] = expanded
else if (operand.text == null)
pane.sel[b].state = .none;
- if (s.button == config.look_button and clk.r0 >= BOX_H and pane.mode != .tty) {
- pane.cur_row = operand.row;
- pane.cur_col = operand.col;
- if (edit.clampFileCursor(pane)) pane.ensureCursorVisible();
+ if (s.button == config.look_button and clk.r0 >= BOX_H and pane.body.mode != .tty) {
+ pane.body.cur_row = operand.row;
+ pane.body.cur_col = operand.col;
+ if (edit.clampFileCursor(&pane.body)) pane.ensureCursorVisible();
}
const txt = operand.text;
const cmd = if (s.button == config.look_button) config.look_cmd else config.exec_cmd;
@@ -909,7 +909,7 @@ fn chordCutPaste(p: *Pardes, cut: bool) void {
if (cut and pv.selection_text.len > 0) edit.setYank(p, pv.selection_text);
return;
};
- if (pane.mode == .tty) {
+ if (pane.body.mode == .tty) {
if (!s.chorded) {
s.chorded = true;
pane.sel[sel_slot].state = .none; // drop the sweep highlight
@@ -944,44 +944,44 @@ fn chordCutPaste(p: *Pardes, cut: bool) void {
const w1 = pane.wrapAt(@max(0, sl.r1 - @as(i32, BOX_H)));
const row0 = w0.line;
const row1 = w1.line;
- const col0 = edit.paneByteAtDisplay(p, pane, w0.line, w0.at, sl.c0 - pfx);
- const col1 = edit.paneByteAtDisplay(p, pane, w1.line, w1.at, sl.c1 - pfx);
- pane.cur_row = row1;
- pane.cur_col = col1;
- pane.cur_pinned = true;
- pane.msel.active = false;
- pane.normal.clear();
- if (!pane.isTerminal()) pane.mode = .normal;
- pane.vsel = .{ .active = row0 != row1 or col0 != col1, .row = row0, .col = col0, .explicit = false };
- pane.nsel = 0;
+ const col0 = edit.paneByteAtDisplay(p, &pane.body, w0.line, w0.at, sl.c0 - pfx);
+ const col1 = edit.paneByteAtDisplay(p, &pane.body, w1.line, w1.at, sl.c1 - pfx);
+ pane.body.cur_row = row1;
+ pane.body.cur_col = col1;
+ pane.body.cur_pinned = true;
+ pane.body.msel.active = false;
+ pane.body.normal.clear();
+ if (!pane.isTerminal()) pane.body.mode = .normal;
+ pane.body.vsel = .{ .active = row0 != row1 or col0 != col1, .row = row0, .col = col0, .explicit = false };
+ pane.body.nsel = 0;
}
if (cut) {
- if (pane.vsel.active) edit.normalDelete(p, pane, true);
- } else if (pane.vsel.active) {
- edit.normalReplaceYank(p, pane);
+ if (pane.body.vsel.active) edit.normalDelete(p, &pane.body, true);
+ } else if (pane.body.vsel.active) {
+ edit.normalReplaceYank(p, &pane.body);
} else if (pane.file) |*f| {
// bare cursor: splice the register in literally (no linewise
// magic) so a paste right after a cut restores the text exactly
const y = p.yank orelse return;
if (y.len == 0) return;
- const at = modal.Cursor{ .row = @intCast(@max(0, pane.cur_row)), .col = @intCast(@max(0, pane.cur_col)) };
- edit.pushUndo(p, pane);
+ const at = modal.Cursor{ .row = @intCast(@max(0, pane.body.cur_row)), .col = @intCast(@max(0, pane.body.cur_col)) };
+ edit.pushUndo(p, &pane.body);
const new = modal.insertAt(p.gpa, f.content, at, y) catch return;
panes.File.setContent(p, f, new);
- pane.vsel = .{ .active = modal.nextGrapheme(y, 0) < y.len, .row = @intCast(at.row), .col = @intCast(at.col), .explicit = false };
+ pane.body.vsel = .{ .active = modal.nextGrapheme(y, 0) < y.len, .row = @intCast(at.row), .col = @intCast(at.col), .explicit = false };
const end = modal.advanceBy(at, y);
if (end.col > 0) {
- pane.cur_row = @intCast(end.row);
- pane.cur_col = @intCast(modal.prevGrapheme(modal.lineSlice(f.content, end.row), end.col));
+ pane.body.cur_row = @intCast(end.row);
+ pane.body.cur_col = @intCast(modal.prevGrapheme(modal.lineSlice(f.content, end.row), end.col));
} else {
// the register ended in '\n': the cursor lands ON that newline
- pane.cur_row = @intCast(end.row -| 1);
- pane.cur_col = @intCast(modal.lineSlice(f.content, end.row -| 1).len);
+ pane.body.cur_row = @intCast(end.row -| 1);
+ pane.body.cur_col = @intCast(modal.lineSlice(f.content, end.row -| 1).len);
}
- pane.cur_pinned = true;
- pane.sticky_col = -1;
+ pane.body.cur_pinned = true;
+ pane.body.sticky_col = -1;
pane.ensureCursorVisible();
- } else edit.pasteText(p, pane, p.yank orelse return, true, 1);
+ } else edit.pasteText(p, &pane.body, p.yank orelse return, true, 1);
}
test "plain left click clears explicit modal selection" {
@@ -989,10 +989,10 @@ test "plain left click clears explicit modal selection" {
const p = try Pardes.init(gpa, .{ .cols = 40, .rows = 10 });
defer p.deinit();
const pane = try p.setTestFile("abcdef\n");
- pane.cur_row = 0;
- pane.cur_col = 5;
- pane.vsel = .{ .active = true, .row = 0, .col = 1, .explicit = true };
- pane.msel = .{ .active = true, .r0 = 0, .r1 = 0 };
+ pane.body.cur_row = 0;
+ pane.body.cur_col = 5;
+ pane.body.vsel = .{ .active = true, .row = 0, .col = 1, .explicit = true };
+ pane.body.msel = .{ .active = true, .r0 = 0, .r1 = 0 };
var frame = std.heap.ArenaAllocator.init(gpa);
defer frame.deinit();
@@ -1003,9 +1003,9 @@ test "plain left click clears explicit modal selection" {
p.update(.{ .mouse = .{ .button = config.select_button, .kind = .press, .col = click_x, .row = body_y } });
p.update(.{ .mouse = .{ .button = config.select_button, .kind = .release, .col = click_x, .row = body_y } });
- try std.testing.expectEqual(@as(i32, 3), pane.cur_col);
- try std.testing.expect(!pane.vsel.active);
- try std.testing.expect(!pane.msel.active);
+ try std.testing.expectEqual(@as(i32, 3), pane.body.cur_col);
+ try std.testing.expect(!pane.body.vsel.active);
+ try std.testing.expect(!pane.body.msel.active);
try std.testing.expectEqual(.none, pane.sel[@intFromEnum(config.select_button)].state);
}
@@ -1412,7 +1412,7 @@ test "mouse thumb buttons navigate once and clear selection gestures" {
const p = try Pardes.init(std.testing.allocator, .{ .cols = 60, .rows = 12 });
defer p.deinit();
const pane = try p.setTestFile("alpha beta\ngamma delta\nepsilon zeta\n");
- pane.setRange(pane.file.?.content, 0, .{ .anchor = 1, .head = 5 }, true);
+ pane.body.setRange(pane.file.?.content, 0, .{ .anchor = 1, .head = 5 }, true);
p.njumps = 3;
p.jcur = 2;
for (0..3) |i| p.jumps[i] = .{ .pane = 0, .serial = pane.serial, .line = @intCast(i + 1), .col = 1 };
@@ -1425,6 +1425,6 @@ test "mouse thumb buttons navigate once and clear selection gestures" {
p.update(.{ .mouse = .{ .button = .forward, .kind = .press, .col = 0, .row = 0 } });
p.update(.{ .mouse = .{ .button = .forward, .kind = .release, .col = 0, .row = 0 } });
try std.testing.expectEqual(@as(usize, 2), p.jcur);
- try std.testing.expect(!pane.vsel.active);
+ try std.testing.expect(!pane.body.vsel.active);
try std.testing.expectEqual(.none, p.drag);
}