input: return a K/V entry for the binding set get

This commit is contained in:
Mitchell Hashimoto
2024-10-08 06:29:31 -10:00
parent 78d6cfb620
commit 8d7367fa64
3 changed files with 31 additions and 24 deletions

View File

@ -318,7 +318,7 @@ pub fn keyEvent(
// Get the keybind entry for this event. We don't support key sequences // Get the keybind entry for this event. We don't support key sequences
// so we can look directly in the top-level set. // so we can look directly in the top-level set.
const entry = rt_app.config.keybind.set.getEvent(event) orelse return false; 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 // Sequences aren't supported. Our configuration parser verifies
// this for global keybinds but we may still get an entry for // this for global keybinds but we may still get an entry for
// a non-global keybind. // a non-global keybind.

View File

@ -1697,7 +1697,7 @@ fn maybeHandleBinding(
}; };
// Determine if this entry has an action or if its a leader key. // 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| { .leader => |set| {
// Setup the next set we'll look at. // Setup the next set we'll look at.
self.keyboard.bindings = set; self.keyboard.bindings = set;

View File

@ -1020,7 +1020,7 @@ pub const Trigger = struct {
pub const Set = struct { pub const Set = struct {
const HashMap = std.HashMapUnmanaged( const HashMap = std.HashMapUnmanaged(
Trigger, Trigger,
Entry, Value,
Context(Trigger), Context(Trigger),
std.hash_map.default_max_load_percentage, std.hash_map.default_max_load_percentage,
); );
@ -1046,7 +1046,7 @@ pub const Set = struct {
reverse: ReverseMap = .{}, reverse: ReverseMap = .{},
/// The entry type for the forward mapping of trigger to action. /// 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 /// This key is a leader key in a sequence. You must follow the given
/// set to find the next key in the sequence. /// set to find the next key in the sequence.
leader: *Set, leader: *Set,
@ -1058,7 +1058,7 @@ pub const Set = struct {
/// Implements the formatter for the fmt package. This encodes the /// Implements the formatter for the fmt package. This encodes the
/// action back into the format used by parse. /// action back into the format used by parse.
pub fn format( pub fn format(
self: Entry, self: Value,
comptime layout: []const u8, comptime layout: []const u8,
opts: std.fmt.FormatOptions, opts: std.fmt.FormatOptions,
writer: anytype, 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 { pub fn deinit(self: *Set, alloc: Allocator) void {
// Clear any leaders if we have them // Clear any leaders if we have them
var it = self.bindings.iterator(); var it = self.bindings.iterator();
@ -1160,7 +1163,11 @@ pub const Set = struct {
switch (elem) { switch (elem) {
.leader => |t| { .leader => |t| {
// If we have a leader, we need to upsert a set for it. // 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) { if (old) |entry| switch (entry) {
// We have an existing leader for this key already // We have an existing leader for this key already
// so recurse into this set. // so recurse into this set.
@ -1289,7 +1296,7 @@ pub const Set = struct {
/// Get a binding for a given trigger. /// Get a binding for a given trigger.
pub fn get(self: Set, t: Trigger) ?Entry { 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 /// Get a trigger for the given action. An action can have multiple
@ -1811,7 +1818,7 @@ test "set: parseAndPut typical binding" {
// Creates forward mapping // 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.expect(action.action == .new_window);
try testing.expectEqual(Flags{}, action.flags); try testing.expectEqual(Flags{}, action.flags);
} }
@ -1835,7 +1842,7 @@ test "set: parseAndPut unconsumed binding" {
// Creates forward mapping // Creates forward mapping
{ {
const trigger: Trigger = .{ .key = .{ .translated = .a } }; 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.expect(action.action == .new_window);
try testing.expectEqual(Flags{ .consumed = false }, action.flags); try testing.expectEqual(Flags{ .consumed = false }, action.flags);
} }
@ -1876,13 +1883,13 @@ test "set: parseAndPut sequence" {
var current: *Set = &s; var current: *Set = &s;
{ {
const t: Trigger = .{ .key = .{ .translated = .a } }; const t: Trigger = .{ .key = .{ .translated = .a } };
const e = current.get(t).?; const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leader); try testing.expect(e == .leader);
current = e.leader; current = e.leader;
} }
{ {
const t: Trigger = .{ .key = .{ .translated = .b } }; 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);
try testing.expect(e.leaf.action == .new_window); try testing.expect(e.leaf.action == .new_window);
try testing.expectEqual(Flags{}, e.leaf.flags); try testing.expectEqual(Flags{}, e.leaf.flags);
@ -1901,20 +1908,20 @@ test "set: parseAndPut sequence with two actions" {
var current: *Set = &s; var current: *Set = &s;
{ {
const t: Trigger = .{ .key = .{ .translated = .a } }; const t: Trigger = .{ .key = .{ .translated = .a } };
const e = current.get(t).?; const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leader); try testing.expect(e == .leader);
current = e.leader; current = e.leader;
} }
{ {
const t: Trigger = .{ .key = .{ .translated = .b } }; 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);
try testing.expect(e.leaf.action == .new_window); try testing.expect(e.leaf.action == .new_window);
try testing.expectEqual(Flags{}, e.leaf.flags); try testing.expectEqual(Flags{}, e.leaf.flags);
} }
{ {
const t: Trigger = .{ .key = .{ .translated = .c } }; 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);
try testing.expect(e.leaf.action == .new_tab); try testing.expect(e.leaf.action == .new_tab);
try testing.expectEqual(Flags{}, e.leaf.flags); try testing.expectEqual(Flags{}, e.leaf.flags);
@ -1933,13 +1940,13 @@ test "set: parseAndPut overwrite sequence" {
var current: *Set = &s; var current: *Set = &s;
{ {
const t: Trigger = .{ .key = .{ .translated = .a } }; const t: Trigger = .{ .key = .{ .translated = .a } };
const e = current.get(t).?; const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leader); try testing.expect(e == .leader);
current = e.leader; current = e.leader;
} }
{ {
const t: Trigger = .{ .key = .{ .translated = .b } }; 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);
try testing.expect(e.leaf.action == .new_window); try testing.expect(e.leaf.action == .new_window);
try testing.expectEqual(Flags{}, e.leaf.flags); try testing.expectEqual(Flags{}, e.leaf.flags);
@ -1958,13 +1965,13 @@ test "set: parseAndPut overwrite leader" {
var current: *Set = &s; var current: *Set = &s;
{ {
const t: Trigger = .{ .key = .{ .translated = .a } }; const t: Trigger = .{ .key = .{ .translated = .a } };
const e = current.get(t).?; const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leader); try testing.expect(e == .leader);
current = e.leader; current = e.leader;
} }
{ {
const t: Trigger = .{ .key = .{ .translated = .b } }; 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);
try testing.expect(e.leaf.action == .new_window); try testing.expect(e.leaf.action == .new_window);
try testing.expectEqual(Flags{}, e.leaf.flags); try testing.expectEqual(Flags{}, e.leaf.flags);
@ -2096,8 +2103,8 @@ test "set: consumed state" {
defer s.deinit(alloc); defer s.deinit(alloc);
try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} }); 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 } }).?.value_ptr.* == .leaf);
try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.leaf.flags.consumed); try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed);
try s.putFlags( try s.putFlags(
alloc, alloc,
@ -2105,10 +2112,10 @@ test "set: consumed state" {
.{ .new_window = {} }, .{ .new_window = {} },
.{ .consumed = false }, .{ .consumed = false },
); );
try testing.expect(s.get(.{ .key = .{ .translated = .a } }).? == .leaf); try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.* == .leaf);
try testing.expect(!s.get(.{ .key = .{ .translated = .a } }).?.leaf.flags.consumed); try testing.expect(!s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed);
try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} }); 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 } }).?.value_ptr.* == .leaf);
try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.leaf.flags.consumed); try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed);
} }