diff --git a/src/config/Config.zig b/src/config/Config.zig index 6cd6ad75e..e8acb9fea 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -914,7 +914,9 @@ class: ?[:0]const u8 = null, /// /// * `unbind` - Remove the binding. This makes it so the previous action /// is removed, and the key will be sent through to the child command -/// if it is printable. +/// if it is printable. Unbind will remove any matching trigger, +/// including `physical:`-prefixed triggers without specifying the +/// prefix. /// /// * `csi:text` - Send a CSI sequence. i.e. `csi:A` sends "cursor up". /// diff --git a/src/input/Binding.zig b/src/input/Binding.zig index e0ad6c571..64e07e85e 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -1528,6 +1528,22 @@ pub const Set = struct { /// Remove a binding for a given trigger. pub fn remove(self: *Set, alloc: Allocator, t: Trigger) void { + // Remove whatever this trigger is + self.removeExact(alloc, t); + + // If we have a physical we remove translated and vice versa. + const alternate: Trigger.Key = switch (t.key) { + .unicode => return, + .translated => |k| .{ .physical = k }, + .physical => |k| .{ .translated = k }, + }; + + var alt_t: Trigger = t; + alt_t.key = alternate; + self.removeExact(alloc, alt_t); + } + + fn removeExact(self: *Set, alloc: Allocator, t: Trigger) void { const entry = self.bindings.get(t) orelse return; _ = self.bindings.remove(t); @@ -1559,7 +1575,7 @@ pub const Set = struct { }, } } else { - // No over trigger points to this action so we remove + // No other trigger points to this action so we remove // the reverse mapping completely. _ = self.reverse.remove(leaf.action); } @@ -2101,6 +2117,24 @@ test "set: parseAndPut removed binding" { try testing.expect(s.getTrigger(.{ .new_window = {} }) == null); } +test "set: parseAndPut removed physical binding" { + const testing = std.testing; + const alloc = testing.allocator; + + var s: Set = .{}; + defer s.deinit(alloc); + + try s.parseAndPut(alloc, "physical:a=new_window"); + try s.parseAndPut(alloc, "a=unbind"); + + // Creates forward mapping + { + const trigger: Trigger = .{ .key = .{ .physical = .a } }; + try testing.expect(s.get(trigger) == null); + } + try testing.expect(s.getTrigger(.{ .new_window = {} }) == null); +} + test "set: parseAndPut sequence" { const testing = std.testing; const alloc = testing.allocator;