From 8d7367fa645ee53d559a6bb0c700308219e19bb3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 8 Oct 2024 06:29:31 -1000 Subject: [PATCH] input: return a K/V entry for the binding set `get` --- src/App.zig | 2 +- src/Surface.zig | 2 +- src/input/Binding.zig | 51 ++++++++++++++++++++++++------------------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/App.zig b/src/App.zig index 599265a44..0d09fed58 100644 --- a/src/App.zig +++ b/src/App.zig @@ -318,7 +318,7 @@ pub fn keyEvent( // Get the keybind entry for this event. We don't support key sequences // so we can look directly in the top-level set. const entry = rt_app.config.keybind.set.getEvent(event) orelse return false; - const leaf: input.Binding.Set.Leaf = switch (entry) { + const leaf: input.Binding.Set.Leaf = switch (entry.value_ptr.*) { // Sequences aren't supported. Our configuration parser verifies // this for global keybinds but we may still get an entry for // a non-global keybind. diff --git a/src/Surface.zig b/src/Surface.zig index 3e2aa3d95..ac941ef89 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -1697,7 +1697,7 @@ fn maybeHandleBinding( }; // Determine if this entry has an action or if its a leader key. - const leaf: input.Binding.Set.Leaf = switch (entry) { + const leaf: input.Binding.Set.Leaf = switch (entry.value_ptr.*) { .leader => |set| { // Setup the next set we'll look at. self.keyboard.bindings = set; diff --git a/src/input/Binding.zig b/src/input/Binding.zig index 9667f2d17..30984b0de 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -1020,7 +1020,7 @@ pub const Trigger = struct { pub const Set = struct { const HashMap = std.HashMapUnmanaged( Trigger, - Entry, + Value, Context(Trigger), std.hash_map.default_max_load_percentage, ); @@ -1046,7 +1046,7 @@ pub const Set = struct { reverse: ReverseMap = .{}, /// The entry type for the forward mapping of trigger to action. - pub const Entry = union(enum) { + pub const Value = union(enum) { /// This key is a leader key in a sequence. You must follow the given /// set to find the next key in the sequence. leader: *Set, @@ -1058,7 +1058,7 @@ pub const Set = struct { /// Implements the formatter for the fmt package. This encodes the /// action back into the format used by parse. pub fn format( - self: Entry, + self: Value, comptime layout: []const u8, opts: std.fmt.FormatOptions, writer: anytype, @@ -1100,6 +1100,9 @@ pub const Set = struct { } }; + /// A full key-value entry for the set. + pub const Entry = HashMap.Entry; + pub fn deinit(self: *Set, alloc: Allocator) void { // Clear any leaders if we have them var it = self.bindings.iterator(); @@ -1160,7 +1163,11 @@ pub const Set = struct { switch (elem) { .leader => |t| { // If we have a leader, we need to upsert a set for it. - const old = set.get(t); + // Since we remove the value, we need to copy it. + const old: ?Value = if (set.get(t)) |entry| + entry.value_ptr.* + else + null; if (old) |entry| switch (entry) { // We have an existing leader for this key already // so recurse into this set. @@ -1289,7 +1296,7 @@ pub const Set = struct { /// Get a binding for a given trigger. pub fn get(self: Set, t: Trigger) ?Entry { - return self.bindings.get(t); + return self.bindings.getEntry(t); } /// Get a trigger for the given action. An action can have multiple @@ -1811,7 +1818,7 @@ test "set: parseAndPut typical binding" { // Creates forward mapping { - const action = s.get(.{ .key = .{ .translated = .a } }).?.leaf; + const action = s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf; try testing.expect(action.action == .new_window); try testing.expectEqual(Flags{}, action.flags); } @@ -1835,7 +1842,7 @@ test "set: parseAndPut unconsumed binding" { // Creates forward mapping { const trigger: Trigger = .{ .key = .{ .translated = .a } }; - const action = s.get(trigger).?.leaf; + const action = s.get(trigger).?.value_ptr.*.leaf; try testing.expect(action.action == .new_window); try testing.expectEqual(Flags{ .consumed = false }, action.flags); } @@ -1876,13 +1883,13 @@ test "set: parseAndPut sequence" { var current: *Set = &s; { const t: Trigger = .{ .key = .{ .translated = .a } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leader); current = e.leader; } { const t: Trigger = .{ .key = .{ .translated = .b } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leaf); try testing.expect(e.leaf.action == .new_window); try testing.expectEqual(Flags{}, e.leaf.flags); @@ -1901,20 +1908,20 @@ test "set: parseAndPut sequence with two actions" { var current: *Set = &s; { const t: Trigger = .{ .key = .{ .translated = .a } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leader); current = e.leader; } { const t: Trigger = .{ .key = .{ .translated = .b } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leaf); try testing.expect(e.leaf.action == .new_window); try testing.expectEqual(Flags{}, e.leaf.flags); } { const t: Trigger = .{ .key = .{ .translated = .c } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leaf); try testing.expect(e.leaf.action == .new_tab); try testing.expectEqual(Flags{}, e.leaf.flags); @@ -1933,13 +1940,13 @@ test "set: parseAndPut overwrite sequence" { var current: *Set = &s; { const t: Trigger = .{ .key = .{ .translated = .a } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leader); current = e.leader; } { const t: Trigger = .{ .key = .{ .translated = .b } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leaf); try testing.expect(e.leaf.action == .new_window); try testing.expectEqual(Flags{}, e.leaf.flags); @@ -1958,13 +1965,13 @@ test "set: parseAndPut overwrite leader" { var current: *Set = &s; { const t: Trigger = .{ .key = .{ .translated = .a } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leader); current = e.leader; } { const t: Trigger = .{ .key = .{ .translated = .b } }; - const e = current.get(t).?; + const e = current.get(t).?.value_ptr.*; try testing.expect(e == .leaf); try testing.expect(e.leaf.action == .new_window); try testing.expectEqual(Flags{}, e.leaf.flags); @@ -2096,8 +2103,8 @@ test "set: consumed state" { defer s.deinit(alloc); try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} }); - try testing.expect(s.get(.{ .key = .{ .translated = .a } }).? == .leaf); - try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.leaf.flags.consumed); + try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.* == .leaf); + try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed); try s.putFlags( alloc, @@ -2105,10 +2112,10 @@ test "set: consumed state" { .{ .new_window = {} }, .{ .consumed = false }, ); - try testing.expect(s.get(.{ .key = .{ .translated = .a } }).? == .leaf); - try testing.expect(!s.get(.{ .key = .{ .translated = .a } }).?.leaf.flags.consumed); + try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.* == .leaf); + try testing.expect(!s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed); try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} }); - try testing.expect(s.get(.{ .key = .{ .translated = .a } }).? == .leaf); - try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.leaf.flags.consumed); + try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.* == .leaf); + try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed); }