feat: add support for non string keybinding arguments

This commit is contained in:
CJ van den Berg 2024-11-17 22:41:13 +01:00
parent ed843a9baf
commit 43c49125f8
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
4 changed files with 32 additions and 15 deletions

View file

@ -18,8 +18,8 @@
.hash = "1220220dbc7fe91c1c54438193ca765cebbcb7d58f35cdcaee404a9d2245a42a4362", .hash = "1220220dbc7fe91c1c54438193ca765cebbcb7d58f35cdcaee404a9d2245a42a4362",
}, },
.thespian = .{ .thespian = .{
.url = "https://github.com/neurocyte/thespian/archive/2b380bbef442cd80842176f87517ef5726480a7a.tar.gz", .url = "https://github.com/neurocyte/thespian/archive/1691421a94e507d98c1d758e34dc6e5bcfc59bb3.tar.gz",
.hash = "122011f0b0bd6798c0575b7c8f5ec8903fe19509976aedffa5f17c6d98a4dc786de3", .hash = "1220d08c06bce0609b1078148f22aa023843ee600a67d7baa04de55d96190cd5ddb6",
}, },
.themes = .{ .themes = .{
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-5f1ca2fd3c784d430306a5cd1df237681a196333/flow-themes.tar.gz", .url = "https://github.com/neurocyte/flow-themes/releases/download/master-5f1ca2fd3c784d430306a5cd1df237681a196333/flow-themes.tar.gz",

View file

@ -215,36 +215,45 @@ const BindingSet = struct {
} }
} }
fn load_set_from_json(self: *BindingSet, mode_bindings: std.json.Value) !void { fn load_set_from_json(self: *BindingSet, mode_bindings: std.json.Value) (parse_flow.ParseError || parse_vim.ParseError || std.json.ParseFromValueError)!void {
const JsonConfig = struct { const JsonConfig = struct {
bindings: []const []const []const u8, bindings: []const []const std.json.Value,
syntax: KeySyntax, syntax: KeySyntax,
on_match_failure: OnMatchFailure, on_match_failure: OnMatchFailure,
}; };
const parsed = try std.json.parseFromValue(JsonConfig, self.allocator, mode_bindings, .{}); const parsed = try std.json.parseFromValue(JsonConfig, self.allocator, mode_bindings, .{
.ignore_unknown_fields = true,
});
defer parsed.deinit(); defer parsed.deinit();
self.syntax = parsed.value.syntax; self.syntax = parsed.value.syntax;
self.on_match_failure = parsed.value.on_match_failure; self.on_match_failure = parsed.value.on_match_failure;
for (parsed.value.bindings) |entry| { bindings: for (parsed.value.bindings) |entry| {
var state: enum { key_event, command, args } = .key_event; var state: enum { key_event, command, args } = .key_event;
var keys: ?[]KeyEvent = null; var keys: ?[]KeyEvent = null;
var command_: ?[]const u8 = null; var command_: ?[]const u8 = null;
var args = std.ArrayListUnmanaged([]const u8){}; var args = std.ArrayListUnmanaged(std.json.Value){};
defer { defer {
if (keys) |p| self.allocator.free(p); if (keys) |p| self.allocator.free(p);
if (command_) |p| self.allocator.free(p); if (command_) |p| self.allocator.free(p);
for (args.items) |p| self.allocator.free(p);
args.deinit(self.allocator); args.deinit(self.allocator);
} }
for (entry) |token| { for (entry) |token| {
switch (state) { switch (state) {
.key_event => { .key_event => {
if (token != .string) {
self.logger.print_err("keybind.load", "ERROR: invalid binding key token {any} in '{s}' mode '{s}' ", .{
token,
self.namespace_name,
self.mode_name,
});
continue :bindings;
}
keys = switch (self.syntax) { keys = switch (self.syntax) {
.flow => parse_flow.parse_key_events(self.allocator, token) catch |e| { .flow => parse_flow.parse_key_events(self.allocator, token.string) catch |e| {
self.logger.print_err("keybind.load", "ERROR: {s} {s}", .{ @errorName(e), parse_flow.parse_error_message }); self.logger.print_err("keybind.load", "ERROR: {s} {s}", .{ @errorName(e), parse_flow.parse_error_message });
break; break;
}, },
.vim => parse_vim.parse_key_events(self.allocator, token) catch |e| { .vim => parse_vim.parse_key_events(self.allocator, token.string) catch |e| {
self.logger.print_err("keybind.load.vim", "ERROR: {s} {s}", .{ @errorName(e), parse_vim.parse_error_message }); self.logger.print_err("keybind.load.vim", "ERROR: {s} {s}", .{ @errorName(e), parse_vim.parse_error_message });
break; break;
}, },
@ -252,11 +261,19 @@ const BindingSet = struct {
state = .command; state = .command;
}, },
.command => { .command => {
command_ = try self.allocator.dupe(u8, token); if (token != .string) {
self.logger.print_err("keybind.load", "ERROR: invalid binding command token {any} in '{s}' mode '{s}' ", .{
token,
self.namespace_name,
self.mode_name,
});
continue :bindings;
}
command_ = try self.allocator.dupe(u8, token.string);
state = .args; state = .args;
}, },
.args => { .args => {
try args.append(self.allocator, try self.allocator.dupe(u8, token)); try args.append(self.allocator, token);
}, },
} }
} }
@ -268,7 +285,7 @@ const BindingSet = struct {
defer args_cbor.deinit(self.allocator); defer args_cbor.deinit(self.allocator);
const writer = args_cbor.writer(self.allocator); const writer = args_cbor.writer(self.allocator);
try cbor.writeArrayHeader(writer, args.items.len); try cbor.writeArrayHeader(writer, args.items.len);
for (args.items) |arg| try cbor.writeValue(writer, arg); for (args.items) |arg| try cbor.writeJsonValue(writer, arg);
try self.bindings.append(.{ try self.bindings.append(.{
.keys = keys.?, .keys = keys.?,

View file

@ -2,7 +2,7 @@ const std = @import("std");
const input = @import("input"); const input = @import("input");
const KeyEvent = @import("KeyEvent.zig"); const KeyEvent = @import("KeyEvent.zig");
const ParseError = error{ pub const ParseError = error{
OutOfMemory, OutOfMemory,
InvalidFormat, InvalidFormat,
}; };

View file

@ -8,7 +8,7 @@ fn peek(str: []const u8, i: usize) error{OutOfBounds}!u8 {
} else return error.OutOfBounds; } else return error.OutOfBounds;
} }
const ParseError = error{ pub const ParseError = error{
OutOfMemory, OutOfMemory,
OutOfBounds, OutOfBounds,
InvalidEscapeSequenceStart, InvalidEscapeSequenceStart,