diff options
Diffstat (limited to 'src/pardes.zig')
| -rw-r--r-- | src/pardes.zig | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/src/pardes.zig b/src/pardes.zig index 65f3aebb..321a6b3c 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -4976,16 +4976,14 @@ pub const Pardes = struct { if (t.what != .body) { // An explicit selection, else the word under the cursor in the // text as it is shown: a tag's prefix is part of what a word is. - const arena = p.scratch.allocator(); - const own = arena.dupe(u8, edit.flatSurface(p, t) catch return) catch return; - const shown = if (t.what == .tag) tagline.tagText(p, arena, pane) catch return else own; - const range = t.primaryRange(own, 0); + const shown = p.scratch.allocator().dupe(u8, edit.flatSurface(p, t) catch return) catch return; + const range = t.primaryRange(shown, 0); const lo = @min(range.anchor, range.head); const hi = @max(range.anchor, range.head); const txt = if ((t.vsel.active and t.vsel.explicit) or t.msel.active) - own[lo..hi] + shown[lo..hi] else word: { - const b = config.wordBounds(shown, shown.len - own.len + modal.selectionCursor(own, range)); + const b = config.wordBounds(shown, modal.selectionCursor(shown, range)); break :word shown[b.lo..b.hi]; }; // Out of the tag or header FIRST: Del frees the pane, Kill @@ -5013,6 +5011,14 @@ pub const Pardes = struct { return; } if (t.mode == .normal and t.what == .body and pane.hasPdf()) return normal.handlePdfNormal(p, pane, key); + if (t.what == .tag and t.mode == .insert and tagline.typedIntoName(p, pane, key)) return; + // A tag's prefix is read-only: a key whose edit reached into it + // changes nothing, not even where the cursor is. + const kept = .{ t.cur_row, t.cur_col, t.vsel, t.msel, t.sels, t.nsel }; + t.refused = false; + defer if (t.refused) { + t.cur_row, t.cur_col, t.vsel, t.msel, t.sels, t.nsel = kept; + }; switch (t.mode) { .normal => normal.handleNormal(p, t, key), .insert => { @@ -5597,6 +5603,23 @@ pub const Pardes = struct { const r = p.rects[id]; // The tag takes a row per line, leaving the body one row if it // had any; a folded pane shows its first line only. + // Measured on the stack: this runs on every event, and not + // every event may take from the scratch arena. + var room: [2 * limits.host_path_cap + 256]u8 = undefined; + var measure = std.heap.FixedBufferAllocator.init(&room); + const lead = if (tagline.prefixIn(measure.allocator(), pane)) |prefix| prefix.len else |_| pane.tag_lead; + if (lead != pane.tag_lead) { + const t = &pane.tag; + const old: i32 = @intCast(pane.tag_lead); + const new: i32 = @intCast(lead); + if (t.cur_row == 0 and t.cur_col >= old) t.cur_col += new - old; + if (t.vsel.row == 0 and t.vsel.col >= old) t.vsel.col += new - old; + for (t.sels[0..t.nsel]) |*sel| { + if (sel.row == 0 and sel.col >= old) sel.col += new - old; + if (sel.arow == 0 and sel.acol >= old) sel.acol += new - old; + } + pane.tag_lead = lead; + } const lines = std.mem.count(u8, tagline.curTail(pane), "\n") + 1; pane.tag_rows = @intCast(@min(lines, MAX_TAG_ROWS, @max(BOX_H, r.h -| 1))); if (pane.collapsed) pane.tag_rows = BOX_H; |
