refactor: add Cursor.from_pos and Seleciton.from_range
And use them to clean-up all root.pos_to_width call sites.
This commit is contained in:
parent
be41027d75
commit
4a0150d68f
3 changed files with 80 additions and 68 deletions
|
|
@ -42,6 +42,13 @@ fn follow_target(self: *Self, root: Buffer.Root, metrics: Metrics) void {
|
||||||
self.col = @min(self.target, root.line_width(self.row, metrics) catch 0);
|
self.col = @min(self.target, root.line_width(self.row, metrics) catch 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_pos(self: Self, root: Buffer.Root, metrics: Buffer.Metrics) Self {
|
||||||
|
return .{
|
||||||
|
.row = self.row,
|
||||||
|
.col = root.pos_to_width(self.row, self.col, metrics) catch root.line_width(self.row, metrics) catch 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn move_right_no_target(self: *Self, root: Buffer.Root, metrics: Metrics) !void {
|
fn move_right_no_target(self: *Self, root: Buffer.Root, metrics: Metrics) !void {
|
||||||
const lines = root.lines();
|
const lines = root.lines();
|
||||||
if (lines <= self.row) return error.Stop;
|
if (lines <= self.row) return error.Stop;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,17 @@ pub fn from_pos(sel: Self, root: Buffer.Root, metrics: Buffer.Metrics) Self {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_range(range: anytype, root: Buffer.Root, metrics: Buffer.Metrics) Self {
|
||||||
|
return from_pos(from_range_raw(range), root, metrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_range_raw(range: anytype) Self {
|
||||||
|
return .{
|
||||||
|
.begin = .{ .row = range.start_point.row, .col = range.start_point.column },
|
||||||
|
.end = .{ .row = range.end_point.row, .col = range.end_point.column },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn line_from_cursor(cursor: Cursor, root: Buffer.Root, mtrx: Buffer.Metrics) Self {
|
pub fn line_from_cursor(cursor: Cursor, root: Buffer.Root, mtrx: Buffer.Metrics) Self {
|
||||||
var begin = cursor;
|
var begin = cursor;
|
||||||
var end = cursor;
|
var end = cursor;
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@ pub const Match = struct {
|
||||||
return .{ .begin = self.begin, .end = self.end };
|
return .{ .begin = self.begin, .end = self.end };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_pos(self: Self, root: Buffer.Root, metrics: Buffer.Metrics) error{NotFound}!Self {
|
pub fn from_pos(self: Self, root: Buffer.Root, metrics: Buffer.Metrics) Self {
|
||||||
return from_selection(try self.to_selection().from_pos(root, metrics));
|
return from_selection(self.to_selection().from_pos(root, metrics));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nudge_insert(self: *Self, nudge: Selection) void {
|
fn nudge_insert(self: *Self, nudge: Selection) void {
|
||||||
|
|
@ -1442,7 +1442,7 @@ pub const Editor = struct {
|
||||||
pos_cache: PosToWidthCache,
|
pos_cache: PosToWidthCache,
|
||||||
last_begin: Cursor = Cursor.invalid(),
|
last_begin: Cursor = Cursor.invalid(),
|
||||||
fn cb(ctx: *@This(), range: syntax.Range, scope: []const u8, id: u32, idx: usize, _: *const syntax.Node) error{Stop}!void {
|
fn cb(ctx: *@This(), range: syntax.Range, scope: []const u8, id: u32, idx: usize, _: *const syntax.Node) error{Stop}!void {
|
||||||
const sel_ = ctx.pos_cache.range_to_selection(range, ctx.root, ctx.self.metrics) orelse return;
|
const sel_ = ctx.pos_cache.range_to_selection(range, ctx.root, ctx.self.metrics);
|
||||||
|
|
||||||
if (idx > 0) return;
|
if (idx > 0) return;
|
||||||
if (sel_.begin.eql(ctx.last_begin)) return;
|
if (sel_.begin.eql(ctx.last_begin)) return;
|
||||||
|
|
@ -5420,13 +5420,14 @@ pub const Editor = struct {
|
||||||
self.need_render();
|
self.need_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_match_internal(self: *Self, begin_line_: usize, begin_pos_: usize, end_line_: usize, end_pos_: usize) void {
|
fn add_match_internal(self: *Self, begin_line: usize, begin_pos: usize, end_line: usize, end_pos: usize) void {
|
||||||
const root = self.buf_root() catch return;
|
const root = self.buf_root() catch return;
|
||||||
const begin_line = begin_line_ - 1;
|
const begin: Cursor = .{ .row = begin_line - 1, .col = begin_pos };
|
||||||
const end_line = end_line_ - 1;
|
const end: Cursor = .{ .row = end_line - 1, .col = end_pos };
|
||||||
const begin_pos = root.pos_to_width(begin_line, begin_pos_, self.metrics) catch return;
|
var match: Match = .{
|
||||||
const end_pos = root.pos_to_width(end_line, end_pos_, self.metrics) catch return;
|
.begin = begin.from_pos(root, self.metrics),
|
||||||
var match: Match = .{ .begin = .{ .row = begin_line, .col = begin_pos }, .end = .{ .row = end_line, .col = end_pos } };
|
.end = end.from_pos(root, self.metrics),
|
||||||
|
};
|
||||||
if (match.end.eql(self.get_primary().cursor))
|
if (match.end.eql(self.get_primary().cursor))
|
||||||
match.has_selection = true;
|
match.has_selection = true;
|
||||||
(self.matches.addOne(self.allocator) catch return).* = match;
|
(self.matches.addOne(self.allocator) catch return).* = match;
|
||||||
|
|
@ -5631,72 +5632,73 @@ pub const Editor = struct {
|
||||||
pub const goto_line_vim_meta: Meta = .{ .arguments = &.{.integer} };
|
pub const goto_line_vim_meta: Meta = .{ .arguments = &.{.integer} };
|
||||||
|
|
||||||
pub fn goto_column(self: *Self, ctx: Context) Result {
|
pub fn goto_column(self: *Self, ctx: Context) Result {
|
||||||
var column: usize = 0;
|
|
||||||
if (!try ctx.args.match(.{tp.extract(&column)}))
|
|
||||||
return error.InvalidGotoColumnArgument;
|
|
||||||
const root = self.buf_root() catch return;
|
const root = self.buf_root() catch return;
|
||||||
const primary = self.get_primary();
|
const primary = self.get_primary();
|
||||||
column = if (column < 1) 0 else column - 1;
|
var dest = primary.cursor;
|
||||||
column = try root.pos_to_width(primary.cursor.row, column, self.metrics);
|
if (!try ctx.args.match(.{tp.extract(&dest.col)}))
|
||||||
try primary.cursor.move_to(root, primary.cursor.row, column, self.metrics);
|
return error.InvalidGotoColumnArgument;
|
||||||
|
dest.col -|= 1;
|
||||||
|
dest = dest.from_pos(root, self.metrics);
|
||||||
|
try primary.cursor.move_to(root, dest.row, dest.col, self.metrics);
|
||||||
self.clamp();
|
self.clamp();
|
||||||
}
|
}
|
||||||
pub const goto_column_meta: Meta = .{ .arguments = &.{.integer} };
|
pub const goto_column_meta: Meta = .{ .arguments = &.{.integer} };
|
||||||
|
|
||||||
pub fn goto_line_and_column(self: *Self, ctx: Context) Result {
|
pub fn goto_line_and_column(self: *Self, ctx: Context) Result {
|
||||||
try self.send_editor_jump_source();
|
try self.send_editor_jump_source();
|
||||||
var line: usize = 0;
|
var dest: Cursor = .{};
|
||||||
var column: usize = 0;
|
|
||||||
var have_sel: bool = false;
|
var have_sel: bool = false;
|
||||||
var sel: Selection = .{};
|
var sel: Selection = .{};
|
||||||
var pos_type: PosType = .column;
|
var pos_type: PosType = .column;
|
||||||
if (try ctx.args.match(.{
|
if (try ctx.args.match(.{
|
||||||
tp.extract(&line),
|
tp.extract(&dest.row),
|
||||||
tp.extract(&column),
|
tp.extract(&dest.col),
|
||||||
})) {
|
})) {
|
||||||
// self.logger.print("goto: l:{d} c:{d}", .{ line, column });
|
// self.logger.print("goto: l:{d} c:{d}", .{ dest.row, dest.col });
|
||||||
} else if (try ctx.args.match(.{
|
} else if (try ctx.args.match(.{
|
||||||
tp.extract(&line),
|
tp.extract(&dest.row),
|
||||||
tp.extract(&column),
|
tp.extract(&dest.col),
|
||||||
tp.extract(&pos_type),
|
tp.extract(&pos_type),
|
||||||
})) {
|
})) {
|
||||||
// self.logger.print("goto: l:{d} c:{d}", .{ line, column });
|
// self.logger.print("goto: l:{d} c:{d}", .{ dest.row, dest.col });
|
||||||
} else if (try ctx.args.match(.{
|
} else if (try ctx.args.match(.{
|
||||||
tp.extract(&line),
|
tp.extract(&dest.row),
|
||||||
tp.extract(&column),
|
tp.extract(&dest.col),
|
||||||
tp.extract(&sel.begin.row),
|
tp.extract(&sel.begin.row),
|
||||||
tp.extract(&sel.begin.col),
|
tp.extract(&sel.begin.col),
|
||||||
tp.extract(&sel.end.row),
|
tp.extract(&sel.end.row),
|
||||||
tp.extract(&sel.end.col),
|
tp.extract(&sel.end.col),
|
||||||
})) {
|
})) {
|
||||||
// self.logger.print("goto: l:{d} c:{d} {any}", .{ line, column, sel });
|
// self.logger.print("goto: l:{d} c:{d} {any}", .{ dest.row, dest.col, sel });
|
||||||
have_sel = true;
|
have_sel = true;
|
||||||
} else if (try ctx.args.match(.{
|
} else if (try ctx.args.match(.{
|
||||||
tp.extract(&line),
|
tp.extract(&dest.row),
|
||||||
tp.extract(&column),
|
tp.extract(&dest.col),
|
||||||
tp.extract(&sel.begin.row),
|
tp.extract(&sel.begin.row),
|
||||||
tp.extract(&sel.begin.col),
|
tp.extract(&sel.begin.col),
|
||||||
tp.extract(&sel.end.row),
|
tp.extract(&sel.end.row),
|
||||||
tp.extract(&sel.end.col),
|
tp.extract(&sel.end.col),
|
||||||
tp.extract(&pos_type),
|
tp.extract(&pos_type),
|
||||||
})) {
|
})) {
|
||||||
// self.logger.print("goto: l:{d} c:{d} {any} {}", .{ line, column, sel, pos_type });
|
// self.logger.print("goto: l:{d} c:{d} {any} {}", .{ dest.row, dest.col, sel, pos_type });
|
||||||
have_sel = true;
|
have_sel = true;
|
||||||
} else return error.InvalidGotoLineAndColumnArgument;
|
} else return error.InvalidGotoLineAndColumnArgument;
|
||||||
self.cancel_all_selections();
|
self.cancel_all_selections();
|
||||||
const root = self.buf_root() catch return;
|
const root = self.buf_root() catch return;
|
||||||
if (pos_type == .byte) {
|
if (pos_type == .byte) {
|
||||||
column = root.pos_to_width(line - 1, column - 1, self.metrics) catch return;
|
dest.row -|= 1;
|
||||||
column += 1;
|
dest.col -|= 1;
|
||||||
|
dest = dest.from_pos(root, self.metrics);
|
||||||
|
dest.col += 1;
|
||||||
if (have_sel)
|
if (have_sel)
|
||||||
sel = sel.from_pos(root, self.metrics) catch return;
|
sel = sel.from_pos(root, self.metrics);
|
||||||
// self.logger.print("goto_byte_pos: l:{d} c:{d} {any} {}", .{ line, column, sel, pos_type });
|
// self.logger.print("goto_byte_pos: l:{d} c:{d} {any} {}", .{ dest.row, dest.col, sel, pos_type });
|
||||||
}
|
}
|
||||||
const primary = self.get_primary();
|
const primary = self.get_primary();
|
||||||
try primary.cursor.move_to(
|
try primary.cursor.move_to(
|
||||||
root,
|
root,
|
||||||
@intCast(if (line < 1) 0 else line - 1),
|
dest.row -| 1,
|
||||||
@intCast(if (column < 1) 0 else column - 1),
|
dest.col -| 1,
|
||||||
self.metrics,
|
self.metrics,
|
||||||
);
|
);
|
||||||
if (have_sel) primary.selection = sel;
|
if (have_sel) primary.selection = sel;
|
||||||
|
|
@ -5918,23 +5920,10 @@ pub const Editor = struct {
|
||||||
|
|
||||||
pub fn add_hover_highlight(self: *Self, match_: Match) void {
|
pub fn add_hover_highlight(self: *Self, match_: Match) void {
|
||||||
const root = self.buf_root() catch return;
|
const root = self.buf_root() catch return;
|
||||||
const match: Match = .{
|
const match = match_.from_pos(root, self.metrics);
|
||||||
.begin = .{
|
|
||||||
.row = match_.begin.row,
|
|
||||||
.col = root.pos_to_width(match_.begin.row, match_.begin.col, self.metrics) catch return,
|
|
||||||
},
|
|
||||||
.end = .{
|
|
||||||
.row = match_.end.row,
|
|
||||||
.col = root.pos_to_width(match_.end.row, match_.end.col, self.metrics) catch return,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
switch (self.matches.items.len) {
|
switch (self.matches.items.len) {
|
||||||
0 => {
|
0 => (self.matches.addOne(self.allocator) catch return).* = match,
|
||||||
(self.matches.addOne(self.allocator) catch return).* = match;
|
1 => self.matches.items[0] = match,
|
||||||
},
|
|
||||||
1 => {
|
|
||||||
self.matches.items[0] = match;
|
|
||||||
},
|
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
self.need_render();
|
self.need_render();
|
||||||
|
|
@ -5954,14 +5943,11 @@ pub const Editor = struct {
|
||||||
self.cancel_all_matches();
|
self.cancel_all_matches();
|
||||||
}
|
}
|
||||||
const root = self.buf_root() catch return;
|
const root = self.buf_root() catch return;
|
||||||
const begin_row = match_.begin.row - @min(match_.begin.row, 1);
|
var match = match_;
|
||||||
const begin_col = root.pos_to_width(begin_row, match_.begin.col, self.metrics) catch return;
|
match.begin.row -|= 1;
|
||||||
const end_row = match_.end.row - @min(match_.end.row, 1);
|
match.end.row -|= 1;
|
||||||
const end_col = root.pos_to_width(end_row, match_.end.col, self.metrics) catch return;
|
match = match.from_pos(root, self.metrics);
|
||||||
(self.matches.addOne(self.allocator) catch return).* = .{
|
(self.matches.addOne(self.allocator) catch return).* = match;
|
||||||
.begin = .{ .row = begin_row, .col = begin_col },
|
|
||||||
.end = .{ .row = end_row, .col = end_col },
|
|
||||||
};
|
|
||||||
self.need_render();
|
self.need_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6696,18 +6682,26 @@ pub const PosToWidthCache = struct {
|
||||||
self.cache.deinit(self.allocator);
|
self.cache.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn range_to_selection(self: *Self, range: syntax.Range, root: Buffer.Root, metrics: Buffer.Metrics) ?Selection {
|
pub fn range_to_selection(self: *Self, range: syntax.Range, root: Buffer.Root, metrics: Buffer.Metrics) Selection {
|
||||||
const start = range.start_point;
|
var sel = Selection.from_range_raw(range);
|
||||||
const end = range.end_point;
|
if (root != self.cached_root or self.cached_line != sel.begin.row) {
|
||||||
if (root != self.cached_root or self.cached_line != start.row) {
|
|
||||||
self.cache.clearRetainingCapacity();
|
self.cache.clearRetainingCapacity();
|
||||||
self.cached_line = start.row;
|
self.cached_line = sel.begin.row;
|
||||||
self.cached_root = root;
|
self.cached_root = root;
|
||||||
root.get_line_width_map(self.cached_line, &self.cache, self.allocator, metrics) catch return null;
|
root.get_line_width_map(self.cached_line, &self.cache, self.allocator, metrics) catch return sel;
|
||||||
}
|
}
|
||||||
const start_col = if (start.column < self.cache.items.len) self.cache.items[start.column] else start.column;
|
|
||||||
const end_col = if (end.row == start.row and end.column < self.cache.items.len) self.cache.items[end.column] else root.pos_to_width(end.row, end.column, metrics) catch end.column;
|
sel.begin.col = if (sel.begin.col < self.cache.items.len)
|
||||||
return .{ .begin = .{ .row = start.row, .col = start_col }, .end = .{ .row = end.row, .col = end_col } };
|
self.cache.items[sel.begin.col]
|
||||||
|
else
|
||||||
|
sel.begin.col;
|
||||||
|
|
||||||
|
sel.end.col = if (sel.end.row == sel.end.row and sel.end.col < self.cache.items.len)
|
||||||
|
self.cache.items[sel.end.col]
|
||||||
|
else
|
||||||
|
root.pos_to_width(sel.end.row, sel.end.col, metrics) catch sel.end.col;
|
||||||
|
|
||||||
|
return sel;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue