Compare commits

...

9 commits

Author SHA1 Message Date
563eb57e44
refactor: move cut_to helix workaround to a helix specific command 2025-04-03 06:37:29 +02:00
62c6313107
refactor: mark more editor functions as public 2025-04-03 06:29:31 +02:00
Levi Santos
0babbb1833 fix(helix): Making d and c work as expected in normal mode 2025-04-03 06:16:13 +02:00
ivel.santos
e669849629 Helix mode: find_file 2025-04-03 06:13:05 +02:00
ivel.santos
d2d6508ed8 Helix mode: move_cursor_word_left 2025-04-03 06:13:05 +02:00
ivel.santos
bef8549afa Helix mode: move_next_word 2025-04-03 06:13:05 +02:00
Levi Santos
d8553dd9d7 Helix mode: move_to_char 2025-04-03 06:13:05 +02:00
Levi Santos
b5a57e0901 Helix mode: adding file_picker_in_current_directory 2025-04-03 06:13:05 +02:00
Levi Santos
b850befc5d Helix mode: adding extend_line_below 2025-04-03 06:13:05 +02:00
3 changed files with 110 additions and 22 deletions

View file

@ -62,7 +62,7 @@
["shift+`", "switch_case"],
["shift+t", "till_prev_char"],
["shift+f", "move_to_char", false],
["shift+f", "move_to_char", "left"],
["shift+w", "move_next_long_word_start"],
["shift+b", "move_prev_long_word_start"],
["shift+e", "move_next_long_word_end"],
@ -107,7 +107,7 @@
["l", "move_right"],
["t", "find_till_char"],
["f", "move_to_char", true],
["f", "move_to_char", "right"],
["`", "to_lower"],
@ -146,8 +146,8 @@
["a", ["move_right"], ["enter_mode", "insert"]],
["o", ["smart_insert_line_after"], ["enter_mode", "insert"]],
["d", "cut"],
["c", ["cut"], ["enter_mode", "insert"]],
["d", "cut_forward_internal_inclusive"],
["c", ["cut_forward_internal_inclusive"], ["enter_mode", "insert"]],
["s", "select_regex"],
[";", "collapse_selections"],
@ -204,13 +204,13 @@
["page_up", "move_scroll_page_up"],
["page_down", "move_scroll_page_down"],
["space shift+f", "file_picker_in_current_directory"],
["space shift+f", "find_file"],
["space shift+s", "workspace_symbol_picker"],
["space shift+d", "workspace_diagnostics_picker"],
["space shift+p", "system_paste"],
["space shift+r", "replace_selections_with_clipboard"],
["space shift+/", "open_command_palette"],
["space f", "file_picker"],
["space f", "find_file"],
["space b", "buffer_picker"],
["space j", "jumplist_picker"],
["space s", "symbol_picker"],

View file

