feat: improve logging of keybind parsing errors

This commit is contained in:
CJ van den Berg 2024-11-15 22:06:24 +01:00
parent 14167d7869
commit f016277621
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9

View file

@ -81,13 +81,50 @@ pub const Mode = struct {
pub const KeybindHints = std.static_string_map.StaticStringMap([]const u8); pub const KeybindHints = std.static_string_map.StaticStringMap([]const u8);
fn peek(str: []const u8, i: usize) !u8 { fn peek(str: []const u8, i: usize) error{OutOfBounds}!u8 {
if (i + 1 < str.len) { if (i + 1 < str.len) {
return str[i + 1]; return str[i + 1];
} else return error.outOfBounds; } else return error.OutOfBounds;
} }
pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEvent { const ParseError = error{
OutOfMemory,
OutOfBounds,
InvalidEscapeSequenceStart,
InvalidInitialCharacter,
InvalidStartOfControlBinding,
InvalidStartOfShiftBinding,
InvalidStartOfDeleteBinding,
InvalidCRBinding,
InvalidSpaceBinding,
InvalidDeleteBinding,
InvalidTabBinding,
InvalidUpBinding,
InvalidEscapeBinding,
InvalidDownBinding,
InvalidLeftBinding,
InvalidRightBinding,
InvalidFunctionKeyNumber,
InvalidFunctionKeyBinding,
InvalidEscapeSequenceDelimiter,
InvalidModifier,
InvalidEscapeSequenceEnd,
};
var parse_error_buf: [256]u8 = undefined;
var parse_error_message: []const u8 = "";
fn parse_error_reset() void {
parse_error_message = "";
}
fn parse_error(e: ParseError, comptime format: anytype, args: anytype) ParseError {
parse_error_message = std.fmt.bufPrint(&parse_error_buf, format, args) catch "error in parse_error";
return e;
}
fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ParseError![]KeyEvent {
parse_error_reset();
const State = enum { const State = enum {
base, base,
escape_sequence_start, escape_sequence_start,
@ -125,9 +162,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
try result.append(.{ .key = str[i] }); try result.append(.{ .key = str[i] });
i += 1; i += 1;
}, },
else => { else => return parse_error(error.InvalidInitialCharacter, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
return error.parseBase;
},
} }
}, },
.escape_sequence_start => { .escape_sequence_start => {
@ -143,9 +178,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
'-' => { '-' => {
state = .modifier; state = .modifier;
}, },
else => { else => return parse_error(error.InvalidStartOfControlBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
return error.parseEscapeSequenceStartC;
},
} }
}, },
'S' => { 'S' => {
@ -156,7 +189,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
'p' => { 'p' => {
state = .space; state = .space;
}, },
else => return error.parseEscapeSequenceStartS, else => return parse_error(error.InvalidStartOfShiftBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
} }
}, },
'F' => { 'F' => {
@ -189,13 +222,10 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
'e' => { 'e' => {
state = .del; state = .del;
}, },
else => return error.parseEscapeSequenceStartD, else => return parse_error(error.InvalidStartOfDeleteBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
} }
}, },
else => { else => return parse_error(error.InvalidEscapeSequenceStart, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
std.debug.print("str: {s}, i: {} c: {c}\n", .{ str, i, str[i] });
return error.parseEscapeSequenceStart;
},
} }
}, },
.cr => { .cr => {
@ -204,7 +234,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 2; i += 2;
} else return error.parseCR; } else return parse_error(error.InvalidCRBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
}, },
.space => { .space => {
if (std.mem.indexOf(u8, str[i..], "Space") == 0) { if (std.mem.indexOf(u8, str[i..], "Space") == 0) {
@ -212,10 +242,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 5; i += 5;
} else { } else return parse_error(error.InvalidSpaceBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
std.debug.print("str: {s}, i: {}, char: {}\n", .{ str, i, str[i] });
return error.parseSpace;
}
}, },
.del => { .del => {
if (std.mem.indexOf(u8, str[i..], "Del") == 0) { if (std.mem.indexOf(u8, str[i..], "Del") == 0) {
@ -223,7 +250,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 3; i += 3;
} else return error.parseDel; } else return parse_error(error.InvalidDeleteBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
}, },
.tab => { .tab => {
if (std.mem.indexOf(u8, str[i..], "Tab") == 0) { if (std.mem.indexOf(u8, str[i..], "Tab") == 0) {
@ -231,7 +258,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 3; i += 3;
} else return error.parseTab; } else return parse_error(error.InvalidTabBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
}, },
.up => { .up => {
if (std.mem.indexOf(u8, str[i..], "Up") == 0) { if (std.mem.indexOf(u8, str[i..], "Up") == 0) {
@ -239,7 +266,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 2; i += 2;
} else return error.parseSpace; } else return parse_error(error.InvalidUpBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
}, },
.esc => { .esc => {
if (std.mem.indexOf(u8, str[i..], "Esc") == 0) { if (std.mem.indexOf(u8, str[i..], "Esc") == 0) {
@ -247,7 +274,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 3; i += 3;
} else return error.parseEsc; } else return parse_error(error.InvalidEscapeBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
}, },
.down => { .down => {
if (std.mem.indexOf(u8, str[i..], "Down") == 0) { if (std.mem.indexOf(u8, str[i..], "Down") == 0) {
@ -255,7 +282,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 4; i += 4;
} else return error.parseDown; } else return parse_error(error.InvalidDownBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
}, },
.left => { .left => {
if (std.mem.indexOf(u8, str[i..], "Left") == 0) { if (std.mem.indexOf(u8, str[i..], "Left") == 0) {
@ -263,7 +290,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 4; i += 4;
} else return error.parseLeft; } else return parse_error(error.InvalidLeftBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
}, },
.right => { .right => {
if (std.mem.indexOf(u8, str[i..], "Right") == 0) { if (std.mem.indexOf(u8, str[i..], "Right") == 0) {
@ -271,17 +298,15 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
modifiers = 0; modifiers = 0;
state = .escape_sequence_end; state = .escape_sequence_end;
i += 5; i += 5;
} else return error.parseRight; } else return parse_error(error.InvalidRightBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
}, },
.function_key => { .function_key => {
switch (str[i]) { switch (str[i]) {
'0'...'9' => { '0'...'9' => {
function_key_number *= 10; function_key_number *= 10;
function_key_number += str[i] - '0'; function_key_number += str[i] - '0';
if (function_key_number < 1 or function_key_number > 35) { if (function_key_number < 1 or function_key_number > 35)
std.debug.print("function_key_number: {}\n", .{function_key_number}); return parse_error(error.InvalidFunctionKeyNumber, "function_key_number: {}", .{function_key_number});
return error.FunctionKeyNumber;
}
i += 1; i += 1;
}, },
'>' => { '>' => {
@ -292,7 +317,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
state = .base; state = .base;
i += 1; i += 1;
}, },
else => return error.parseFunctionKey, else => return parse_error(error.InvalidFunctionKeyBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
} }
}, },
.escape_sequence_delimiter => { .escape_sequence_delimiter => {
@ -301,9 +326,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
state = .char_or_key_or_modifier; state = .char_or_key_or_modifier;
i += 1; i += 1;
}, },
else => { else => return parse_error(error.InvalidEscapeSequenceDelimiter, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
return error.parseEscapeSequenceDelimiter;
},
} }
}, },
.char_or_key_or_modifier => { .char_or_key_or_modifier => {
@ -325,7 +348,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
'C' => input.mod.ctrl, 'C' => input.mod.ctrl,
'D' => input.mod.super, 'D' => input.mod.super,
'S' => input.mod.shift, 'S' => input.mod.shift,
else => return error.parseModifier, else => return parse_error(error.InvalidModifier, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
}; };
state = .escape_sequence_delimiter; state = .escape_sequence_delimiter;
@ -337,9 +360,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
state = .base; state = .base;
i += 1; i += 1;
}, },
else => { else => return parse_error(error.InvalidEscapeSequenceEnd, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
return error.parseEscapeSequenceEnd;
},
} }
}, },
} }
@ -481,7 +502,10 @@ const BindingSet = struct {
for (entry) |token| { for (entry) |token| {
switch (state) { switch (state) {
.key_event => { .key_event => {
keys = try parse_key_events(self.allocator, token); keys = parse_key_events(self.allocator, token) catch |e| {
self.logger.print_err("keybind.load", "ERROR: {s} {s}", .{@errorName(e), parse_error_message});
return e;
};
state = .command; state = .command;
}, },
.command => { .command => {