summaryrefslogtreecommitdiff
path: root/src/normal.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/normal.zig')
-rw-r--r--src/normal.zig42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/normal.zig b/src/normal.zig
index 53e416fd..542c9fb3 100644
--- a/src/normal.zig
+++ b/src/normal.zig
@@ -18,6 +18,7 @@ const Key = pardes.Key;
const hit = pardes.hit;
const sel_slot = pardes.sel_slot;
const Pardes = pardes.Pardes;
+const Macro = pardes.Macro;
fn isPrefix(key: Key, cp: u21) bool {
return key.cp == cp and !key.ctrl and !key.alt;
@@ -324,6 +325,8 @@ fn executeNormalAction(p: *Pardes, t: *Text, semantic: modal.Normal.Action) void
switch (semantic) {
.escape => {
t.select = false;
+ // typed again by a macro, Esc is only helix's
+ if (p.macro.replaying > 0) return;
return exec.runBuiltin(p, .Last, p.active, "", null);
},
.goto => |go| switch (go.target) {
@@ -571,7 +574,7 @@ fn executeNormalAction(p: *Pardes, t: *Text, semantic: modal.Normal.Action) void
.format => .format,
}, ""),
.adjust_number => |delta| return edit.normalAdjustNumber(p, t, delta),
- .leader => {
+ .leader => if (p.macro.replaying == 0) {
p.leader_on = true;
p.leader_n = 0;
},
@@ -588,6 +591,43 @@ fn executeNormalAction(p: *Pardes, t: *Text, semantic: modal.Normal.Action) void
p,
if (direction == .forward) @as(i32, 1) else -1,
),
+ .macro_record => {
+ const m = &p.macro;
+ if (m.recording == 0) {
+ m.recording = if (p.register != 0) p.register else '@';
+ m.recorded.clearRetainingCapacity();
+ return;
+ }
+ // the keys of this command (a count, `"<reg>`, the `Q`) are not
+ // the macro's
+ m.recorded.shrinkRetainingCapacity(m.recorded.items.len -| (m.command.items.len + 1));
+ const keys = Macro.encode(p.gpa, m.recorded.items) catch return;
+ defer p.gpa.free(keys);
+ p.registers.put(p.gpa, m.recording, keys, 0, 1, true);
+ m.recording = 0;
+ },
+ .macro_replay => |count| {
+ const name: u21 = if (p.register != 0) p.register else '@';
+ const notation = p.registers.value(name, 0) orelse return;
+ const keys = Macro.decode(p.scratch.allocator(), notation) catch return;
+ p.register = 0;
+ for (0..count) |_| p.replayKeys(keys);
+ },
+ .repeat_insert => |count| {
+ const m = &p.macro;
+ if (m.last_insert.items.len == 0 or m.repeating) return;
+ if (m.inserting) return; // the session is still open
+ const keys = p.scratch.allocator().dupe(Macro.Stored, m.last_insert.items) catch return;
+ m.repeating = true;
+ defer m.repeating = false;
+ // helix repeat_last_insert: the command once, what was typed
+ // count times, and out of insert mode the way it was left
+ const typed = @min(m.typed_from, keys.len);
+ p.replayKeys(keys[0..typed]);
+ if (keys.len == typed) return;
+ for (0..count) |_| p.replayKeys(keys[typed .. keys.len - 1]);
+ p.replayKeys(keys[keys.len - 1 ..]);
+ },
}
}