@ -103,7 +103,7 @@ pub const CurSel = struct {
};
}
fn enable_selection_normal(self: *Self) *Selection {
pub fn enable_selection_normal(self: *Self) *Selection {
return if (self.selection) |*sel|
sel
else cod: {
@ -493,7 +493,7 @@ pub const Editor = struct {
Widget.need_render();
}
fn buf_for_update(self: *Self) !*const Buffer {
pub fn buf_for_update(self: *Self) !*const Buffer {
if (!self.pause_undo) {
self.cursels_saved.clearAndFree();
self.cursels_saved = try self.cursels.clone();
@ -501,7 +501,7 @@ pub const Editor = struct {
return self.buffer orelse error.Stop;
}
fn buf_root(self: *const Self) !Buffer.Root {
pub fn buf_root(self: *const Self) !Buffer.Root {
return if (self.buffer) |p| p.root else error.Stop;
}
@ -709,7 +709,7 @@ pub const Editor = struct {
return meta.toOwnedSlice();
}
fn update_buf(self: *Self, root: Buffer.Root) !void {
pub fn update_buf(self: *Self, root: Buffer.Root) !void {
const b = self.buffer orelse return error.Stop;
return self.update_buf_and_eol_mode(root, b.file_eol_mode, b.file_utf8_sanitized);
}
@ -1649,7 +1649,7 @@ pub const Editor = struct {
self.view.col = dest.col;
}
inline fn clamp(self: *Self) void {
pub inline fn clamp(self: *Self) void {
self.clamp_abs(false);
}
@ -1775,7 +1775,7 @@ pub const Editor = struct {
cursel.check_selection(root, metrics);
}
fn with_selections_const(self: *Self, root: Buffer.Root, move: cursor_operator_const) error{Stop}!void {
pub fn with_selections_const(self: *Self, root: Buffer.Root, move: cursor_operator_const) error{Stop}!void {
var someone_stopped = false;
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel|
with_selection_const(root, move, cursel, self.metrics) catch {
@ -1921,7 +1921,7 @@ pub const Editor = struct {
const cursel_operator = *const fn (root: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root;
const cursel_operator_mut = *const fn (self: *Self, root: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root;
fn is_not_word_char(c: []const u8) bool {
pub fn is_not_word_char(c: []const u8) bool {
if (c.len == 0) return true;
return switch (c[0]) {
' ' => true,
@ -1962,7 +1962,7 @@ pub const Editor = struct {
return cursor.test_at(root, is_word_char, metrics);
}
fn is_non_word_char_at_cursor(root: Buffer.Root, cursor: *const Cursor, metrics: Buffer.Metrics) bool {
pub fn is_non_word_char_at_cursor(root: Buffer.Root, cursor: *const Cursor, metrics: Buffer.Metrics) bool {
return cursor.test_at(root, is_not_word_char, metrics);
}
@ -1986,7 +1986,7 @@ pub const Editor = struct {
return is_whitespace(c) or c[0] == '\n';
}
fn is_whitespace_at_cursor(root: Buffer.Root, cursor: *const Cursor, metrics: Buffer.Metrics) bool {
pub fn is_whitespace_at_cursor(root: Buffer.Root, cursor: *const Cursor, metrics: Buffer.Metrics) bool {
return cursor.test_at(root, is_whitespace, metrics);
}
@ -1994,7 +1994,7 @@ pub const Editor = struct {
return !cursor.test_at(root, is_whitespace_or_eol, metrics);
}
fn is_word_boundary_left_vim(root: Buffer.Root, cursor: *const Cursor, metrics: Buffer.Metrics) bool {
pub fn is_word_boundary_left_vim(root: Buffer.Root, cursor: *const Cursor, metrics: Buffer.Metrics) bool {
if (is_whitespace_at_cursor(root, cursor, metrics)) return false;
var next = cursor.*;
next.move_left(root, metrics) catch return true;
@ -2087,11 +2087,11 @@ pub const Editor = struct {
return false;
}
fn move_cursor_left(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
pub fn move_cursor_left(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
try cursor.move_left(root, metrics);
}
fn move_cursor_left_until(root: Buffer.Root, cursor: *Cursor, pred: cursor_predicate, metrics: Buffer.Metrics) void {
pub fn move_cursor_left_until(root: Buffer.Root, cursor: *Cursor, pred: cursor_predicate, metrics: Buffer.Metrics) void {
while (!pred(root, cursor, metrics))
move_cursor_left(root, cursor, metrics) catch return;
}
@ -2101,7 +2101,7 @@ pub const Editor = struct {
move_cursor_left(root, cursor, metrics) catch return;
}
fn move_cursor_begin(_: Buffer.Root, cursor: *Cursor, _: Buffer.Metrics) !void {
pub fn move_cursor_begin(_: Buffer.Root, cursor: *Cursor, _: Buffer.Metrics) !void {
cursor.move_begin();
}
@ -2124,7 +2124,7 @@ pub const Editor = struct {
move_cursor_right(root, cursor, metrics) catch return;
}
fn move_cursor_end(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) !void {
pub fn move_cursor_end(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) !void {
cursor.move_end(root, metrics);
}
@ -2413,7 +2413,7 @@ pub const Editor = struct {
}
}
fn set_clipboard_internal(self: *Self, text: []const u8) void {
pub fn set_clipboard_internal(self: *Self, text: []const u8) void {
if (self.clipboard) |old|
self.allocator.free(old);
self.clipboard = text;
@ -2476,7 +2476,7 @@ pub const Editor = struct {
return root_;
}
fn cut_to(self: *Self, move: cursor_operator_const, root_: Buffer.Root) !struct { []const u8, Buffer.Root } {
pub fn cut_to(self: *Self, move: cursor_operator_const, root_: Buffer.Root) !struct { []const u8, Buffer.Root } {
var all_stop = true;
var root = root_;

View file

@ -5,6 +5,9 @@ const command = @import("command");
const cmd = command.executeName;
const tui = @import("../tui.zig");
const Editor = @import("../editor.zig").Editor;
const Buffer = @import("Buffer");
const Cursor = Buffer.Cursor;
var commands: Commands = undefined;
@ -72,4 +75,89 @@ const cmds_ = struct {
}, sel);
}
pub const save_selection_meta: Meta = .{ .description = "Save current selection to location history" };
pub fn extend_line_below(_: *void, _: Ctx) Result {
const mv = tui.mainview() orelse return;
const ed = mv.get_active_editor() orelse return;
const root = try ed.buf_root();
for (ed.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
const sel = cursel.enable_selection_normal();
sel.normalize();
try Editor.move_cursor_begin(root, &sel.begin, ed.metrics);
try Editor.move_cursor_end(root, &sel.end, ed.metrics);
cursel.cursor = sel.end;
try cursel.selection.?.end.move_right(root, ed.metrics);
try cursel.cursor.move_right(root, ed.metrics);
};
ed.clamp();
}
pub const extend_line_below_meta: Meta = .{ .description = "Select current line, if already selected, extend to next line" };
pub fn move_next_word_start(_: *void, _: Ctx) Result {
const mv = tui.mainview() orelse return;
const ed = mv.get_active_editor() orelse return;
const root = try ed.buf_root();
for (ed.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
cursel.selection = null;
};
ed.with_selections_const(root, Editor.move_cursor_word_right_vim) catch {};
ed.clamp();
}
pub const move_next_word_start_meta: Meta = .{ .description = "Move next word start" };
pub fn move_prev_word_start(_: *void, _: Ctx) Result {
const mv = tui.mainview() orelse return;
const ed = mv.get_active_editor() orelse return;
const root = try ed.buf_root();
for (ed.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
cursel.selection = null;
};
ed.with_selections_const(root, move_cursor_word_left_helix) catch {};
ed.clamp();
}
pub const move_prev_word_start_meta: Meta = .{ .description = "Move previous word start" };
pub fn cut_forward_internal_inclusive(_: *void, _: Ctx) Result {
const mv = tui.mainview() orelse return;
const ed = mv.get_active_editor() orelse return;
const b = try ed.buf_for_update();
const text, const root = try ed.cut_to(move_noop, b.root);
ed.set_clipboard_internal(text);
try ed.update_buf(root);
ed.clamp();
}
pub const cut_forward_internal_inclusive_meta: Meta = .{ .description = "Cut next character to internal clipboard (inclusive)" };
};
fn move_cursor_word_left_helix(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
try Editor.move_cursor_left(root, cursor, metrics);
// Consume " "
while (Editor.is_whitespace_at_cursor(root, cursor, metrics)) {
try Editor.move_cursor_left(root, cursor, metrics);
}
var next = cursor.*;
next.move_left(root, metrics) catch return;
var next_next = next;
next_next.move_left(root, metrics) catch return;
const cur = next.test_at(root, Editor.is_not_word_char, metrics);
const nxt = next_next.test_at(root, Editor.is_not_word_char, metrics);
if (cur != nxt) {
try Editor.move_cursor_left(root, cursor, metrics);
return;
} else {
try move_cursor_word_left_helix(root, cursor, metrics);
}
}
fn move_noop(_: Buffer.Root, _: *Cursor, _: Buffer.Metrics) error{Stop}!void {}