Compare commits
9 commits
a3a6830043
...
ae815043d9
Author | SHA1 | Date | |
---|---|---|---|
ae815043d9 | |||
ec483d34d5 | |||
6bed62e51d | |||
94b222fb1b | |||
545b470e03 | |||
d594e42f1a | |||
6946cb4010 | |||
5f05fd97e6 | |||
875816fdfc |
11 changed files with 400 additions and 244 deletions
|
@ -150,13 +150,8 @@ pub fn execute(id: ID, ctx: Context) tp.result {
|
|||
}
|
||||
|
||||
pub fn get_id(name: []const u8) ?ID {
|
||||
for (commands.items) |cmd| {
|
||||
if (cmd) |p|
|
||||
if (std.mem.eql(u8, p.name, name))
|
||||
return p.id;
|
||||
}
|
||||
tp.trace(tp.channel.debug, .{ "command", "get_id", "failed", name });
|
||||
return null;
|
||||
var id: ?ID = null;
|
||||
return get_id_cache(name, &id);
|
||||
}
|
||||
|
||||
pub fn get_name(id: ID) ?[]const u8 {
|
||||
|
@ -178,6 +173,7 @@ pub fn get_id_cache(name: []const u8, id: *?ID) ?ID {
|
|||
return p.id;
|
||||
};
|
||||
}
|
||||
tp.trace(tp.channel.debug, .{ "command", "get_id_cache", "failed", name });
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,17 @@
|
|||
["ctrl+x ctrl+r", "open_recent"],
|
||||
["ctrl+space", "enter_mode", "select"],
|
||||
|
||||
["alt+0", "add_integer_argument_digit", 0],
|
||||
["alt+1", "add_integer_argument_digit", 1],
|
||||
["alt+2", "add_integer_argument_digit", 2],
|
||||
["alt+3", "add_integer_argument_digit", 3],
|
||||
["alt+4", "add_integer_argument_digit", 4],
|
||||
["alt+5", "add_integer_argument_digit", 5],
|
||||
["alt+6", "add_integer_argument_digit", 6],
|
||||
["alt+7", "add_integer_argument_digit", 7],
|
||||
["alt+8", "add_integer_argument_digit", 8],
|
||||
["alt+9", "add_integer_argument_digit", 9],
|
||||
|
||||
["ctrl+c l = =", "format"],
|
||||
["ctrl+c l = r", "format"],
|
||||
["ctrl+c l g g", "goto_definition"],
|
||||
|
|
|
@ -190,6 +190,17 @@
|
|||
["«", "smart_insert_pair", "«", "»"],
|
||||
["»", "smart_insert_pair_close", "«", "»"],
|
||||
|
||||
["alt+0", "add_integer_argument_digit", 0],
|
||||
["alt+1", "add_integer_argument_digit", 1],
|
||||
["alt+2", "add_integer_argument_digit", 2],
|
||||
["alt+3", "add_integer_argument_digit", 3],
|
||||
["alt+4", "add_integer_argument_digit", 4],
|
||||
["alt+5", "add_integer_argument_digit", 5],
|
||||
["alt+6", "add_integer_argument_digit", 6],
|
||||
["alt+7", "add_integer_argument_digit", 7],
|
||||
["alt+8", "add_integer_argument_digit", 8],
|
||||
["alt+9", "add_integer_argument_digit", 9],
|
||||
|
||||
["left_control", "enable_jump_mode"],
|
||||
["right_control", "enable_jump_mode"],
|
||||
["left_alt", "enable_fast_scroll"],
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
|
||||
["n", "goto_next_match"],
|
||||
["N", "goto_prev_match"],
|
||||
["0", "move_begin"],
|
||||
["^", "smart_move_begin"],
|
||||
["$", "move_end"],
|
||||
[":", "open_command_palette"],
|
||||
|
@ -90,7 +89,18 @@
|
|||
["f", "move_to_char", "move_to_char_right"],
|
||||
|
||||
["<C-CR>", ["move_down"], ["move_begin"]],
|
||||
["<CR>", ["move_down"], ["move_begin"]]
|
||||
["<CR>", ["move_down"], ["move_begin"]],
|
||||
|
||||
["0", "move_begin_or_add_integer_argument_zero"],
|
||||
["1", "add_integer_argument_digit", 1],
|
||||
["2", "add_integer_argument_digit", 2],
|
||||
["3", "add_integer_argument_digit", 3],
|
||||
["4", "add_integer_argument_digit", 4],
|
||||
["5", "add_integer_argument_digit", 5],
|
||||
["6", "add_integer_argument_digit", 6],
|
||||
["7", "add_integer_argument_digit", 7],
|
||||
["8", "add_integer_argument_digit", 8],
|
||||
["9", "add_integer_argument_digit", 9]
|
||||
]
|
||||
},
|
||||
"visual": {
|
||||
|
|
|
@ -25,6 +25,31 @@ const builtin_keybinds = std.static_string_map.StaticStringMap([]const u8).initC
|
|||
.{ "emacs", @embedFile("builtin/emacs.json") },
|
||||
});
|
||||
|
||||
var integer_argument: ?usize = null;
|
||||
|
||||
var commands: Commands = undefined;
|
||||
const Commands = command.Collection(struct {
|
||||
pub const Target = void;
|
||||
const Ctx = command.Context;
|
||||
const Meta = command.Metadata;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn add_integer_argument_digit(_: *void, ctx: Ctx) Result {
|
||||
var digit: usize = undefined;
|
||||
if (!try ctx.args.match(.{tp.extract(&digit)}))
|
||||
return error.InvalidIntegerParameterArgument;
|
||||
if (digit > 9)
|
||||
return error.InvalidIntegerParameterDigit;
|
||||
integer_argument = if (integer_argument) |x| x * 10 + digit else digit;
|
||||
}
|
||||
pub const add_integer_argument_digit_meta: Meta = .{ .arguments = &.{.integer} };
|
||||
});
|
||||
|
||||
pub fn init() !void {
|
||||
var v: void = {};
|
||||
try commands.init(&v);
|
||||
}
|
||||
|
||||
pub fn mode(mode_name: []const u8, allocator: std.mem.Allocator, opts: anytype) !Mode {
|
||||
return Handler.create(mode_name, allocator, opts) catch |e| switch (e) {
|
||||
error.NotFound => return error.Stop,
|
||||
|
@ -86,10 +111,18 @@ pub const Mode = struct {
|
|||
selection_style: SelectionStyle,
|
||||
init_command: ?Command = null,
|
||||
deinit_command: ?Command = null,
|
||||
initialized: bool = false,
|
||||
|
||||
pub fn run_init(self: *Mode) void {
|
||||
if (self.initialized) return;
|
||||
self.initialized = true;
|
||||
clear_integer_argument();
|
||||
if (self.init_command) |init_command| init_command.execute_const();
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Mode) void {
|
||||
if (self.deinit_command) |deinit_|
|
||||
deinit_.execute_const();
|
||||
if (self.deinit_command) |deinit_command|
|
||||
deinit_command.execute_const();
|
||||
self.allocator.free(self.mode);
|
||||
self.input_handler.deinit();
|
||||
if (self.event_handler) |eh| eh.deinit();
|
||||
|
@ -144,11 +177,11 @@ fn get_or_load_namespace(namespace_name: []const u8) LoadError!*const Namespace
|
|||
pub fn set_namespace(namespace_name: []const u8) LoadError!void {
|
||||
const new_namespace = try get_or_load_namespace(namespace_name);
|
||||
if (globals.current_namespace) |old_namespace|
|
||||
if (old_namespace.deinit_command) |deinit|
|
||||
deinit.execute_const();
|
||||
if (old_namespace.deinit_command) |deinit_command|
|
||||
deinit_command.execute_const();
|
||||
globals.current_namespace = new_namespace;
|
||||
if (new_namespace.init_command) |init|
|
||||
init.execute_const();
|
||||
if (new_namespace.init_command) |init_command|
|
||||
init_command.execute_const();
|
||||
}
|
||||
|
||||
fn get_mode_binding_set(mode_name: []const u8, insert_command: []const u8) LoadError!*const BindingSet {
|
||||
|
@ -262,10 +295,17 @@ const Command = struct {
|
|||
};
|
||||
var buf: [2048]u8 = undefined;
|
||||
@memcpy(buf[0..self.args.len], self.args);
|
||||
if (integer_argument) |int_arg| {
|
||||
if (cbor.match(self.args, .{}) catch false and has_integer_argument(id)) {
|
||||
integer_argument = null;
|
||||
try command.execute(id, command.fmt(.{int_arg}));
|
||||
return;
|
||||
}
|
||||
}
|
||||
try command.execute(id, .{ .args = .{ .buf = buf[0..self.args.len] } });
|
||||
}
|
||||
|
||||
pub fn execute_const(self: *const @This()) void {
|
||||
fn execute_const(self: *const @This()) void {
|
||||
var buf: [2048]u8 = undefined;
|
||||
@memcpy(buf[0..self.args.len], self.args);
|
||||
command.executeName(self.command, .{ .args = .{ .buf = buf[0..self.args.len] } }) catch |e| {
|
||||
|
@ -275,6 +315,11 @@ const Command = struct {
|
|||
};
|
||||
}
|
||||
|
||||
fn has_integer_argument(id: command.ID) bool {
|
||||
const args = command.get_arguments(id) orelse return false;
|
||||
return args.len == 1 and args[0] == .integer;
|
||||
}
|
||||
|
||||
fn load(allocator: std.mem.Allocator, tokens: []const std.json.Value) (parse_flow.ParseError || parse_vim.ParseError)!Command {
|
||||
if (tokens.len == 0) return error.InvalidFormat;
|
||||
var state: enum { command, args } = .command;
|
||||
|
@ -724,6 +769,14 @@ pub fn current_key_event_sequence_fmt() KeyEventSequenceFmt {
|
|||
return .{ .key_events = globals.current_sequence.items };
|
||||
}
|
||||
|
||||
pub fn current_integer_argument() ?usize {
|
||||
return integer_argument;
|
||||
}
|
||||
|
||||
pub fn clear_integer_argument() void {
|
||||
integer_argument = null;
|
||||
}
|
||||
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
|
||||
const parse_test_cases = .{
|
||||
|
|
|
@ -2,6 +2,8 @@ const vaxis = @import("vaxis");
|
|||
|
||||
const meta = @import("std").meta;
|
||||
const utf8Encode = @import("std").unicode.utf8Encode;
|
||||
const utf8Decode = @import("std").unicode.utf8Decode;
|
||||
const utf8ValidateSlice = @import("std").unicode.utf8ValidateSlice;
|
||||
const FormatOptions = @import("std").fmt.FormatOptions;
|
||||
|
||||
pub const key = vaxis.Key;
|
||||
|
@ -74,6 +76,7 @@ pub const KeyEvent = struct {
|
|||
}
|
||||
|
||||
pub fn eql_unshifted(self: @This(), other: @This()) bool {
|
||||
if (self.text.len > 0 or other.text.len > 0) return false;
|
||||
const self_mods = self.mods_no_caps();
|
||||
const other_mods = other.mods_no_caps();
|
||||
return self.key_unshifted == other.key_unshifted and self_mods == other_mods;
|
||||
|
@ -117,7 +120,7 @@ pub const KeyEvent = struct {
|
|||
pub fn from_message(
|
||||
event_: Event,
|
||||
keypress_: Key,
|
||||
keypress_shifted: Key,
|
||||
keypress_shifted_: Key,
|
||||
text: []const u8,
|
||||
modifiers: Mods,
|
||||
) @This() {
|
||||
|
@ -128,6 +131,11 @@ pub const KeyEvent = struct {
|
|||
key.left_alt, key.right_alt => modifiers & ~mod.alt,
|
||||
else => modifiers,
|
||||
};
|
||||
|
||||
var keypress_shifted: Key = keypress_shifted_;
|
||||
if (text.len > 0 and text.len < 5 and utf8ValidateSlice(text)) blk: {
|
||||
keypress_shifted = utf8Decode(text) catch break :blk;
|
||||
}
|
||||
const keypress, const mods = if (keypress_shifted == keypress_)
|
||||
map_key_to_unshifed_legacy(keypress_shifted, mods_)
|
||||
else
|
||||
|
|
|
@ -1743,7 +1743,7 @@ pub const Editor = struct {
|
|||
try move(root, &cursel.cursor, metrics);
|
||||
}
|
||||
|
||||
fn with_cursors_const(self: *Self, root: Buffer.Root, move: cursor_operator_const) error{Stop}!void {
|
||||
fn with_cursors_const_once(self: *Self, root: Buffer.Root, move: cursor_operator_const) error{Stop}!void {
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
cursel.disable_selection(root, self.metrics);
|
||||
try with_cursor_const(root, move, cursel, self.metrics);
|
||||
|
@ -1751,6 +1751,18 @@ pub const Editor = struct {
|
|||
self.collapse_cursors();
|
||||
}
|
||||
|
||||
fn with_cursors_const_repeat(self: *Self, root: Buffer.Root, move: cursor_operator_const, ctx: Context) error{Stop}!void {
|
||||
var repeat: usize = 1;
|
||||
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
|
||||
while (repeat > 0) : (repeat -= 1) {
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
cursel.disable_selection(root, self.metrics);
|
||||
try with_cursor_const(root, move, cursel, self.metrics);
|
||||
};
|
||||
self.collapse_cursors();
|
||||
}
|
||||
}
|
||||
|
||||
fn with_cursor_const_arg(root: Buffer.Root, move: cursor_operator_const_arg, cursel: *CurSel, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void {
|
||||
try move(root, &cursel.cursor, ctx, metrics);
|
||||
}
|
||||
|
@ -1788,7 +1800,7 @@ pub const Editor = struct {
|
|||
cursel.check_selection(root, metrics);
|
||||
}
|
||||
|
||||
pub fn with_selections_const(self: *Self, root: Buffer.Root, move: cursor_operator_const) error{Stop}!void {
|
||||
pub fn with_selections_const_once(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 {
|
||||
|
@ -1798,6 +1810,21 @@ pub const Editor = struct {
|
|||
return if (someone_stopped) error.Stop else {};
|
||||
}
|
||||
|
||||
pub fn with_selections_const_repeat(self: *Self, root: Buffer.Root, move: cursor_operator_const, ctx: Context) error{Stop}!void {
|
||||
var someone_stopped = false;
|
||||
var repeat: usize = 1;
|
||||
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
|
||||
while (repeat > 0) : (repeat -= 1) {
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel|
|
||||
with_selection_const(root, move, cursel, self.metrics) catch {
|
||||
someone_stopped = true;
|
||||
};
|
||||
self.collapse_cursors();
|
||||
if (someone_stopped) break;
|
||||
}
|
||||
return if (someone_stopped) error.Stop else {};
|
||||
}
|
||||
|
||||
fn with_selection_const_arg(root: Buffer.Root, move: cursor_operator_const_arg, cursel: *CurSel, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void {
|
||||
const sel = try cursel.enable_selection(root, metrics);
|
||||
try move(root, &sel.end, ctx, metrics);
|
||||
|
@ -1831,28 +1858,11 @@ pub const Editor = struct {
|
|||
return if (someone_stopped) error.Stop else {};
|
||||
}
|
||||
|
||||
fn with_cursel(root: Buffer.Root, op: cursel_operator, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
return op(root, cursel, allocator);
|
||||
}
|
||||
|
||||
fn with_cursels(self: *Self, root_: Buffer.Root, move: cursel_operator, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
var root = root_;
|
||||
var someone_stopped = false;
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
root = with_cursel(root, move, cursel, allocator) catch ret: {
|
||||
someone_stopped = true;
|
||||
break :ret root;
|
||||
};
|
||||
};
|
||||
self.collapse_cursors();
|
||||
return if (someone_stopped) error.Stop else root;
|
||||
}
|
||||
|
||||
fn with_cursel_mut(self: *Self, root: Buffer.Root, op: cursel_operator_mut, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
return op(self, root, cursel, allocator);
|
||||
}
|
||||
|
||||
fn with_cursels_mut(self: *Self, root_: Buffer.Root, move: cursel_operator_mut, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
fn with_cursels_mut_once(self: *Self, root_: Buffer.Root, move: cursel_operator_mut, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
var root = root_;
|
||||
var someone_stopped = false;
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
|
@ -1865,6 +1875,24 @@ pub const Editor = struct {
|
|||
return if (someone_stopped) error.Stop else root;
|
||||
}
|
||||
|
||||
fn with_cursels_mut_repeat(self: *Self, root_: Buffer.Root, move: cursel_operator_mut, allocator: Allocator, ctx: Context) error{Stop}!Buffer.Root {
|
||||
var root = root_;
|
||||
var someone_stopped = false;
|
||||
var repeat: usize = 1;
|
||||
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
|
||||
while (repeat > 0) : (repeat -= 1) {
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
root = self.with_cursel_mut(root, move, cursel, allocator) catch ret: {
|
||||
someone_stopped = true;
|
||||
break :ret root;
|
||||
};
|
||||
};
|
||||
self.collapse_cursors();
|
||||
if (someone_stopped) break;
|
||||
}
|
||||
return if (someone_stopped) error.Stop else root;
|
||||
}
|
||||
|
||||
fn with_cursel_const(root: Buffer.Root, op: cursel_operator_const, cursel: *CurSel) error{Stop}!void {
|
||||
return op(root, cursel);
|
||||
}
|
||||
|
@ -2889,9 +2917,9 @@ pub const Editor = struct {
|
|||
}
|
||||
pub const cut_to_end_vim_meta: Meta = .{ .description = "Cut to end of line (vim)" };
|
||||
|
||||
pub fn join_next_line(self: *Self, _: Context) Result {
|
||||
pub fn join_next_line(self: *Self, ctx: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
try self.with_cursors_const(b.root, move_cursor_end);
|
||||
try self.with_cursors_const_repeat(b.root, move_cursor_end, ctx);
|
||||
var root = try self.delete_to(move_cursor_right_until_non_whitespace, b.root, b.allocator);
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
root = try self.insert(root, cursel, " ", b.allocator);
|
||||
|
@ -2899,21 +2927,21 @@ pub const Editor = struct {
|
|||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
}
|
||||
pub const join_next_line_meta: Meta = .{ .description = "Join next line" };
|
||||
pub const join_next_line_meta: Meta = .{ .description = "Join next line", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_left(self: *Self, _: Context) Result {
|
||||
pub fn move_left(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_left) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_left, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_left_meta: Meta = .{ .description = "Move cursor left" };
|
||||
pub const move_left_meta: Meta = .{ .description = "Move cursor left", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_right(self: *Self, _: Context) Result {
|
||||
pub fn move_right(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_right) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_right, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_right_meta: Meta = .{ .description = "Move cursor right" };
|
||||
pub const move_right_meta: Meta = .{ .description = "Move cursor right", .arguments = &.{.integer} };
|
||||
|
||||
fn move_cursor_left_vim(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
|
||||
move_cursor_left_unless(root, cursor, is_eol_left, metrics);
|
||||
|
@ -2923,19 +2951,19 @@ pub const Editor = struct {
|
|||
move_cursor_right_unless(root, cursor, is_eol_right_vim, metrics);
|
||||
}
|
||||
|
||||
pub fn move_left_vim(self: *Self, _: Context) Result {
|
||||
pub fn move_left_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_left_vim) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_left_vim, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_left_vim_meta: Meta = .{ .description = "Move cursor left (vim)" };
|
||||
pub const move_left_vim_meta: Meta = .{ .description = "Move cursor left (vim)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_right_vim(self: *Self, _: Context) Result {
|
||||
pub fn move_right_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_right_vim) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_right_vim, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_right_vim_meta: Meta = .{ .description = "Move cursor right (vim)" };
|
||||
pub const move_right_vim_meta: Meta = .{ .description = "Move cursor right (vim)", .arguments = &.{.integer} };
|
||||
|
||||
fn move_cursor_word_begin(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
|
||||
if (is_non_word_char_at_cursor(root, cursor, metrics)) {
|
||||
|
@ -3010,40 +3038,40 @@ pub const Editor = struct {
|
|||
move_cursor_right_until(root, cursor, is_non_whitespace_at_cursor, metrics);
|
||||
}
|
||||
|
||||
pub fn move_word_left(self: *Self, _: Context) Result {
|
||||
pub fn move_word_left(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_word_left) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_word_left, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_word_left_meta: Meta = .{ .description = "Move cursor left by word" };
|
||||
pub const move_word_left_meta: Meta = .{ .description = "Move cursor left by word", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_word_left_vim(self: *Self, _: Context) Result {
|
||||
pub fn move_word_left_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_word_left_vim) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_word_left_vim, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_word_left_vim_meta: Meta = .{ .description = "Move cursor left by word (vim)" };
|
||||
pub const move_word_left_vim_meta: Meta = .{ .description = "Move cursor left by word (vim)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_word_right(self: *Self, _: Context) Result {
|
||||
pub fn move_word_right(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_word_right) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_word_right, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_word_right_meta: Meta = .{ .description = "Move cursor right by word" };
|
||||
pub const move_word_right_meta: Meta = .{ .description = "Move cursor right by word", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_word_right_vim(self: *Self, _: Context) Result {
|
||||
pub fn move_word_right_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_word_right_vim) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_word_right_vim, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_word_right_vim_meta: Meta = .{ .description = "Move cursor right by word (vim)" };
|
||||
pub const move_word_right_vim_meta: Meta = .{ .description = "Move cursor right by word (vim)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_word_right_end_vim(self: *Self, _: Context) Result {
|
||||
pub fn move_word_right_end_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_word_right_end_vim) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_word_right_end_vim, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_word_right_end_vim_meta: Meta = .{ .description = "Move cursor right by end of word (vim)" };
|
||||
pub const move_word_right_end_vim_meta: Meta = .{ .description = "Move cursor right by end of word (vim)", .arguments = &.{.integer} };
|
||||
|
||||
fn move_cursor_to_char_left(root: Buffer.Root, cursor: *Cursor, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void {
|
||||
var egc: []const u8 = undefined;
|
||||
|
@ -3101,70 +3129,82 @@ pub const Editor = struct {
|
|||
}
|
||||
pub const move_or_select_to_char_right_meta: Meta = .{ .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_up(self: *Self, _: Context) Result {
|
||||
pub fn move_up(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_up) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_up, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_up_meta: Meta = .{ .description = "Move cursor up" };
|
||||
pub const move_up_meta: Meta = .{ .description = "Move cursor up", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_up_vim(self: *Self, _: Context) Result {
|
||||
pub fn move_up_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_up_vim) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_up_vim, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_up_vim_meta: Meta = .{ .description = "Move cursor up (vim)" };
|
||||
pub const move_up_vim_meta: Meta = .{ .description = "Move cursor up (vim)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn add_cursor_up(self: *Self, _: Context) Result {
|
||||
try self.push_cursor();
|
||||
const primary = self.get_primary();
|
||||
pub fn add_cursor_up(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
move_cursor_up(root, &primary.cursor, self.metrics) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const add_cursor_up_meta: Meta = .{ .description = "Add cursor up" };
|
||||
|
||||
pub fn move_down(self: *Self, _: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_down) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_down_meta: Meta = .{ .description = "Move cursor down" };
|
||||
|
||||
pub fn move_down_vim(self: *Self, _: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_down_vim) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_down_vim_meta: Meta = .{ .description = "Move cursor down (vim)" };
|
||||
|
||||
pub fn add_cursor_down(self: *Self, _: Context) Result {
|
||||
try self.push_cursor();
|
||||
const primary = self.get_primary();
|
||||
const root = try self.buf_root();
|
||||
move_cursor_down(root, &primary.cursor, self.metrics) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const add_cursor_down_meta: Meta = .{ .description = "Add cursor down" };
|
||||
|
||||
pub fn add_cursor_next_match(self: *Self, _: Context) Result {
|
||||
try self.send_editor_jump_source();
|
||||
if (self.matches.items.len == 0) {
|
||||
const root = self.buf_root() catch return;
|
||||
self.with_cursors_const(root, move_cursor_word_begin) catch {};
|
||||
try self.with_selections_const(root, move_cursor_word_end);
|
||||
} else if (self.get_next_match(self.get_primary().cursor)) |match| {
|
||||
var repeat: usize = 1;
|
||||
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
|
||||
while (repeat > 0) : (repeat -= 1) {
|
||||
try self.push_cursor();
|
||||
const primary = self.get_primary();
|
||||
const root = self.buf_root() catch return;
|
||||
primary.selection = match.to_selection();
|
||||
match.has_selection = true;
|
||||
primary.cursor.move_to(root, match.end.row, match.end.col, self.metrics) catch return;
|
||||
move_cursor_up(root, &primary.cursor, self.metrics) catch {};
|
||||
}
|
||||
self.clamp();
|
||||
}
|
||||
pub const add_cursor_up_meta: Meta = .{ .description = "Add cursor up", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_down(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const_repeat(root, move_cursor_down, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_down_meta: Meta = .{ .description = "Move cursor down", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_down_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const_repeat(root, move_cursor_down_vim, ctx) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_down_vim_meta: Meta = .{ .description = "Move cursor down (vim)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn add_cursor_down(self: *Self, ctx: Context) Result {
|
||||
var repeat: usize = 1;
|
||||
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
|
||||
while (repeat > 0) : (repeat -= 1) {
|
||||
try self.push_cursor();
|
||||
const primary = self.get_primary();
|
||||
const root = try self.buf_root();
|
||||
move_cursor_down(root, &primary.cursor, self.metrics) catch {};
|
||||
}
|
||||
self.clamp();
|
||||
}
|
||||
pub const add_cursor_down_meta: Meta = .{ .description = "Add cursor down", .arguments = &.{.integer} };
|
||||
|
||||
pub fn add_cursor_next_match(self: *Self, ctx: Context) Result {
|
||||
try self.send_editor_jump_source();
|
||||
var repeat: usize = 1;
|
||||
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
|
||||
while (repeat > 0) : (repeat -= 1) {
|
||||
if (self.matches.items.len == 0) {
|
||||
const root = self.buf_root() catch return;
|
||||
self.with_cursors_const_once(root, move_cursor_word_begin) catch {};
|
||||
try self.with_selections_const_once(root, move_cursor_word_end);
|
||||
} else if (self.get_next_match(self.get_primary().cursor)) |match| {
|
||||
try self.push_cursor();
|
||||
const primary = self.get_primary();
|
||||
const root = self.buf_root() catch return;
|
||||
primary.selection = match.to_selection();
|
||||
match.has_selection = true;
|
||||
primary.cursor.move_to(root, match.end.row, match.end.col, self.metrics) catch return;
|
||||
}
|
||||
}
|
||||
self.clamp();
|
||||
try self.send_editor_jump_destination();
|
||||
}
|
||||
pub const add_cursor_next_match_meta: Meta = .{ .description = "Add cursor at next highlighted match" };
|
||||
pub const add_cursor_next_match_meta: Meta = .{ .description = "Add cursor at next highlighted match", .arguments = &.{.integer} };
|
||||
|
||||
pub fn add_cursor_all_matches(self: *Self, _: Context) Result {
|
||||
if (self.matches.items.len == 0) return;
|
||||
|
@ -3229,13 +3269,13 @@ pub const Editor = struct {
|
|||
return root;
|
||||
}
|
||||
|
||||
pub fn pull_up(self: *Self, _: Context) Result {
|
||||
pub fn pull_up(self: *Self, ctx: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, pull_cursel_up, b.allocator);
|
||||
const root = try self.with_cursels_mut_repeat(b.root, pull_cursel_up, b.allocator, ctx);
|
||||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
}
|
||||
pub const pull_up_meta: Meta = .{ .description = "Pull line up" };
|
||||
pub const pull_up_meta: Meta = .{ .description = "Pull line up", .arguments = &.{.integer} };
|
||||
|
||||
fn pull_cursel_down(self: *Self, root_: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
var root = root_;
|
||||
|
@ -3256,13 +3296,13 @@ pub const Editor = struct {
|
|||
return root;
|
||||
}
|
||||
|
||||
pub fn pull_down(self: *Self, _: Context) Result {
|
||||
pub fn pull_down(self: *Self, ctx: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, pull_cursel_down, b.allocator);
|
||||
const root = try self.with_cursels_mut_repeat(b.root, pull_cursel_down, b.allocator, ctx);
|
||||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
}
|
||||
pub const pull_down_meta: Meta = .{ .description = "Pull line down" };
|
||||
pub const pull_down_meta: Meta = .{ .description = "Pull line down", .arguments = &.{.integer} };
|
||||
|
||||
fn dupe_cursel_up(self: *Self, root_: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
var root = root_;
|
||||
|
@ -3278,13 +3318,13 @@ pub const Editor = struct {
|
|||
return root;
|
||||
}
|
||||
|
||||
pub fn dupe_up(self: *Self, _: Context) Result {
|
||||
pub fn dupe_up(self: *Self, ctx: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, dupe_cursel_up, b.allocator);
|
||||
const root = try self.with_cursels_mut_repeat(b.root, dupe_cursel_up, b.allocator, ctx);
|
||||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
}
|
||||
pub const dupe_up_meta: Meta = .{ .description = "Duplicate line or selection up/backwards" };
|
||||
pub const dupe_up_meta: Meta = .{ .description = "Duplicate line or selection up/backwards", .arguments = &.{.integer} };
|
||||
|
||||
fn dupe_cursel_down(self: *Self, root_: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
var root = root_;
|
||||
|
@ -3299,13 +3339,13 @@ pub const Editor = struct {
|
|||
return root;
|
||||
}
|
||||
|
||||
pub fn dupe_down(self: *Self, _: Context) Result {
|
||||
pub fn dupe_down(self: *Self, ctx: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, dupe_cursel_down, b.allocator);
|
||||
const root = try self.with_cursels_mut_repeat(b.root, dupe_cursel_down, b.allocator, ctx);
|
||||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
}
|
||||
pub const dupe_down_meta: Meta = .{ .description = "Duplicate line or selection down/forwards" };
|
||||
pub const dupe_down_meta: Meta = .{ .description = "Duplicate line or selection down/forwards", .arguments = &.{.integer} };
|
||||
|
||||
fn toggle_cursel_prefix(self: *Self, root_: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
var root = root_;
|
||||
|
@ -3330,7 +3370,7 @@ pub const Editor = struct {
|
|||
@memcpy(self.prefix_buf[0..prefix.len], prefix);
|
||||
self.prefix = self.prefix_buf[0..prefix.len];
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, toggle_cursel_prefix, b.allocator);
|
||||
const root = try self.with_cursels_mut_once(b.root, toggle_cursel_prefix, b.allocator);
|
||||
try self.update_buf(root);
|
||||
}
|
||||
pub const toggle_prefix_meta: Meta = .{ .arguments = &.{.string} };
|
||||
|
@ -3366,12 +3406,12 @@ pub const Editor = struct {
|
|||
} else return try self.indent_cursor(root_, cursel.cursor, allocator);
|
||||
}
|
||||
|
||||
pub fn indent(self: *Self, _: Context) Result {
|
||||
pub fn indent(self: *Self, ctx: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, indent_cursel, b.allocator);
|
||||
const root = try self.with_cursels_mut_repeat(b.root, indent_cursel, b.allocator, ctx);
|
||||
try self.update_buf(root);
|
||||
}
|
||||
pub const indent_meta: Meta = .{ .description = "Indent current line" };
|
||||
pub const indent_meta: Meta = .{ .description = "Indent current line", .arguments = &.{.integer} };
|
||||
|
||||
fn unindent_cursor(self: *Self, root: Buffer.Root, cursor: *Cursor, cursor_protect: ?*Cursor, allocator: Allocator) error{Stop}!Buffer.Root {
|
||||
var newroot = root;
|
||||
|
@ -3415,32 +3455,32 @@ pub const Editor = struct {
|
|||
self.cursels = self.cursels_saved.clone() catch return;
|
||||
}
|
||||
|
||||
pub fn unindent(self: *Self, _: Context) Result {
|
||||
pub fn unindent(self: *Self, ctx: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
errdefer self.restore_cursels();
|
||||
const previous_len = self.cursels.items.len;
|
||||
const root = try self.with_cursels_mut(b.root, unindent_cursel, b.allocator);
|
||||
const root = try self.with_cursels_mut_repeat(b.root, unindent_cursel, b.allocator, ctx);
|
||||
if (self.cursels.items.len != previous_len)
|
||||
self.restore_cursels();
|
||||
try self.update_buf(root);
|
||||
}
|
||||
pub const unindent_meta: Meta = .{ .description = "Unindent current line" };
|
||||
pub const unindent_meta: Meta = .{ .description = "Unindent current line", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_scroll_up(self: *Self, _: Context) Result {
|
||||
pub fn move_scroll_up(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_up) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_up, ctx) catch {};
|
||||
self.view.move_up() catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_scroll_up_meta: Meta = .{ .description = "Move and scroll up" };
|
||||
pub const move_scroll_up_meta: Meta = .{ .description = "Move and scroll up", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_scroll_down(self: *Self, _: Context) Result {
|
||||
pub fn move_scroll_down(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
self.with_cursors_const(root, move_cursor_down) catch {};
|
||||
self.with_cursors_const_repeat(root, move_cursor_down, ctx) catch {};
|
||||
self.view.move_down(root) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_scroll_down_meta: Meta = .{ .description = "Move and scroll down" };
|
||||
pub const move_scroll_down_meta: Meta = .{ .description = "Move and scroll down", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_scroll_left(self: *Self, _: Context) Result {
|
||||
self.view.move_left() catch {};
|
||||
|
@ -3526,21 +3566,21 @@ pub const Editor = struct {
|
|||
|
||||
pub fn smart_move_begin(self: *Self, _: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_cursors_const(root, smart_move_cursor_begin);
|
||||
try self.with_cursors_const_once(root, smart_move_cursor_begin);
|
||||
self.clamp();
|
||||
}
|
||||
pub const smart_move_begin_meta: Meta = .{ .description = "Move cursor to beginning of line (smart)" };
|
||||
|
||||
pub fn move_begin(self: *Self, _: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_cursors_const(root, move_cursor_begin);
|
||||
try self.with_cursors_const_once(root, move_cursor_begin);
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_begin_meta: Meta = .{ .description = "Move cursor to beginning of line" };
|
||||
|
||||
pub fn move_end(self: *Self, _: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_cursors_const(root, move_cursor_end);
|
||||
try self.with_cursors_const_once(root, move_cursor_end);
|
||||
self.clamp();
|
||||
}
|
||||
pub const move_end_meta: Meta = .{ .description = "Move cursor to end of line" };
|
||||
|
@ -3601,6 +3641,7 @@ pub const Editor = struct {
|
|||
pub fn cancel(self: *Self, _: Context) Result {
|
||||
self.cancel_all_selections();
|
||||
self.cancel_all_matches();
|
||||
@import("keybind").clear_integer_argument();
|
||||
}
|
||||
pub const cancel_meta: Meta = .{ .description = "Cancel current action" };
|
||||
|
||||
|
@ -3620,98 +3661,98 @@ pub const Editor = struct {
|
|||
}
|
||||
pub const select_line_vim_meta: Meta = .{ .description = "Select the line around the cursor (vim)" };
|
||||
|
||||
pub fn select_up(self: *Self, _: Context) Result {
|
||||
pub fn select_up(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_up);
|
||||
try self.with_selections_const_repeat(root, move_cursor_up, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_up_meta: Meta = .{ .description = "Select up" };
|
||||
pub const select_up_meta: Meta = .{ .description = "Select up", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_down(self: *Self, _: Context) Result {
|
||||
pub fn select_down(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_down);
|
||||
try self.with_selections_const_repeat(root, move_cursor_down, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_down_meta: Meta = .{ .description = "Select down" };
|
||||
pub const select_down_meta: Meta = .{ .description = "Select down", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_scroll_up(self: *Self, _: Context) Result {
|
||||
pub fn select_scroll_up(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_up);
|
||||
try self.with_selections_const_repeat(root, move_cursor_up, ctx);
|
||||
self.view.move_up() catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_scroll_up_meta: Meta = .{ .description = "Select and scroll up" };
|
||||
pub const select_scroll_up_meta: Meta = .{ .description = "Select and scroll up", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_scroll_down(self: *Self, _: Context) Result {
|
||||
pub fn select_scroll_down(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_down);
|
||||
try self.with_selections_const_repeat(root, move_cursor_down, ctx);
|
||||
self.view.move_down(root) catch {};
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_scroll_down_meta: Meta = .{ .description = "Select and scroll down" };
|
||||
pub const select_scroll_down_meta: Meta = .{ .description = "Select and scroll down", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_left(self: *Self, _: Context) Result {
|
||||
pub fn select_left(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_left);
|
||||
try self.with_selections_const_repeat(root, move_cursor_left, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_left_meta: Meta = .{ .description = "Select left" };
|
||||
pub const select_left_meta: Meta = .{ .description = "Select left", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_right(self: *Self, _: Context) Result {
|
||||
pub fn select_right(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_right);
|
||||
try self.with_selections_const_repeat(root, move_cursor_right, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_right_meta: Meta = .{ .description = "Select right" };
|
||||
pub const select_right_meta: Meta = .{ .description = "Select right", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_word_left(self: *Self, _: Context) Result {
|
||||
pub fn select_word_left(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_word_left);
|
||||
try self.with_selections_const_repeat(root, move_cursor_word_left, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_word_left_meta: Meta = .{ .description = "Select left by word" };
|
||||
pub const select_word_left_meta: Meta = .{ .description = "Select left by word", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_word_left_vim(self: *Self, _: Context) Result {
|
||||
pub fn select_word_left_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_word_left_vim);
|
||||
try self.with_selections_const_repeat(root, move_cursor_word_left_vim, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_word_left_vim_meta: Meta = .{ .description = "Select left by word (vim)" };
|
||||
pub const select_word_left_vim_meta: Meta = .{ .description = "Select left by word (vim)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_word_right(self: *Self, _: Context) Result {
|
||||
pub fn select_word_right(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_word_right);
|
||||
try self.with_selections_const_repeat(root, move_cursor_word_right, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_word_right_meta: Meta = .{ .description = "Select right by word" };
|
||||
pub const select_word_right_meta: Meta = .{ .description = "Select right by word", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_word_right_vim(self: *Self, _: Context) Result {
|
||||
pub fn select_word_right_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_word_right_vim);
|
||||
try self.with_selections_const_repeat(root, move_cursor_word_right_vim, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_word_right_vim_meta: Meta = .{ .description = "Select right by word (vim)" };
|
||||
pub const select_word_right_vim_meta: Meta = .{ .description = "Select right by word (vim)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_word_right_end_vim(self: *Self, _: Context) Result {
|
||||
pub fn select_word_right_end_vim(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_word_right_end_vim);
|
||||
try self.with_selections_const_repeat(root, move_cursor_word_right_end_vim, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_word_right_end_vim_meta: Meta = .{ .description = "Select right by end of word (vim)" };
|
||||
pub const select_word_right_end_vim_meta: Meta = .{ .description = "Select right by end of word (vim)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_word_begin(self: *Self, _: Context) Result {
|
||||
pub fn select_word_begin(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_word_begin);
|
||||
try self.with_selections_const_repeat(root, move_cursor_word_begin, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_word_begin_meta: Meta = .{ .description = "Select to beginning of word" };
|
||||
pub const select_word_begin_meta: Meta = .{ .description = "Select to beginning of word", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_word_end(self: *Self, _: Context) Result {
|
||||
pub fn select_word_end(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_word_end);
|
||||
try self.with_selections_const_repeat(root, move_cursor_word_end, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_word_end_meta: Meta = .{ .description = "Select to end of word" };
|
||||
pub const select_word_end_meta: Meta = .{ .description = "Select to end of word", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_to_char_left(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
|
@ -3737,44 +3778,44 @@ pub const Editor = struct {
|
|||
}
|
||||
pub const select_to_char_right_meta: Meta = .{ .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_begin(self: *Self, _: Context) Result {
|
||||
pub fn select_begin(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_begin);
|
||||
try self.with_selections_const_repeat(root, move_cursor_begin, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_begin_meta: Meta = .{ .description = "Select to beginning of line" };
|
||||
pub const select_begin_meta: Meta = .{ .description = "Select to beginning of line", .arguments = &.{.integer} };
|
||||
|
||||
pub fn smart_select_begin(self: *Self, _: Context) Result {
|
||||
pub fn smart_select_begin(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, smart_move_cursor_begin);
|
||||
try self.with_selections_const_repeat(root, smart_move_cursor_begin, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const smart_select_begin_meta: Meta = .{ .description = "Select to beginning of line (smart)" };
|
||||
pub const smart_select_begin_meta: Meta = .{ .description = "Select to beginning of line (smart)", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_end(self: *Self, _: Context) Result {
|
||||
pub fn select_end(self: *Self, ctx: Context) Result {
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_end);
|
||||
try self.with_selections_const_repeat(root, move_cursor_end, ctx);
|
||||
self.clamp();
|
||||
}
|
||||
pub const select_end_meta: Meta = .{ .description = "Select to end of line" };
|
||||
pub const select_end_meta: Meta = .{ .description = "Select to end of line", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_buffer_begin(self: *Self, _: Context) Result {
|
||||
pub fn select_buffer_begin(self: *Self, ctx: Context) Result {
|
||||
try self.send_editor_jump_source();
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_buffer_begin);
|
||||
try self.with_selections_const_repeat(root, move_cursor_buffer_begin, ctx);
|
||||
self.clamp();
|
||||
try self.send_editor_jump_destination();
|
||||
}
|
||||
pub const select_buffer_begin_meta: Meta = .{ .description = "Select to start of file" };
|
||||
pub const select_buffer_begin_meta: Meta = .{ .description = "Select to start of file", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_buffer_end(self: *Self, _: Context) Result {
|
||||
pub fn select_buffer_end(self: *Self, ctx: Context) Result {
|
||||
try self.send_editor_jump_source();
|
||||
const root = try self.buf_root();
|
||||
try self.with_selections_const(root, move_cursor_buffer_end);
|
||||
try self.with_selections_const_repeat(root, move_cursor_buffer_end, ctx);
|
||||
self.clamp();
|
||||
try self.send_editor_jump_destination();
|
||||
}
|
||||
pub const select_buffer_end_meta: Meta = .{ .description = "Select to end of file" };
|
||||
pub const select_buffer_end_meta: Meta = .{ .description = "Select to end of file", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_page_up(self: *Self, _: Context) Result {
|
||||
try self.send_editor_jump_source();
|
||||
|
@ -5369,7 +5410,7 @@ pub const Editor = struct {
|
|||
|
||||
pub fn to_upper(self: *Self, _: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, to_upper_cursel, b.allocator);
|
||||
const root = try self.with_cursels_mut_once(b.root, to_upper_cursel, b.allocator);
|
||||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
}
|
||||
|
@ -5397,7 +5438,7 @@ pub const Editor = struct {
|
|||
|
||||
pub fn to_lower(self: *Self, _: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, to_lower_cursel, b.allocator);
|
||||
const root = try self.with_cursels_mut_once(b.root, to_lower_cursel, b.allocator);
|
||||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
}
|
||||
|
@ -5444,7 +5485,7 @@ pub const Editor = struct {
|
|||
|
||||
pub fn switch_case(self: *Self, _: Context) Result {
|
||||
const b = try self.buf_for_update();
|
||||
const root = try self.with_cursels_mut(b.root, switch_case_cursel, b.allocator);
|
||||
const root = try self.with_cursels_mut_once(b.root, switch_case_cursel, b.allocator);
|
||||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const log = @import("log");
|
||||
const tp = @import("thespian");
|
||||
const location_history = @import("location_history");
|
||||
const command = @import("command");
|
||||
const cmd = command.executeName;
|
||||
|
@ -97,7 +98,7 @@ const cmds_ = struct {
|
|||
}
|
||||
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 {
|
||||
pub fn move_next_word_start(_: *void, ctx: Ctx) Result {
|
||||
const mv = tui.mainview() orelse return;
|
||||
const ed = mv.get_active_editor() orelse return;
|
||||
const root = try ed.buf_root();
|
||||
|
@ -106,13 +107,13 @@ const cmds_ = struct {
|
|||
cursel.selection = null;
|
||||
};
|
||||
|
||||
ed.with_selections_const(root, Editor.move_cursor_word_right_vim) catch {};
|
||||
ed.with_selections_const_repeat(root, Editor.move_cursor_word_right_vim, ctx) catch {};
|
||||
ed.clamp();
|
||||
}
|
||||
|
||||
pub const move_next_word_start_meta: Meta = .{ .description = "Move next word start" };
|
||||
pub const move_next_word_start_meta: Meta = .{ .description = "Move next word start", .arguments = &.{.integer} };
|
||||
|
||||
pub fn move_prev_word_start(_: *void, _: Ctx) Result {
|
||||
pub fn move_prev_word_start(_: *void, ctx: Ctx) Result {
|
||||
const mv = tui.mainview() orelse return;
|
||||
const ed = mv.get_active_editor() orelse return;
|
||||
const root = try ed.buf_root();
|
||||
|
@ -121,10 +122,10 @@ const cmds_ = struct {
|
|||
cursel.selection = null;
|
||||
};
|
||||
|
||||
ed.with_selections_const(root, move_cursor_word_left_helix) catch {};
|
||||
ed.with_selections_const_repeat(root, move_cursor_word_left_helix, ctx) catch {};
|
||||
ed.clamp();
|
||||
}
|
||||
pub const move_prev_word_start_meta: Meta = .{ .description = "Move previous word start" };
|
||||
pub const move_prev_word_start_meta: Meta = .{ .description = "Move previous word start", .arguments = &.{.integer} };
|
||||
|
||||
pub fn cut_forward_internal_inclusive(_: *void, _: Ctx) Result {
|
||||
const mv = tui.mainview() orelse return;
|
||||
|
@ -137,56 +138,64 @@ const cmds_ = struct {
|
|||
}
|
||||
pub const cut_forward_internal_inclusive_meta: Meta = .{ .description = "Cut next character to internal clipboard (inclusive)" };
|
||||
|
||||
pub fn select_right_helix(_: *void, _: Ctx) Result {
|
||||
pub fn select_right_helix(_: *void, ctx: 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 = try cursel.enable_selection(root, ed.metrics);
|
||||
var repeat: usize = 1;
|
||||
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
|
||||
while (repeat > 0) : (repeat -= 1) {
|
||||
for (ed.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
const sel = try cursel.enable_selection(root, ed.metrics);
|
||||
|
||||
// handling left to right transition
|
||||
const sel_begin: i32 = @intCast(sel.begin.col);
|
||||
const sel_end: i32 = @intCast(sel.end.col);
|
||||
if ((sel_begin - sel_end) == 1 and sel.begin.row == sel.end.row) {
|
||||
try Editor.move_cursor_right(root, &sel.end, ed.metrics);
|
||||
sel.begin.col -= 1;
|
||||
}
|
||||
|
||||
// handling left to right transition
|
||||
const sel_begin: i32 = @intCast(sel.begin.col);
|
||||
const sel_end: i32 = @intCast(sel.end.col);
|
||||
if ((sel_begin - sel_end) == 1 and sel.begin.row == sel.end.row) {
|
||||
try Editor.move_cursor_right(root, &sel.end, ed.metrics);
|
||||
sel.begin.col -= 1;
|
||||
}
|
||||
|
||||
try Editor.move_cursor_right(root, &sel.end, ed.metrics);
|
||||
cursel.cursor = sel.end;
|
||||
cursel.check_selection(root, ed.metrics);
|
||||
};
|
||||
cursel.cursor = sel.end;
|
||||
cursel.check_selection(root, ed.metrics);
|
||||
};
|
||||
}
|
||||
ed.clamp();
|
||||
}
|
||||
pub const select_right_helix_meta: Meta = .{ .description = "Select right" };
|
||||
pub const select_right_helix_meta: Meta = .{ .description = "Select right", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_left_helix(_: *void, _: Ctx) Result {
|
||||
pub fn select_left_helix(_: *void, ctx: 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| {
|
||||
if (cursel.selection == null) {
|
||||
cursel.selection = Selection.from_cursor(&cursel.cursor);
|
||||
try cursel.selection.?.begin.move_right(root, ed.metrics);
|
||||
}
|
||||
if (cursel.selection) |*sel| {
|
||||
try Editor.move_cursor_left(root, &sel.end, ed.metrics);
|
||||
cursel.cursor = sel.end;
|
||||
|
||||
if (sel.begin.col == sel.end.col and sel.begin.row == sel.end.row) {
|
||||
try sel.begin.move_right(root, ed.metrics);
|
||||
var repeat: usize = 1;
|
||||
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
|
||||
while (repeat > 0) : (repeat -= 1) {
|
||||
for (ed.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
if (cursel.selection == null) {
|
||||
cursel.selection = Selection.from_cursor(&cursel.cursor);
|
||||
try cursel.selection.?.begin.move_right(root, ed.metrics);
|
||||
}
|
||||
if (cursel.selection) |*sel| {
|
||||
try Editor.move_cursor_left(root, &sel.end, ed.metrics);
|
||||
cursel.cursor = sel.end;
|
||||
}
|
||||
}
|
||||
|
||||
cursel.check_selection(root, ed.metrics);
|
||||
};
|
||||
if (sel.begin.col == sel.end.col and sel.begin.row == sel.end.row) {
|
||||
try sel.begin.move_right(root, ed.metrics);
|
||||
try Editor.move_cursor_left(root, &sel.end, ed.metrics);
|
||||
cursel.cursor = sel.end;
|
||||
}
|
||||
}
|
||||
|
||||
cursel.check_selection(root, ed.metrics);
|
||||
};
|
||||
}
|
||||
ed.clamp();
|
||||
}
|
||||
pub const select_left_helix_meta: Meta = .{ .description = "Select left" };
|
||||
pub const select_left_helix_meta: Meta = .{ .description = "Select left", .arguments = &.{.integer} };
|
||||
|
||||
pub fn select_to_char_right_helix(_: *void, ctx: Ctx) Result {
|
||||
const mv = tui.mainview() orelse return;
|
||||
|
|
|
@ -46,6 +46,14 @@ const cmds_ = struct {
|
|||
}
|
||||
pub const @"wq!_meta": Meta = .{ .description = "wq! (write file and quit without saving)" };
|
||||
|
||||
pub fn move_begin_or_add_integer_argument_zero(_: *void, _: Ctx) Result {
|
||||
return if (@import("keybind").current_integer_argument()) |_|
|
||||
command.executeName("add_integer_argument_digit", command.fmt(.{0}))
|
||||
else
|
||||
command.executeName("move_begin", .{});
|
||||
}
|
||||
pub const move_begin_or_add_integer_argument_zero_meta: Meta = .{ .description = "Move cursor to beginning of line (vim)" };
|
||||
|
||||
pub fn enter_mode_at_next_char(self: *void, ctx: Ctx) Result {
|
||||
_ = self; // autofix
|
||||
_ = ctx; // autofix
|
||||
|
|
|
@ -29,9 +29,12 @@ pub fn layout(_: *Self) Widget.Layout {
|
|||
var buf: [256]u8 = undefined;
|
||||
var fbs = std.io.fixedBufferStream(&buf);
|
||||
const writer = fbs.writer();
|
||||
writer.print("{}", .{keybind.current_key_event_sequence_fmt()}) catch {};
|
||||
writer.print(" ", .{}) catch {};
|
||||
if (keybind.current_integer_argument()) |integer_argument|
|
||||
writer.print("{}", .{integer_argument}) catch {};
|
||||
writer.print("{} ", .{keybind.current_key_event_sequence_fmt()}) catch {};
|
||||
const len = fbs.getWritten().len;
|
||||
return .{ .static = if (len > 0) len + 2 else 0 };
|
||||
return .{ .static = if (len > 0) len else 0 };
|
||||
}
|
||||
|
||||
pub fn render(self: *Self, theme: *const Widget.Theme) bool {
|
||||
|
@ -41,6 +44,9 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
|
|||
self.plane.set_style(theme.statusbar);
|
||||
self.plane.fill(" ");
|
||||
self.plane.home();
|
||||
_ = self.plane.print(" {} ", .{keybind.current_key_event_sequence_fmt()}) catch {};
|
||||
_ = self.plane.print(" ", .{}) catch {};
|
||||
if (keybind.current_integer_argument()) |integer_argument|
|
||||
_ = self.plane.print("{}", .{integer_argument}) catch {};
|
||||
_ = self.plane.print("{} ", .{keybind.current_key_event_sequence_fmt()}) catch {};
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ fn init(allocator: Allocator) InitError!*Self {
|
|||
|
||||
try frame_clock.start();
|
||||
try self.commands.init(self);
|
||||
try keybind.init();
|
||||
errdefer self.deinit();
|
||||
switch (builtin.os.tag) {
|
||||
.windows => {
|
||||
|
@ -658,6 +659,7 @@ fn enter_overlay_mode(self: *Self, mode: type) command.Result {
|
|||
if (self.input_mode_outer_) |_| try cmds.exit_overlay_mode(self, .{});
|
||||
self.input_mode_outer_ = self.input_mode_;
|
||||
self.input_mode_ = try mode.create(self.allocator);
|
||||
if (self.input_mode_) |*m| m.run_init();
|
||||
refresh_hover();
|
||||
}
|
||||
|
||||
|
@ -673,8 +675,7 @@ fn enter_input_mode(self: *Self, new_mode: Mode) command.Result {
|
|||
self.input_mode_ = null;
|
||||
}
|
||||
self.input_mode_ = new_mode;
|
||||
if (new_mode.init_command) |cmd|
|
||||
cmd.execute_const();
|
||||
if (self.input_mode_) |*m| m.run_init();
|
||||
}
|
||||
|
||||
fn refresh_input_mode(self: *Self) command.Result {
|
||||
|
@ -689,6 +690,7 @@ fn refresh_input_mode(self: *Self) command.Result {
|
|||
self.input_mode_ = null;
|
||||
}
|
||||
self.input_mode_ = new_mode;
|
||||
if (self.input_mode_) |*m| m.run_init();
|
||||
}
|
||||
|
||||
fn set_theme_by_name(self: *Self, name: []const u8) !void {
|
||||
|
@ -950,6 +952,7 @@ const cmds = struct {
|
|||
self.input_mode_outer_ = self.input_mode_;
|
||||
self.input_mode_ = input_mode_;
|
||||
self.mini_mode_ = mini_mode_;
|
||||
if (self.input_mode_) |*m| m.run_init();
|
||||
}
|
||||
|
||||
pub fn exit_mini_mode(self: *Self, _: Ctx) Result {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue