summaryrefslogtreecommitdiff
path: root/src/edit.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/edit.zig')
-rw-r--r--src/edit.zig51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/edit.zig b/src/edit.zig
index 09c3ffe7..2dc79ab5 100644
--- a/src/edit.zig
+++ b/src/edit.zig
@@ -1292,6 +1292,57 @@ pub fn normalJoin(p: *Pardes, t: *Text, select_space: bool) void {
t.setRanges(t2, rs[0..n], &.{}, pri, expl);
}
+/// `Alt-)` / `Alt-(`: rotate the TEXT of the selections forward / back by
+/// one range (count ranges), in one edit (helix reorder_selection_contents).
+/// Each range comes back over the text it now holds, in its own direction,
+/// and the primary moves with the text it had.
+pub fn normalRotateContents(p: *Pardes, t: *Text, forward: bool, cnt: usize) void {
+ const expl = (t.vsel.active and t.vsel.explicit) or t.msel.active;
+ var b = selRows(t);
+ for (t.sels[0..t.nsel]) |s| {
+ b.lo_row = @min(b.lo_row, @min(s.row, s.arow));
+ b.hi_row = @max(b.hi_row, @max(s.row, s.arow));
+ }
+ const eb = editTextEol(p, t, b) orelse return;
+ const text = eb.text;
+ var rs: [Text.max_selections]modal.Selection = undefined;
+ const got = t.ranges(text, eb.row0, &rs);
+ const n = got.n;
+ if (n < 2) return;
+ const by = @min(cnt, n);
+ var chs: [Text.max_selections]TextChange = undefined;
+ for (rs[0..n], 0..) |r, i| {
+ const src = rs[if (forward) (i + n - by) % n else (i + by) % n];
+ chs[i] = .{
+ .from = @min(r.anchor, r.head),
+ .to = @max(r.anchor, r.head),
+ .ins = text[@min(src.anchor, src.head)..@max(src.anchor, src.head)],
+ };
+ }
+ pushUndo(p, t);
+ const new = applyChanges(p, text, chs[0..n]) catch return;
+ var cells: [Text.max_selections]Text.SelRange = undefined;
+ var delta: i64 = 0;
+ for (chs[0..n], rs[0..n], 0..) |ch, r, i| {
+ const from: usize = @intCast(@as(i64, @intCast(ch.from)) + delta);
+ delta += @as(i64, @intCast(ch.ins.len)) - @as(i64, @intCast(ch.to - ch.from));
+ const to = from + ch.ins.len;
+ const c = Text.rangeCells(new, if (r.anchor > r.head) .{ .anchor = to, .head = from } else .{ .anchor = from, .head = to });
+ const cc = modal.positionAt(new, c.cur);
+ const ac = modal.positionAt(new, c.anc);
+ cells[i] = .{
+ .row = @as(i32, @intCast(cc.row)) + eb.row0,
+ .col = @intCast(cc.col),
+ .arow = @as(i32, @intCast(ac.row)) + eb.row0,
+ .acol = @intCast(ac.col),
+ };
+ }
+ setEditText(p, t, new);
+ const t2 = flatSurface(p, t) catch return;
+ for (cells[0..n], 0..) |s, i| rs[i] = Text.cellRange(t2, s.arow, s.acol, s.row, s.col);
+ t.setRanges(t2, rs[0..n], &.{}, if (forward) (got.pri + by) % n else (got.pri + n - by) % n, expl);
+}
+
pub fn normalIndent(p: *Pardes, t: *Text, cnt: usize, add: bool) void {
t.select = false;
const sr = selRows(t);