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
// 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.

View File

@ -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;

View File

@ -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);
}