summaryrefslogtreecommitdiff
path: root/src/exec.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/exec.zig')
-rw-r--r--src/exec.zig98
1 files changed, 58 insertions, 40 deletions
diff --git a/src/exec.zig b/src/exec.zig
index f3819a83..8ddb9abd 100644
--- a/src/exec.zig
+++ b/src/exec.zig
@@ -108,6 +108,23 @@ pub const PointerOperand = struct {
};
pub fn pointerOperand(p: *Pardes, pane: *Pane, clicked: Pane.Sel) PointerOperand {
+ return operandAt(p, pane, clicked, true);
+}
+
+/// The body's explicit selection, else what a look at its cursor takes.
+pub fn currentOperand(p: *Pardes, pane: *Pane) ?[]const u8 {
+ if (pane.file == null and !pane.isTerminal()) return null;
+ if ((pane.body.vsel.active and pane.body.vsel.explicit) or pane.body.msel.active) return edit.currentSelText(p, pane);
+ return operandAt(p, pane, look.cursorWordSel(p, pane), false).text;
+}
+
+/// What a look or an exec at `clicked` takes: the ONE expansion every
+/// entry point uses (a B2/B3 click, Enter and Tab in normal mode, a bare
+/// Look), so a diff line, a hunk line's code word and a file word expand
+/// alike however they are reached (look.zig's "every entry point" test).
+/// `borrow`: a gesture inside a kept or modal selection takes it; the
+/// keyboard has said which selection it means already.
+pub fn operandAt(p: *Pardes, pane: *Pane, clicked: Pane.Sel, borrow: bool) PointerOperand {
const visible = clicked.r0 - @as(i32, pane.tag_rows);
const wrapped = pane.wrapAt(visible);
const raw = pane.isTerminal() and pane.body.mode == .tty and clicked.r0 >= pane.tag_rows;
@@ -126,48 +143,49 @@ pub fn pointerOperand(p: *Pardes, pane: *Pane, clicked: Pane.Sel) PointerOperand
else
clicked.c0;
var result: PointerOperand = .{ .row = row, .col = col };
-
- const kept = pane.sel[sel_slot];
- const inside_kept = if (pane.pointerSelection(kept)) |rows| inside: {
- if (clicked.r0 < pane.tag_rows) break :inside false;
- if (pane.file != null and clicked.c0 < panes.File.gutterWidth(pane)) break :inside false;
- const source_col: usize = @intCast(@max(0, col));
- for (rows) |span| {
- const target = if (span.raw_terminal)
- (if (raw) span.row else pane.surfRow(span.row))
- else
- (if (raw) pane.gridRow(span.row) else span.row);
- var lo = span.lo;
- var hi = span.hi;
- if (span.raw_terminal and !raw) {
- lo -|= span.prompt_bytes;
- hi -|= span.prompt_bytes;
- } else if (!span.raw_terminal and raw) {
- const prefix = panes.terminal.promptPrefixBytes(pane, row, raw_line);
- lo += prefix;
- hi += prefix;
+ if (borrow) {
+ const kept = pane.sel[sel_slot];
+ const inside_kept = if (pane.pointerSelection(kept)) |rows| inside: {
+ if (clicked.r0 < pane.tag_rows) break :inside false;
+ if (pane.file != null and clicked.c0 < panes.File.gutterWidth(pane)) break :inside false;
+ const source_col: usize = @intCast(@max(0, col));
+ for (rows) |span| {
+ const target = if (span.raw_terminal)
+ (if (raw) span.row else pane.surfRow(span.row))
+ else
+ (if (raw) pane.gridRow(span.row) else span.row);
+ var lo = span.lo;
+ var hi = span.hi;
+ if (span.raw_terminal and !raw) {
+ lo -|= span.prompt_bytes;
+ hi -|= span.prompt_bytes;
+ } else if (!span.raw_terminal and raw) {
+ const prefix = panes.terminal.promptPrefixBytes(pane, row, raw_line);
+ lo += prefix;
+ hi += prefix;
+ }
+ if (target == row and source_col >= lo and source_col < hi)
+ break :inside true;
}
- if (target == row and source_col >= lo and source_col < hi)
- break :inside true;
+ break :inside false;
+ } else edit.spanHas(clicked.r0, clicked.c0, kept.r0, kept.c0, kept.r1, kept.c1);
+ if (kept.state == .done and inside_kept) {
+ result.text = edit.selectionText(p, pane, kept) catch null;
+ result.preview = kept;
+ return result;
+ }
+ if (pane.body.vsel.active and pane.body.vsel.explicit and
+ edit.spanHas(row, col, pane.body.vsel.row, pane.body.vsel.col, pane.body.cur_row, pane.body.cur_col))
+ {
+ result.text = edit.currentSelText(p, pane);
+ return result;
+ }
+ if (pane.body.msel.active and row >= @min(pane.body.msel.r0, pane.body.msel.r1) and
+ row <= @max(pane.body.msel.r0, pane.body.msel.r1))
+ {
+ result.text = edit.currentSelText(p, pane);
+ return result;
}
- break :inside false;
- } else edit.spanHas(clicked.r0, clicked.c0, kept.r0, kept.c0, kept.r1, kept.c1);
- if (kept.state == .done and inside_kept) {
- result.text = edit.selectionText(p, pane, kept) catch null;
- result.preview = kept;
- return result;
- }
- if (pane.body.vsel.active and pane.body.vsel.explicit and
- edit.spanHas(row, col, pane.body.vsel.row, pane.body.vsel.col, pane.body.cur_row, pane.body.cur_col))
- {
- result.text = edit.currentSelText(p, pane);
- return result;
- }
- if (pane.body.msel.active and row >= @min(pane.body.msel.r0, pane.body.msel.r1) and
- row <= @max(pane.body.msel.r0, pane.body.msel.r1))
- {
- result.text = edit.currentSelText(p, pane);
- return result;
}
// In a diff, a file or hunk header, and a hunk line pointed at on its
// `+`/`-`/` ` prefix, expand to the whole line (the hover shows it) and