summaryrefslogtreecommitdiff
path: root/src/panes.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/panes.zig')
-rw-r--r--src/panes.zig44
1 files changed, 38 insertions, 6 deletions
diff --git a/src/panes.zig b/src/panes.zig
index a39afe01..b2f05cdf 100644
--- a/src/panes.zig
+++ b/src/panes.zig
@@ -44,10 +44,13 @@ pub const Pane = struct {
hi: usize,
prefix: [32]u8 = @splat(0),
prefix_len: u8 = 0,
+ raw_terminal: bool = false,
+ prompt_bytes: usize = 0,
};
pub const PointerSelection = struct {
gesture: Sel,
rows: []PointerRow,
+ raw_text: ?[]u8 = null,
};
/// A modal line selection (helix `x`): whole rows [r0, r1], absolute.
@@ -174,10 +177,21 @@ pub const Pane = struct {
msg_len: u16 = 0,
pub fn clearPointerSelection(pane: *Pane, slot: usize) void {
- if (pane.pointer_selections[slot]) |selection| pane.gpa.free(selection.rows);
+ if (pane.pointer_selections[slot]) |selection| {
+ pane.gpa.free(selection.rows);
+ if (selection.raw_text) |text| pane.gpa.free(text);
+ }
pane.pointer_selections[slot] = null;
}
+ pub fn rawPointerText(pane: *const Pane, gesture: Sel) ?[]const u8 {
+ if (gesture.state != .done or gesture.source_id == 0) return null;
+ for (pane.pointer_selections) |selection| {
+ if (selection) |saved| if (std.meta.eql(saved.gesture, gesture)) return saved.raw_text;
+ }
+ return null;
+ }
+
pub fn pointerSelection(pane: *const Pane, gesture: Sel) ?[]PointerRow {
if (gesture.state != .done or gesture.source_id == 0) return null;
for (pane.pointer_selections) |selection| {
@@ -6330,7 +6344,7 @@ pub const Terminal = struct {
var index: usize = 0;
for (pane.sel) |gesture| if (pane.pointerSelection(gesture)) |rows| {
for (rows) |*row| {
- pins[index] = trackPosition(pages, &row.row, overlay, &failed);
+ pins[index] = trackPosition(pages, &row.row, if (row.raw_terminal) null else overlay, &failed);
index += 1;
}
};
@@ -6482,7 +6496,8 @@ pub const Terminal = struct {
pub fn enterTty(p: *Pardes, id: usize) void {
const pane = p.panes[id] orelse return;
- if (comptime enabled) if (pane.terminal != null and pane.cur_pinned and pane.terminal.?.vt.cursorIsAtPrompt()) handoff: {
+ const selected = pane.rawPointerText(pane.sel[@intFromEnum(config.select_button)]) != null;
+ if (comptime enabled) if (!selected and pane.terminal != null and pane.cur_pinned and pane.terminal.?.vt.cursorIsAtPrompt()) handoff: {
const screen = pane.terminal.?.vt.screens.active;
const goff: i32 = @intCast(screen.pages.scrollbar().offset);
const vp_row = pane.gridRow(pane.cur_row) - goff;
@@ -6511,9 +6526,9 @@ pub const Terminal = struct {
pane.msel.active = false;
pane.vsel.active = false;
pane.nsel = 0;
- // A pinned row scrolls away. Raw mode must follow the program's live
- // cursor, and Last must not restore a stale modal spot on the way back.
- pane.cur_pinned = false;
+ // The raw renderer follows the live cursor. A captured mouse selection
+ // keeps its modal endpoint for the next return to editor mode.
+ pane.cur_pinned = selected;
pane.select = false;
pane.append_at = null;
pane.sticky_col = -1;
@@ -6590,6 +6605,19 @@ pub const Terminal = struct {
return .{ .cut = cols };
}
+ pub fn promptPrefixBytes(pane: *Pane, row: i32, raw: []const u8) usize {
+ if (comptime !enabled) return 0;
+ if (row < 0) return 0;
+ const state = pane.terminal orelse return 0;
+ const pin = state.vt.screens.active.pages.pin(.{ .screen = .{ .x = 0, .y = @intCast(row) } }) orelse return 0;
+ if (pin.rowAndCell().row.semantic_prompt == .none) return 0;
+ return switch (promptCut(pin)) {
+ .keep => 0,
+ .blank => raw.len,
+ .cut => |cols| @min(raw.len, File.rawAtDisplay(raw, cols)),
+ };
+ }
+
fn promptRow(pin: ghostty_vt.Pin, raw: []const u8) []const u8 {
const cols = switch (promptCut(pin)) {
.keep => return raw,
@@ -6765,6 +6793,10 @@ pub const Terminal = struct {
/// Consume a rewritten overlay, freeing the terminal edit text it replaces.
pub fn setEditText(p: *Pardes, pane: *Pane, new: []u8) void {
const overlay = if (pane.ovl) |*value| value else return p.gpa.free(new);
+ for (0..pane.sel.len) |button| {
+ pane.clearPointerSelection(button);
+ pane.sel[button].state = .none;
+ }
p.gpa.free(overlay.text);
overlay.text = new;
}