From 43c49125f8ce9f86fb0ce55b56ada8ed41b95836 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Sun, 17 Nov 2024 22:41:13 +0100 Subject: [PATCH] feat: add support for non string keybinding arguments --- build.zig.zon | 4 +-- src/keybind/dynamic/keybind.zig | 39 +++++++++++++++++++++--------- src/keybind/dynamic/parse_flow.zig | 2 +- src/keybind/dynamic/parse_vim.zig | 2 +- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index d8b5617..0c6ccb6 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -18,8 +18,8 @@ .hash = "1220220dbc7fe91c1c54438193ca765cebbcb7d58f35cdcaee404a9d2245a42a4362", }, .thespian = .{ - .url = "https://github.com/neurocyte/thespian/archive/2b380bbef442cd80842176f87517ef5726480a7a.tar.gz", - .hash = "122011f0b0bd6798c0575b7c8f5ec8903fe19509976aedffa5f17c6d98a4dc786de3", + .url = "https://github.com/neurocyte/thespian/archive/1691421a94e507d98c1d758e34dc6e5bcfc59bb3.tar.gz", + .hash = "1220d08c06bce0609b1078148f22aa023843ee600a67d7baa04de55d96190cd5ddb6", }, .themes = .{ .url = "https://github.com/neurocyte/flow-themes/releases/download/master-5f1ca2fd3c784d430306a5cd1df237681a196333/flow-themes.tar.gz", diff --git a/src/keybind/dynamic/keybind.zig b/src/keybind/dynamic/keybind.zig index 4da6a63..df2d577 100644 --- a/src/keybind/dynamic/keybind.zig +++ b/src/keybind/dynamic/keybind.zig @@ -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 { - bindings: []const []const []const u8, + bindings: []const []const std.json.Value, syntax: KeySyntax, 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(); self.syntax = parsed.value.syntax; 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 keys: ?[]KeyEvent = null; var command_: ?[]const u8 = null; - var args = std.ArrayListUnmanaged([]const u8){}; + var args = std.ArrayListUnmanaged(std.json.Value){}; defer { if (keys) |p| self.allocator.free(p); if (command_) |p| self.allocator.free(p); - for (args.items) |p| self.allocator.free(p); args.deinit(self.allocator); } for (entry) |token| { switch (state) { .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) { - .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 }); 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 }); break; }, @@ -252,11 +261,19 @@ const BindingSet = struct { state = .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; }, .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); const writer = args_cbor.writer(self.allocator); 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(.{ .keys = keys.?, diff --git a/src/keybind/dynamic/parse_flow.zig b/src/keybind/dynamic/parse_flow.zig index 4b5f8c0..8b31938 100644 --- a/src/keybind/dynamic/parse_flow.zig +++ b/src/keybind/dynamic/parse_flow.zig @@ -2,7 +2,7 @@ const std = @import("std"); const input = @import("input"); const KeyEvent = @import("KeyEvent.zig"); -const ParseError = error{ +pub const ParseError = error{ OutOfMemory, InvalidFormat, }; diff --git a/src/keybind/dynamic/parse_vim.zig b/src/keybind/dynamic/parse_vim.zig index 3298c48..a05cba3 100644 --- a/src/keybind/dynamic/parse_vim.zig +++ b/src/keybind/dynamic/parse_vim.zig @@ -8,7 +8,7 @@ fn peek(str: []const u8, i: usize) error{OutOfBounds}!u8 { } else return error.OutOfBounds; } -const ParseError = error{ +pub const ParseError = error{ OutOfMemory, OutOfBounds, InvalidEscapeSequenceStart,