From d5d5f7f06397d73f497d352f2f38b1a53d932b0d Mon Sep 17 00:00:00 2001 From: Uko Kokņevičs Date: Mon, 19 Feb 2024 23:38:33 +0200 Subject: Big update to modern zig --- src/KeyMap.zig | 64 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 26 deletions(-) (limited to 'src/KeyMap.zig') diff --git a/src/KeyMap.zig b/src/KeyMap.zig index e200faa..8df4c06 100644 --- a/src/KeyMap.zig +++ b/src/KeyMap.zig @@ -25,6 +25,7 @@ pub const Error = error{ std.os.RealPathError; pub const BoundFn = fn (*Editor, *Buffer, Key) Error!void; +pub const BoundFnPtr = *const BoundFn; const Context = struct { pub fn hash(self: Context, key: []const Key) u64 { @@ -65,13 +66,13 @@ const Keys = struct { const RawMap = HashMap([]const Key, Value, Context, std.hash_map.default_max_load_percentage); const Value = union(enum) { - bound_fn: BoundFn, + bound_fn: BoundFnPtr, chord: void, }; allocator: Allocator, current_chord: ArrayList(Key), -default: ?BoundFn, +default: ?BoundFnPtr, raw_map: RawMap, pub fn init(allocator: Allocator) KeyMap { @@ -90,22 +91,22 @@ pub fn defaultMap(allocator: Allocator) !KeyMap { map.default = wrapFn(defaultFn); // M-g <*> - try map.bind(&.{Key.meta('g'), Key.char('g')}, Buffer.goToLine); + try map.bind(&.{ Key.meta('g'), Key.char('g') }, Buffer.goToLine); // M-O <*> - try map.bind(&.{Key.meta('O'), Key.char('F')}, Buffer.moveEndOfLine); - try map.bind(&.{Key.meta('O'), Key.char('H')}, Buffer.moveBeginningOfLine); + try map.bind(&.{ Key.meta('O'), Key.char('F') }, Buffer.moveEndOfLine); + try map.bind(&.{ Key.meta('O'), Key.char('H') }, Buffer.moveBeginningOfLine); // C-x C-<*> - try map.bind(&.{Key.ctrl('x'), Key.ctrl('b')}, Editor.switchBuffer); - try map.bind(&.{Key.ctrl('x'), Key.ctrl('c')}, Editor.saveBuffersExit); - try map.bind(&.{Key.ctrl('x'), Key.ctrl('f')}, Editor.openFile); - try map.bind(&.{Key.ctrl('x'), Key.ctrl('s')}, Buffer.save); + try map.bind(&.{ Key.ctrl('x'), Key.ctrl('b') }, Editor.switchBuffer); + try map.bind(&.{ Key.ctrl('x'), Key.ctrl('c') }, Editor.saveBuffersExit); + try map.bind(&.{ Key.ctrl('x'), Key.ctrl('f') }, Editor.openFile); + try map.bind(&.{ Key.ctrl('x'), Key.ctrl('s') }, Buffer.save); // C-x <*> - try map.bind(&.{Key.ctrl('x'), Key.char('b')}, Editor.switchBuffer); + try map.bind(&.{ Key.ctrl('x'), Key.char('b') }, Editor.switchBuffer); // TODO: C-x h for help - try map.bind(&.{Key.ctrl('x'), Key.char('k')}, Editor.killCurrentBuffer); + try map.bind(&.{ Key.ctrl('x'), Key.char('k') }, Editor.killCurrentBuffer); // M-C-<*> try map.bind(&.{Key.meta(Key.ctrl('d'))}, Buffer.backwardDeleteChar); @@ -166,7 +167,7 @@ pub fn bind(self: *KeyMap, keys: []const Key, comptime f: anytype) !void { std.debug.assert(keys.len > 0); var idx: usize = 0; while (idx < keys.len - 1) : (idx += 1) { - const subseq = try self.allocator.dupe(Key, keys[0..idx + 1]); + const subseq = try self.allocator.dupe(Key, keys[0 .. idx + 1]); errdefer self.allocator.free(subseq); const gop = try self.raw_map.getOrPut(subseq); @@ -204,7 +205,7 @@ pub fn bind(self: *KeyMap, keys: []const Key, comptime f: anytype) !void { const keys_wrap = Keys{ .keys = keys }; std.log.err( "Attempting to bind a shorter chord ({}) over longer one(s)", - .{ keys_wrap }, + .{keys_wrap}, ); return error.KeyBindError; }, @@ -239,9 +240,9 @@ pub fn keypress(self: *KeyMap, editor: *Editor, buf: *Buffer, key: Key) !void { } fn defaultFn(editor: *Editor, buffer: *Buffer, key: Key) !void { - if (@enumToInt(key) <= @enumToInt(Key.max_char)) { - const char = @intCast(u8, @enumToInt(key)); - if (std.ascii.isGraph(char) or char == ' ') { + if (@intFromEnum(key) <= @intFromEnum(Key.max_char)) { + const char: u8 = @intCast(@intFromEnum(key)); + if (std.ascii.isPrint(char)) { try buffer.insertChar(char); return; } @@ -251,6 +252,17 @@ fn defaultFn(editor: *Editor, buffer: *Buffer, key: Key) !void { try editor.setStatusMessage("Unknown key: {}", .{key}); } +// I think there's a bug in Zig's std.mem.eql +fn typeEql(comptime a: []const type, comptime b: []const type) bool { + if (a.len != b.len) return false; + if (a.len == 0 or a.ptr == b.ptr) return true; + + for (a, b) |a_elem, b_elem| { + if (a_elem != b_elem) return false; + } + return true; +} + fn wrapFn(comptime f: anytype) BoundFn { comptime { if (@TypeOf(f) == BoundFn) { @@ -260,13 +272,13 @@ fn wrapFn(comptime f: anytype) BoundFn { const fn_info = @typeInfo(@TypeOf(f)).Fn; const should_try = if (fn_info.return_type) |return_type| @typeInfo(return_type) == .ErrorUnion else false; - const args_info = fn_info.args; - var args = [_]type { undefined } ** args_info.len; - for (args_info) |arg_info, idx| { - args[idx] = arg_info.arg_type.?; + const params_info = fn_info.params; + var params = [_]type{undefined} ** params_info.len; + for (params_info, 0..) |param_info, idx| { + params[idx] = param_info.type.?; } - if (std.mem.eql(type, &args, &.{*Buffer})) { + if (typeEql(¶ms, &.{*Buffer})) { return struct { pub fn wf(e: *Editor, b: *Buffer, k: Key) Error!void { _ = e; @@ -278,7 +290,7 @@ fn wrapFn(comptime f: anytype) BoundFn { } } }.wf; - } else if (std.mem.eql(type, &args, &.{*Editor})) { + } else if (typeEql(¶ms, &.{*Editor})) { return struct { pub fn wf(e: *Editor, b: *Buffer, k: Key) Error!void { _ = b; @@ -290,7 +302,7 @@ fn wrapFn(comptime f: anytype) BoundFn { } } }.wf; - } else if (std.mem.eql(type, &args, &.{*Editor, *Buffer})) { + } else if (typeEql(¶ms, &.{ *Editor, *Buffer })) { return struct { pub fn wf(e: *Editor, b: *Buffer, k: Key) Error!void { _ = k; @@ -301,7 +313,7 @@ fn wrapFn(comptime f: anytype) BoundFn { } } }.wf; - } else if (std.mem.eql(type, &args, &.{*Buffer, *Editor})) { + } else if (typeEql(¶ms, &.{ *Buffer, *Editor })) { return struct { pub fn wf(e: *Editor, b: *Buffer, k: Key) Error!void { _ = k; @@ -312,7 +324,7 @@ fn wrapFn(comptime f: anytype) BoundFn { } } }.wf; - } else if (std.mem.eql(type, &args, &.{*Buffer, Editor})) { + } else if (typeEql(¶ms, &.{ *Buffer, Editor })) { return struct { pub fn wf(e: *Editor, b: *Buffer, k: Key) Error!void { _ = k; @@ -323,7 +335,7 @@ fn wrapFn(comptime f: anytype) BoundFn { } } }.wf; - } else if (std.mem.eql(type, &args, &.{*Editor, *Buffer, Key})) { + } else if (typeEql(¶ms, &.{ *Editor, *Buffer, Key })) { return struct { pub fn wf(e: *Editor, b: *Buffer, k: Key) Error!void { if (should_try) { -- cgit v1.2.3