summaryrefslogtreecommitdiff
path: root/src/pardes.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/pardes.zig')
-rw-r--r--src/pardes.zig35
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;