feat: add support for command sequence bindings
This commit is contained in:
parent
98062f669d
commit
b693b111b2
1 changed files with 51 additions and 11 deletions
|
@ -272,7 +272,21 @@ const Command = struct {
|
||||||
command_ = try allocator.dupe(u8, token.string);
|
command_ = try allocator.dupe(u8, token.string);
|
||||||
state = .args;
|
state = .args;
|
||||||
},
|
},
|
||||||
.args => try args.append(allocator, token),
|
.args => {
|
||||||
|
switch (token) {
|
||||||
|
.string, .integer, .float, .bool => {},
|
||||||
|
else => {
|
||||||
|
var json = std.ArrayList(u8).init(allocator);
|
||||||
|
defer json.deinit();
|
||||||
|
std.json.stringify(token, .{}, json.writer()) catch {};
|
||||||
|
const logger = log.logger("keybind");
|
||||||
|
logger.print_err("keybind.load", "ERROR: invalid command argument '{s}'", .{json.items});
|
||||||
|
logger.deinit();
|
||||||
|
return error.InvalidFormat;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
try args.append(allocator, token);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +305,7 @@ const Command = struct {
|
||||||
//An association of an command with a triggering key chord
|
//An association of an command with a triggering key chord
|
||||||
const Binding = struct {
|
const Binding = struct {
|
||||||
key_events: []KeyEvent,
|
key_events: []KeyEvent,
|
||||||
command: Command,
|
commands: []Command,
|
||||||
|
|
||||||
fn len(self: Binding) usize {
|
fn len(self: Binding) usize {
|
||||||
return self.key_events.items.len;
|
return self.key_events.items.len;
|
||||||
|
@ -365,22 +379,28 @@ const BindingSet = struct {
|
||||||
|
|
||||||
fn load_event(self: *BindingSet, allocator: std.mem.Allocator, dest: *std.ArrayListUnmanaged(Binding), event: input.Event, bindings: []const []const std.json.Value) (parse_flow.ParseError || parse_vim.ParseError)!void {
|
fn load_event(self: *BindingSet, allocator: std.mem.Allocator, dest: *std.ArrayListUnmanaged(Binding), event: input.Event, bindings: []const []const std.json.Value) (parse_flow.ParseError || parse_vim.ParseError)!void {
|
||||||
bindings: for (bindings) |entry| {
|
bindings: for (bindings) |entry| {
|
||||||
const token = entry[0];
|
if (entry.len < 2) {
|
||||||
if (token != .string) {
|
|
||||||
const logger = log.logger("keybind");
|
const logger = log.logger("keybind");
|
||||||
logger.print_err("keybind.load", "ERROR: invalid binding key token {any}", .{token});
|
logger.print_err("keybind.load", "ERROR: invalid binding definition {any}", .{entry});
|
||||||
|
logger.deinit();
|
||||||
|
continue :bindings;
|
||||||
|
}
|
||||||
|
const keys = entry[0];
|
||||||
|
if (keys != .string) {
|
||||||
|
const logger = log.logger("keybind");
|
||||||
|
logger.print_err("keybind.load", "ERROR: invalid binding key definition {any}", .{keys});
|
||||||
logger.deinit();
|
logger.deinit();
|
||||||
continue :bindings;
|
continue :bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const key_events = switch (self.syntax) {
|
const key_events = switch (self.syntax) {
|
||||||
.flow => parse_flow.parse_key_events(allocator, event, token.string) catch |e| {
|
.flow => parse_flow.parse_key_events(allocator, event, keys.string) catch |e| {
|
||||||
const logger = log.logger("keybind");
|
const logger = log.logger("keybind");
|
||||||
logger.print_err("keybind.load", "ERROR: {s} {s}", .{ @errorName(e), parse_flow.parse_error_message });
|
logger.print_err("keybind.load", "ERROR: {s} {s}", .{ @errorName(e), parse_flow.parse_error_message });
|
||||||
logger.deinit();
|
logger.deinit();
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
.vim => parse_vim.parse_key_events(allocator, event, token.string) catch |e| {
|
.vim => parse_vim.parse_key_events(allocator, event, keys.string) catch |e| {
|
||||||
const logger = log.logger("keybind");
|
const logger = log.logger("keybind");
|
||||||
logger.print_err("keybind.load.vim", "ERROR: {s} {s}", .{ @errorName(e), parse_vim.parse_error_message });
|
logger.print_err("keybind.load.vim", "ERROR: {s} {s}", .{ @errorName(e), parse_vim.parse_error_message });
|
||||||
logger.deinit();
|
logger.deinit();
|
||||||
|
@ -389,9 +409,28 @@ const BindingSet = struct {
|
||||||
};
|
};
|
||||||
errdefer allocator.free(key_events);
|
errdefer allocator.free(key_events);
|
||||||
|
|
||||||
|
const cmd = entry[1];
|
||||||
|
var cmds = std.ArrayList(Command).init(allocator);
|
||||||
|
defer cmds.deinit();
|
||||||
|
if (cmd == .string) {
|
||||||
|
try cmds.append(try Command.load(allocator, entry[1..]));
|
||||||
|
} else {
|
||||||
|
for (entry[1..]) |cmd_entry| {
|
||||||
|
if (cmd_entry != .array) {
|
||||||
|
var json = std.ArrayList(u8).init(allocator);
|
||||||
|
defer json.deinit();
|
||||||
|
std.json.stringify(cmd_entry, .{}, json.writer()) catch {};
|
||||||
|
const logger = log.logger("keybind");
|
||||||
|
logger.print_err("keybind.load", "ERROR: invalid command definition {s}", .{json.items});
|
||||||
|
logger.deinit();
|
||||||
|
continue :bindings;
|
||||||
|
}
|
||||||
|
try cmds.append(try Command.load(allocator, cmd_entry.array.items));
|
||||||
|
}
|
||||||
|
}
|
||||||
try dest.append(allocator, .{
|
try dest.append(allocator, .{
|
||||||
.key_events = key_events,
|
.key_events = key_events,
|
||||||
.command = try Command.load(allocator, entry[1..]),
|
.commands = try cmds.toOwnedSlice(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +452,8 @@ const BindingSet = struct {
|
||||||
const hints_map = &self.hints_map;
|
const hints_map = &self.hints_map;
|
||||||
|
|
||||||
for (self.press.items) |binding| {
|
for (self.press.items) |binding| {
|
||||||
var hint = if (hints_map.get(binding.command.command)) |previous|
|
const cmd = binding.commands[0].command;
|
||||||
|
var hint = if (hints_map.get(cmd)) |previous|
|
||||||
std.ArrayList(u8).fromOwnedSlice(allocator, previous)
|
std.ArrayList(u8).fromOwnedSlice(allocator, previous)
|
||||||
else
|
else
|
||||||
std.ArrayList(u8).init(allocator);
|
std.ArrayList(u8).init(allocator);
|
||||||
|
@ -433,7 +473,7 @@ const BindingSet = struct {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try hints_map.put(allocator, binding.command.command, try hint.toOwnedSlice());
|
try hints_map.put(allocator, cmd, try hint.toOwnedSlice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +523,7 @@ const BindingSet = struct {
|
||||||
.key = keypress,
|
.key = keypress,
|
||||||
.modifiers = modifiers,
|
.modifiers = modifiers,
|
||||||
}) catch |e| return tp.exit_error(e, @errorReturnTrace())) |binding| {
|
}) catch |e| return tp.exit_error(e, @errorReturnTrace())) |binding| {
|
||||||
try binding.command.execute();
|
for (binding.commands) |*cmd| try cmd.execute();
|
||||||
}
|
}
|
||||||
} else if (try m.match(.{"F"})) {
|
} else if (try m.match(.{"F"})) {
|
||||||
self.flush() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
self.flush() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
|
|
Loading…
Add table
Reference in a new issue