diff --git a/src/keybind/builtin/helix.json b/src/keybind/builtin/helix.json index 103f577..af3314e 100644 --- a/src/keybind/builtin/helix.json +++ b/src/keybind/builtin/helix.json @@ -66,11 +66,13 @@ ["alt+|", "shell_pipe_to"], ["alt+!", "shell_append_output"], - ["T", "till_prev_char"], - ["F", "move_to_char", "move_to_char_left"], + ["F", "move_to_char", "select_to_char_left_helix"], + ["T", "move_to_char", "select_till_char_left_helix"], ["W", "move_next_long_word_start"], ["B", "move_prev_long_word_start"], ["E", "move_next_long_word_end"], + ["t", "move_to_char", "select_till_char_right_helix"], + ["f", "move_to_char", "select_to_char_right_helix"], ["I", ["enter_mode", "insert"], ["smart_move_begin"]], ["A", ["enter_mode", "insert"], ["move_end"]], @@ -116,9 +118,6 @@ ["k", "move_up"], ["l", "move_right"], - ["t", "find_till_char"], - ["f", "move_to_char", "select_to_char_right_helix"], - ["home", "move_begin"], ["end", "move_end"], ["kp_home", "move_begin"], @@ -354,12 +353,13 @@ ["~", "switch_case"], - ["T", "extend_till_prev_char"], - ["F", "move_to_char", "select_to_char_left_vim"], - + ["F", "move_to_char", "extend_to_char_left_helix"], + ["T", "move_to_char", "extend_till_char_left_helix"], ["W", "extend_next_long_word_start"], ["B", "extend_prev_long_word_start"], ["E", "extend_next_long_word_end"], + ["t", "move_to_char", "extend_till_char_right_helix"], + ["f", "move_to_char", "extend_to_char_right_helix"], ["G", "goto_line"], @@ -415,9 +415,6 @@ ["kp_right", "select_right"], ["%", "select_all"], - ["t", "extend_till_char"], - ["f", "move_to_char", "select_to_char_right_helix"], - ["`", "switch_to_lowercase"], ["home", "extend_to_line_start"], diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 398318c..ca0ed0f 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -2094,7 +2094,7 @@ pub const Editor = struct { const cursor_predicate = *const fn (root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) bool; const cursor_operator_const = *const fn (root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void; const cursor_operator_const_arg = *const fn (root: Buffer.Root, cursor: *Cursor, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void; - const cursel_operator_mut_once_arg = *const fn (root: Buffer.Root, cursel: *CurSel, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void; + pub const cursel_operator_mut_once_arg = *const fn (root: Buffer.Root, cursel: *CurSel, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void; const cursor_view_operator_const = *const fn (root: Buffer.Root, cursor: *Cursor, view: *const View, metrics: Buffer.Metrics) error{Stop}!void; const cursel_operator_const = *const fn (root: Buffer.Root, cursel: *CurSel) error{Stop}!void; const cursor_operator = *const fn (root: Buffer.Root, cursor: *Cursor, allocator: Allocator) error{Stop}!Buffer.Root; diff --git a/src/tui/mode/helix.zig b/src/tui/mode/helix.zig index db58645..5187425 100644 --- a/src/tui/mode/helix.zig +++ b/src/tui/mode/helix.zig @@ -372,15 +372,46 @@ const cmds_ = struct { } pub const select_left_helix_meta: Meta = .{ .description = "Select left", .arguments = &.{.integer} }; + pub fn select_to_char_left_helix(_: *void, ctx: Ctx) Result { + try to_char_helix(ctx, &select_cursel_to_char_left_helix); + } + pub const select_to_char_left_helix_meta: Meta = .{ .description = "Select to char left" }; + + pub fn select_till_char_left_helix(_: *void, ctx: Ctx) Result { + try to_char_helix(ctx, &select_cursel_till_char_left_helix); + } + pub const select_till_char_left_helix_meta: Meta = .{ .description = "Select until char left" }; + + pub fn extend_to_char_left_helix(_: *void, ctx: Ctx) Result { + try to_char_helix(ctx, &extend_cursel_to_char_left_helix); + } + pub const extend_to_char_left_helix_meta: Meta = .{ .description = "Extend Selection to char left" }; + + pub fn extend_till_char_left_helix(_: *void, ctx: Ctx) Result { + try to_char_helix(ctx, &extend_cursel_till_char_left_helix); + } + pub const extend_till_char_left_helix_meta: Meta = .{ .description = "Extend Selection until char left" }; + + pub fn select_till_char_right_helix(_: *void, ctx: Ctx) Result { + try to_char_helix(ctx, &select_cursel_till_char_right_helix); + } + pub const select_till_char_right_helix_meta: Meta = .{ .description = "Select until char right" }; + pub fn select_to_char_right_helix(_: *void, ctx: Ctx) Result { - const mv = tui.mainview() orelse return; - const ed = mv.get_active_editor() orelse return; - const root = ed.buf_root() catch return; - try ed.with_cursels_const_once_arg(root, &select_cursel_to_char_right_helix, ctx); - ed.clamp(); + try to_char_helix(ctx, &select_cursel_to_char_right_helix); } pub const select_to_char_right_helix_meta: Meta = .{ .description = "Select to char right" }; + pub fn extend_till_char_right_helix(_: *void, ctx: Ctx) Result { + try to_char_helix(ctx, &extend_cursel_till_char_right_helix); + } + pub const extend_till_char_right_helix_meta: Meta = .{ .description = "Extend Selection until char right" }; + + pub fn extend_to_char_right_helix(_: *void, ctx: Ctx) Result { + try to_char_helix(ctx, &extend_cursel_to_char_right_helix); + } + pub const extend_to_char_right_helix_meta: Meta = .{ .description = "Extend Selection to char right" }; + pub fn copy_helix(_: *void, _: Ctx) Result { const mv = tui.mainview() orelse return; const ed = mv.get_active_editor() orelse return; @@ -411,6 +442,101 @@ const cmds_ = struct { pub const paste_clipboard_before_meta: Meta = .{ .description = "Paste from clipboard before selection" }; }; +fn to_char_helix(ctx: command.Context, move: Editor.cursel_operator_mut_once_arg) command.Result { + const mv = tui.mainview() orelse return; + const ed = mv.get_active_editor() orelse return; + const root = ed.buf_root() catch return; + try ed.with_cursels_const_once_arg(root, move, ctx); + ed.clamp(); +} + +fn select_cursel_to_char_left_helix(root: Buffer.Root, cursel: *CurSel, ctx: command.Context, metrics: Buffer.Metrics) error{Stop}!void { + var moving_cursor: Cursor = cursel.*.cursor; + var begin = cursel.*.cursor; + move_cursor_to_char_left_beyond_eol(root, &moving_cursor, metrics, ctx) catch return; + + // Character found, selecting + Editor.move_cursor_right(root, &begin, metrics) catch { + //At end of file, it's ok + }; + moving_cursor.target = moving_cursor.col; + const sel = try cursel.enable_selection(root, metrics); + sel.begin = begin; + sel.end = moving_cursor; + cursel.cursor = moving_cursor; +} + +fn extend_cursel_to_char_left_helix(root: Buffer.Root, cursel: *CurSel, ctx: command.Context, metrics: Buffer.Metrics) error{Stop}!void { + var moving_cursor: Cursor = cursel.*.cursor; + const begin = if (cursel.*.selection) |sel| sel.end else cursel.*.cursor; + move_cursor_to_char_left_beyond_eol(root, &moving_cursor, metrics, ctx) catch return; + + //Character found, selecting + moving_cursor.target = moving_cursor.col; + const sel = try cursel.enable_selection(root, metrics); + if (sel.empty()) + sel.begin = begin; + sel.end = moving_cursor; + cursel.cursor = moving_cursor; +} + +fn select_cursel_till_char_left_helix(root: Buffer.Root, cursel: *CurSel, ctx: command.Context, metrics: Buffer.Metrics) error{Stop}!void { + var moving_cursor: Cursor = cursel.*.cursor; + var begin = cursel.*.cursor; + move_cursor_till_char_left_beyond_eol(root, &moving_cursor, metrics, ctx) catch return; + Editor.move_cursor_right(root, &begin, metrics) catch { + //At end of file, it's ok + }; + + // Character found, selecting + moving_cursor.target = moving_cursor.col; + const sel = try cursel.enable_selection(root, metrics); + sel.begin = begin; + sel.end = moving_cursor; + cursel.cursor = moving_cursor; +} + +fn extend_cursel_till_char_left_helix(root: Buffer.Root, cursel: *CurSel, ctx: command.Context, metrics: Buffer.Metrics) error{Stop}!void { + var moving_cursor: Cursor = cursel.*.cursor; + const begin = if (cursel.*.selection) |sel| sel.end else cursel.*.cursor; + move_cursor_till_char_left_beyond_eol(root, &moving_cursor, metrics, ctx) catch return; + + //Character found, selecting + moving_cursor.target = moving_cursor.col; + const sel = try cursel.enable_selection(root, metrics); + if (sel.empty()) + sel.begin = begin; + sel.end = moving_cursor; + cursel.cursor = moving_cursor; +} + +fn select_cursel_till_char_right_helix(root: Buffer.Root, cursel: *CurSel, ctx: command.Context, metrics: Buffer.Metrics) error{Stop}!void { + var moving_cursor: Cursor = cursel.*.cursor; + const begin = cursel.*.cursor; + move_cursor_to_char_right_beyond_eol(root, &moving_cursor, metrics, ctx) catch return; + + //Character found, selecting + moving_cursor.target = moving_cursor.col; + const sel = try cursel.enable_selection(root, metrics); + sel.begin = begin; + sel.end = moving_cursor; + cursel.cursor = moving_cursor; +} + +fn extend_cursel_till_char_right_helix(root: Buffer.Root, cursel: *CurSel, ctx: command.Context, metrics: Buffer.Metrics) error{Stop}!void { + var moving_cursor: Cursor = cursel.*.cursor; + const begin = cursel.*.cursor; + move_cursor_to_char_right_beyond_eol(root, &moving_cursor, metrics, ctx) catch return; + + //Character found, selecting + moving_cursor.target = moving_cursor.col; + const sel = try cursel.enable_selection(root, metrics); + if (sel.empty()) + sel.begin = begin; + sel.end = moving_cursor; + cursel.cursor = moving_cursor; +} + fn select_cursel_to_char_right_helix(root: Buffer.Root, cursel: *CurSel, ctx: command.Context, metrics: Buffer.Metrics) error{Stop}!void { var moving_cursor: Cursor = cursel.*.cursor; const begin = cursel.*.cursor; @@ -427,6 +553,23 @@ fn select_cursel_to_char_right_helix(root: Buffer.Root, cursel: *CurSel, ctx: co cursel.cursor = moving_cursor; } +fn extend_cursel_to_char_right_helix(root: Buffer.Root, cursel: *CurSel, ctx: command.Context, metrics: Buffer.Metrics) error{Stop}!void { + var moving_cursor: Cursor = cursel.*.cursor; + const begin = cursel.*.cursor; + move_cursor_to_char_right_beyond_eol(root, &moving_cursor, metrics, ctx) catch return; + + //Character found, selecting + Editor.move_cursor_right(root, &moving_cursor, metrics) catch { + // We might be at end of file + }; + moving_cursor.target = moving_cursor.col; + const sel = try cursel.enable_selection(root, metrics); + if (sel.empty()) + sel.begin = begin; + sel.end = moving_cursor; + cursel.cursor = moving_cursor; +} + fn move_cursor_find_egc_beyond_eol(root: Buffer.Root, cursor: *Cursor, ctx: command.Context, metrics: Buffer.Metrics, move: find_char_function) error{Stop}!void { move(root, cursor, metrics, ctx); }