mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-05 17:36:32 +00:00
binding parse action with parameter
This commit is contained in:
44
src/key.zig
44
src/key.zig
@@ -20,6 +20,9 @@ pub const Binding = struct {
|
||||
/// modifiers and keys. Action is the action name and optionally a
|
||||
/// parameter after a colon, i.e. "csi:A" or "ignore".
|
||||
pub fn parse(input: []const u8) !Binding {
|
||||
// NOTE(mitchellh): This is not the most efficient way to do any
|
||||
// of this, I welcome any improvements here!
|
||||
|
||||
// Find the first = which splits are mapping into the trigger
|
||||
// and action, respectively.
|
||||
const eqlIdx = std.mem.indexOf(u8, input, "=") orelse return Error.InvalidFormat;
|
||||
@@ -66,6 +69,8 @@ pub const Binding = struct {
|
||||
return Error.InvalidFormat;
|
||||
}
|
||||
|
||||
// Find a matching action
|
||||
result.action = action: {
|
||||
// Split our action by colon. A colon may not exist for some
|
||||
// actions so it is optional. The part preceding the colon is the
|
||||
// action name.
|
||||
@@ -76,18 +81,30 @@ pub const Binding = struct {
|
||||
// An action name is always required
|
||||
if (action.len == 0) return Error.InvalidFormat;
|
||||
|
||||
// Find a matching action
|
||||
const actionInfo = @typeInfo(Action).Union;
|
||||
inline for (actionInfo.fields) |field| {
|
||||
if (std.mem.eql(u8, action, field.name)) {
|
||||
// If the field type is void we expect no value
|
||||
if (field.field_type == void) {
|
||||
switch (field.field_type) {
|
||||
void => {
|
||||
if (colonIdx != null) return Error.InvalidFormat;
|
||||
result.action = @unionInit(Action, field.name, {});
|
||||
break :action @unionInit(Action, field.name, {});
|
||||
},
|
||||
|
||||
[]const u8 => {
|
||||
const idx = colonIdx orelse return Error.InvalidFormat;
|
||||
const param = actionRaw[idx + 1 ..];
|
||||
break :action @unionInit(Action, field.name, param);
|
||||
},
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Error.InvalidFormat;
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -135,6 +152,27 @@ pub const Binding = struct {
|
||||
// multiple character
|
||||
try testing.expectError(Error.InvalidFormat, parse("a+b=ignore"));
|
||||
}
|
||||
|
||||
test "parse: action" {
|
||||
const testing = std.testing;
|
||||
|
||||
// invalid action
|
||||
try testing.expectError(Error.InvalidFormat, parse("a=nopenopenope"));
|
||||
|
||||
// no parameters
|
||||
try testing.expectEqual(
|
||||
Binding{ .key = .a, .action = .{ .ignore = {} } },
|
||||
try parse("a=ignore"),
|
||||
);
|
||||
try testing.expectError(Error.InvalidFormat, parse("a=ignore:A"));
|
||||
|
||||
// parameter
|
||||
{
|
||||
const binding = try parse("a=csi:A");
|
||||
try testing.expect(binding.action == .csi);
|
||||
try testing.expectEqualStrings("A", binding.action.csi);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// The set of actions that a keybinding can take.
|
||||
|
Reference in New Issue
Block a user