summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Terminal.zig6
-rw-r--r--src/Text.zig3
-rw-r--r--src/config.zig1
-rw-r--r--src/edit.zig7
-rw-r--r--src/modal.zig3
-rw-r--r--src/normal.zig4
6 files changed, 23 insertions, 1 deletions
diff --git a/src/Terminal.zig b/src/Terminal.zig
index 1ff561b1..4c29e151 100644
--- a/src/Terminal.zig
+++ b/src/Terminal.zig
@@ -720,7 +720,7 @@ pub fn feedOutput(p: *Pardes, pane: *Pane, bytes: []const u8) void {
if (comptime !enabled) return;
if (pane.terminal == null) return;
const has_positions = pane.ovl != null or pane.body.cur_pinned or pane.body.vsel.active or
- pane.body.msel.active or pane.body.nsel > 0 or pane.look_at != null or
+ pane.body.msel.active or pane.body.nsel > 0 or pane.body.last_edit != null or pane.look_at != null or
pane.body.ed_undo_len > 0 or pane.body.ed_redo_len > 0 or pointerRowCount(pane) > 0;
// Sticky bottom, as every other terminal does it: output drags the
// viewport down only when the viewport was already on the last row, so
@@ -846,6 +846,10 @@ fn ingestWithPositions(pane: *Pane, bytes: []const u8) void {
extra[nextra + 1] = &selection.arow;
nextra += 2;
}
+ if (pane.body.last_edit) |*at| {
+ extra[nextra] = &at.row;
+ nextra += 1;
+ }
if (pane.look_at) |*at| {
extra[nextra] = &at.row;
nextra += 1;
diff --git a/src/Text.zig b/src/Text.zig
index 411c2ec8..70ec5369 100644
--- a/src/Text.zig
+++ b/src/Text.zig
@@ -69,6 +69,9 @@ sticky_col: i32 = -1,
/// The insert session began with `a`: on Esc every range gives back the
/// one character it was stretched by (helix restore_cursor).
restore_cursor: bool = false,
+/// Where the last edit ended, a deletion's start or an insertion's end, in
+/// surface rows: for `g.` (helix last_edit_pos).
+last_edit: ?struct { row: i32, col: i32 } = null,
/// insert `Ctrl-r` was pressed: the next key names the register to insert
reg_wait: bool = false,
normal: modal.Normal.State = .{},
diff --git a/src/config.zig b/src/config.zig
index 959f4c4a..993b6fe0 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -487,6 +487,7 @@ pub const goto_column: []const Chord = &.{.{ .cp = '|' }};
pub const goto_view_top: []const Chord = &.{.{ .cp = 't' }};
pub const goto_view_center: []const Chord = &.{.{ .cp = 'c' }};
pub const goto_view_bottom: []const Chord = &.{.{ .cp = 'b' }};
+pub const goto_last_modification: []const Chord = &.{.{ .cp = '.' }};
pub const goto_definition: []const Chord = &.{.{ .cp = 'd' }};
pub const goto_declaration: []const Chord = &.{.{ .cp = 'D' }};
pub const goto_type_definition: []const Chord = &.{.{ .cp = 'y' }};
diff --git a/src/edit.zig b/src/edit.zig
index 5e0d20a4..9398674a 100644
--- a/src/edit.zig
+++ b/src/edit.zig
@@ -484,6 +484,13 @@ pub fn setEditText(p: *Pardes, t: *Text, new: []u8) void {
return;
}
const pane = t.pane() orelse return retireEditText(p, new);
+ // what changed ended where the texts agree again from their ends
+ const old: []const u8, const row0: i32 = if (pane.file) |f| .{ f.content, 0 } else if (pane.ovl) |o| .{ o.text, o.row } else .{ "", 0 };
+ const front = std.mem.indexOfDiff(u8, old, new) orelse @min(old.len, new.len);
+ var back: usize = 0;
+ while (back < @min(old.len, new.len) - front and old[old.len - 1 - back] == new[new.len - 1 - back]) back += 1;
+ const end = modal.positionAt(new, new.len - back);
+ t.last_edit = .{ .row = @as(i32, @intCast(end.row)) + row0, .col = @intCast(end.col) };
if (pane.file) |*f| return panes.File.setContent(p, f, new);
panes.Terminal.setEditText(p, pane, new);
}
diff --git a/src/modal.zig b/src/modal.zig
index ae008f60..0171da93 100644
--- a/src/modal.zig
+++ b/src/modal.zig
@@ -28,6 +28,7 @@ pub const Normal = struct {
goto_view_top,
goto_view_center,
goto_view_bottom,
+ goto_last_modification,
goto_definition,
goto_declaration,
goto_type_definition,
@@ -251,6 +252,7 @@ pub const Normal = struct {
view_top,
view_center,
view_bottom,
+ last_modification,
};
pub const View = enum { top, center, bottom, scroll_down, scroll_up };
pub const Find = enum { forward, backward, till_forward, till_backward };
@@ -437,6 +439,7 @@ pub const Normal = struct {
if (key.has(.goto_view_top)) return resultAction(.{ .goto = .{ .target = .view_top, .count = count, .explicit_count = counted.explicit } });
if (key.has(.goto_view_center)) return resultAction(.{ .goto = .{ .target = .view_center, .count = count, .explicit_count = counted.explicit } });
if (key.has(.goto_view_bottom)) return resultAction(.{ .goto = .{ .target = .view_bottom, .count = count, .explicit_count = counted.explicit } });
+ if (key.has(.goto_last_modification)) return resultAction(.{ .goto = .{ .target = .last_modification, .count = count, .explicit_count = counted.explicit } });
if (key.has(.goto_definition)) return resultAction(.{ .lsp = .definition });
if (key.has(.goto_declaration)) return resultAction(.{ .lsp = .declaration });
if (key.has(.goto_type_definition)) return resultAction(.{ .lsp = .type_definition });
diff --git a/src/normal.zig b/src/normal.zig
index bc450581..228c9c39 100644
--- a/src/normal.zig
+++ b/src/normal.zig
@@ -460,6 +460,10 @@ fn executeNormalAction(p: *Pardes, t: *Text, semantic: modal.Normal.Action) void
.view_top => return t.gotoWindow(text, range, .top, go.count),
.view_center => return t.gotoWindow(text, range, .center, go.count),
.view_bottom => return t.gotoWindow(text, range, .bottom, go.count),
+ .last_modification => {
+ const at = t.last_edit orelse return;
+ return t.pointMove(text, range, modal.offsetAt(text, .{ .row = @intCast(@max(0, at.row)), .col = @intCast(@max(0, at.col)) }));
+ },
},
.view => |view| if (t.what == .body) switch (view) {
.top => {