input: allow modifier aliases

Fixes #824
This commit is contained in:
Mitchell Hashimoto
2023-11-06 11:42:51 -08:00
parent 61b24a2f5c
commit 0ec225683e
2 changed files with 62 additions and 1 deletions

View File

@ -335,6 +335,11 @@ class: ?[:0]const u8 = null,
/// but valid.
/// - only a single key input is allowed, "ctrl+a+b" is invalid.
///
/// Valid modifiers are "shift", "ctrl" (alias: "control"),
/// "alt" (alias: "opt", "option"), and "super" (alias: "cmd", "command").
/// You may use the modifier or the alias. When debugging keybinds,
/// the non-aliased modifier will always be used in output.
///
/// Action is the action to take when the trigger is satisfied. It takes
/// the format "action" or "action:param". The latter form is only valid
/// if the action requires a parameter.

View File

@ -57,13 +57,27 @@ pub fn parse(raw_input: []const u8) !Binding {
if (std.mem.eql(u8, part, field.name)) {
// Repeat not allowed
if (@field(result.mods, field.name)) return Error.InvalidFormat;
@field(result.mods, field.name) = true;
continue :loop;
}
}
}
// Alias modifiers
const alias_mods = .{
.{ "cmd", "super" }, .{ "command", "super" },
.{ "opt", "alt" }, .{ "option", "alt" },
.{ "control", "ctrl" },
};
inline for (alias_mods) |pair| {
if (std.mem.eql(u8, part, pair[0])) {
// Repeat not allowed
if (@field(result.mods, pair[1])) return Error.InvalidFormat;
@field(result.mods, pair[1]) = true;
continue :loop;
}
}
// If the key starts with "physical" then this is an physical key.
const physical = "physical:";
const key_part = if (std.mem.startsWith(u8, part, physical)) key_part: {
@ -754,6 +768,48 @@ test "parse: triggers" {
try testing.expectError(Error.InvalidFormat, parse("a+b=ignore"));
}
test "parse: modifier aliases" {
const testing = std.testing;
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .super = true },
.key = .a,
},
.action = .{ .ignore = {} },
}, try parse("cmd+a=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .super = true },
.key = .a,
},
.action = .{ .ignore = {} },
}, try parse("command+a=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .alt = true },
.key = .a,
},
.action = .{ .ignore = {} },
}, try parse("opt+a=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .alt = true },
.key = .a,
},
.action = .{ .ignore = {} },
}, try parse("option+a=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .ctrl = true },
.key = .a,
},
.action = .{ .ignore = {} },
}, try parse("control+a=ignore"));
}
test "parse: action invalid" {
const testing = std.testing;