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 --- build.zig | 38 ++++++++++++++++----------------- src/Buffer.zig | 27 ++++++++++++----------- src/Config.zig | 6 +++--- src/Editor.zig | 42 ++++++++++++++++++------------------ src/KeyMap.zig | 64 +++++++++++++++++++++++++++++++++---------------------- src/KeyReader.zig | 16 ++++++++------ src/RawMode.zig | 16 +++++++------- src/Row.zig | 22 +++++++++---------- src/Syntax.zig | 12 +++++------ src/c.zig | 5 +++++ src/key.zig | 51 ++++++++++++++++++-------------------------- src/main.zig | 10 ++++++++- 12 files changed, 162 insertions(+), 147 deletions(-) create mode 100644 src/c.zig diff --git a/build.zig b/build.zig index d65020a..429dc5b 100644 --- a/build.zig +++ b/build.zig @@ -1,11 +1,12 @@ const std = @import("std"); -const Builder = std.build.Builder; +const Builder = std.Build; const SemanticVersion = std.SemanticVersion; const share_prefix = "share/arkta/es/"; const version = "0.3.0"; +const semver = SemanticVersion.parse(version) catch unreachable; const config = struct { template: []const u8 = @embedFile("es.ini.in"), @@ -18,37 +19,34 @@ const config = struct { }{}; fn installGeneratedFile(b: *Builder, comptime name: []const u8, data: []const u8) void { - const write_file = b.addWriteFile(name, data); - - const write_file_install = b.addInstallFile( - write_file.getFileSource(name).?, - share_prefix ++ name, - ); - write_file_install.step.dependOn(&write_file.step); + const write_files = b.addWriteFiles(); + const write_file = write_files.add(name, data); + const write_file_install = b.addInstallFile(write_file, share_prefix ++ name); + write_file_install.step.dependOn(&write_files.step); b.getInstallStep().dependOn(&write_file_install.step); } pub fn build(b: *Builder) void { const target = b.standardTargetOptions(.{}); - const mode = b.standardReleaseOptions(); + const optimize = b.standardOptimizeOption(.{}); const options = b.addOptions(); - options.addOption( - SemanticVersion, - "es_version", - SemanticVersion.parse(version) catch unreachable, - ); + options.addOption(SemanticVersion, "es_version", semver); options.addOption(bool, "default_hard_tabs", config.default.hard_tabs); options.addOption(usize, "default_line_limit", config.default.line_limit); options.addOption(usize, "default_page_overlap", config.default.page_overlap); options.addOption(usize, "default_tab_stop", config.default.tab_stop); - const exe = b.addExecutable("es", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.addOptions("es-config", options); - exe.install(); + const exe = b.addExecutable(.{ + .name = "es", + .version = semver, + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + exe.root_module.addOptions("es-config", options); + b.installArtifact(exe); installGeneratedFile( b, @@ -56,7 +54,7 @@ pub fn build(b: *Builder) void { comptime std.fmt.comptimePrint(config.template, config.default), ); - const run_cmd = exe.run(); + const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); if (b.args) |args| { run_cmd.addArgs(args); diff --git a/src/Buffer.zig b/src/Buffer.zig index 8917772..473674c 100644 --- a/src/Buffer.zig +++ b/src/Buffer.zig @@ -31,11 +31,11 @@ config: Config, syntax: ?Syntax, pub fn init(allocator: Allocator, name: []const u8) !Buffer { - var name_owned = try allocator.dupe(u8, name); + const name_owned = try allocator.dupe(u8, name); errdefer allocator.free(name_owned); // TODO: buffer-specific config support - var config = try Config.readConfig(allocator); + const config = try Config.readConfig(allocator); return Buffer{ .allocator = allocator, @@ -156,7 +156,7 @@ pub fn deleteRow(self: *Buffer, at: usize) void { if (self.cy == self.rows.items.len) { self.cx = 0; } else { - self.cx = std.math.min(self.cx, self.rows.items[self.cy].data.items.len); + self.cx = @min(self.cx, self.rows.items[self.cy].data.items.len); } } @@ -184,7 +184,7 @@ pub fn drawRows(self: Buffer, writer: anytype, screenrows: usize, screencols: us } const char = row.rdata.items[rx]; - if (std.ascii.isCntrl(char)) { + if (std.ascii.isControl(char)) { const sym = [_]u8{if (char <= 26) char + '@' else '?'}; try writer.print("\x1b[7m{s}\x1b[m", .{&sym}); last_hl = Highlight.none; @@ -225,7 +225,7 @@ pub fn drawRows(self: Buffer, writer: anytype, screenrows: usize, screencols: us pub fn drawStatusBar(self: Buffer, writer: anytype, screencols: usize) !void { try writer.writeAll("\x1b[m\x1b[7m"); - var name = if (self.short_name.len > 20) + const name = if (self.short_name.len > 20) try std.fmt.allocPrint( self.allocator, "...{s}", @@ -250,8 +250,8 @@ pub fn drawStatusBar(self: Buffer, writer: anytype, screencols: usize) !void { }); defer self.allocator.free(rbuf); - var rlen = if (rbuf.len > screencols) screencols else rbuf.len; - var llen = if (lbuf.len > screencols - rlen) screencols - rlen else lbuf.len; + const rlen = if (rbuf.len > screencols) screencols else rbuf.len; + const llen = if (lbuf.len > screencols - rlen) screencols - rlen else lbuf.len; try writer.writeAll(lbuf[0..llen]); try writer.writeByteNTimes(' ', screencols - llen - rlen); @@ -286,7 +286,7 @@ pub fn goToLine(self: *Buffer, editor: *Editor) !void { if (self.cy == self.rows.items.len) { self.cx = 0; } else { - self.cx = std.math.min(self.cx, self.rows.items[self.cy].data.items.len); + self.cx = @min(self.cx, self.rows.items[self.cy].data.items.len); } } } @@ -409,7 +409,7 @@ pub fn pageDown(self: *Buffer, editor: Editor) void { pub fn pageUp(self: *Buffer, editor: Editor) void { const screenrows = editor.screenrows; - self.cy = std.math.min(self.rows.items.len, self.rowoff + self.config.page_overlap); + self.cy = @min(self.rows.items.len, self.rowoff + self.config.page_overlap); var i: usize = 0; while (i < screenrows) : (i += 1) { self.previousLine(); @@ -439,7 +439,9 @@ pub fn recenterTopBottom(self: *Buffer, editor: *Editor) !void { pub fn save(self: *Buffer, editor: *Editor) !void { if (self.file_path == null) { - const fname = (try editor.prompt(self.allocator, "Save as")) orelse { return; }; + const fname = (try editor.prompt(self.allocator, "Save as")) orelse { + return; + }; defer self.allocator.free(fname); const file_path = try es.files.resolvePath(self.allocator, fname); @@ -463,7 +465,8 @@ pub fn save(self: *Buffer, editor: *Editor) !void { const file_path = self.file_path.?; if (std.fs.path.dirname(file_path)) |dirname| { - if (std.fs.openDirAbsolute(dirname, .{})) |*dir| { + var res_dir = std.fs.openDirAbsolute(dirname, .{}); + if (res_dir) |*dir| { dir.close(); } else |_| { const prompt = try std.fmt.allocPrint( @@ -597,7 +600,7 @@ fn printWithLeftPadding( padding: u8, args: anytype, ) !void { - var unpadded = try std.fmt.allocPrint(allocator, fmt, args); + const unpadded = try std.fmt.allocPrint(allocator, fmt, args); defer allocator.free(unpadded); std.debug.assert(unpadded.len <= width); diff --git a/src/Config.zig b/src/Config.zig index ea11e5c..47e61a0 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -68,7 +68,7 @@ fn readConfigInBaseDir(allocator: Allocator, config: *Config, base_dir: []const while (try reader.readUntilDelimiterOrEofAlloc(allocator, '\n', 4096)) |line_buf| { defer allocator.free(line_buf); - var line = std.mem.trim(u8, line_buf, &std.ascii.spaces); + var line = std.mem.trim(u8, line_buf, &std.ascii.whitespace); if (line.len == 0 or line[0] == '#') { continue; } @@ -77,8 +77,8 @@ fn readConfigInBaseDir(allocator: Allocator, config: *Config, base_dir: []const return error.MalformedConfig; }; - const key = std.mem.trimRight(u8, line[0..split], &std.ascii.spaces); - const value = std.mem.trimLeft(u8, line[(split + 1)..], &std.ascii.spaces); + const key = std.mem.trimRight(u8, line[0..split], &std.ascii.whitespace); + const value = std.mem.trimLeft(u8, line[(split + 1)..], &std.ascii.whitespace); if (std.mem.eql(u8, key, "hard-tabs")) { config.hard_tabs = try parseBool(value); } else if (std.mem.eql(u8, key, "line-limit")) { diff --git a/src/Editor.zig b/src/Editor.zig index 7e56783..aa57c15 100644 --- a/src/Editor.zig +++ b/src/Editor.zig @@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; const Buffer = es.Buffer; const Editor = @This(); +const File = std.fs.File; const Key = es.Key; const KeyMap = es.KeyMap; const KeyReader = es.KeyReader; @@ -144,7 +145,8 @@ pub fn killCurrentBuffer(self: *Editor) !bool { self.allocator.free(entry_to_kill.key); entry_to_kill.value.deinit(); - if (self.buffers.valueIterator().next()) |buffer| { + var it = self.buffers.valueIterator(); + if (it.next()) |buffer| { self.buffer = buffer; } else { self.buffer = try self.putBuffer("*scratch*"); @@ -245,11 +247,11 @@ pub fn promptEx( try cb(self, buf.items, key, cb_data); } - return buf.toOwnedSlice(); + return try buf.toOwnedSlice(); }, - else => if (@enumToInt(key) < @enumToInt(Key.max_char)) { - const key_char = @intCast(u8, @enumToInt(key)); - if (std.ascii.isSpace(key_char) or std.ascii.isGraph(key_char)) { + else => if (@intFromEnum(key) < @intFromEnum(Key.max_char)) { + const key_char: u8 = @intCast(@intFromEnum(key)); + if (std.ascii.isWhitespace(key_char) or std.ascii.isPrint(key_char)) { try buf.append(key_char); } }, // TODO: else ?? @@ -272,15 +274,7 @@ pub fn promptYN(self: *Editor, prompt_str: []const u8) !bool { var response = try self.prompt(self.allocator, full_prompt); defer if (response) |str| self.allocator.free(str); // TODO: This can be improved - while (response != null - and (response.?.len == 0 - or (response.?[0] != 'y' - and response.?[0] != 'Y' - and response.?[0] != 'n' - and response.?[0] != 'N' - ) - ) - ) { + while (response != null and (response.?.len == 0 or (response.?[0] != 'y' and response.?[0] != 'Y' and response.?[0] != 'n' and response.?[0] != 'N'))) { if (response) |str| self.allocator.free(str); response = try self.prompt(self.allocator, full_prompt); } @@ -352,7 +346,7 @@ pub fn saveBuffersExit(self: *Editor) !void { pub fn setStatusMessage(self: *Editor, comptime fmt: []const u8, args: anytype) !void { // Get new resources - var new_msg = try std.fmt.allocPrint(self.allocator, fmt, args); + const new_msg = try std.fmt.allocPrint(self.allocator, fmt, args); errdefer self.allocator.free(new_msg); // Get rid of old resources (no errors) @@ -387,11 +381,17 @@ fn drawMessageBar(self: Editor, writer: anytype) !void { } if (self.statusmsg.?.len != 0 and std.time.milliTimestamp() - self.statusmsg_time < 5 * std.time.ms_per_s) { - try writer.writeAll(self.statusmsg.?[0..(std.math.min(self.statusmsg.?.len, self.screencols))]); + try writer.writeAll(self.statusmsg.?[0..(@min(self.statusmsg.?.len, self.screencols))]); } } -fn getCursorPosition(row: *usize, col: *usize) !void { +// TODO[zigbug]: https://github.com/ziglang/zig/issues/18177 +// Replace with an inferred set +const CursorPositionError = error{ + MisformedTerminalResponse, +} || File.WriteError; + +fn getCursorPosition(row: *usize, col: *usize) CursorPositionError!void { const std_out = std.io.getStdOut(); try std_out.writeAll("\x1b[6n\r\n"); @@ -400,7 +400,7 @@ fn getCursorPosition(row: *usize, col: *usize) !void { var response = std_in.readUntilDelimiter(&buf, 'R') catch |err| switch (err) { error.EndOfStream => return error.MisformedTerminalResponse, error.StreamTooLong => return error.MisformedTerminalResponse, - else => return @errSetCast(std.os.ReadError, err), + else => return @as(CursorPositionError, @errorCast(err)), }; if (response.len < 2 or response[0] != '\x1b' or response[1] != '[') { @@ -418,9 +418,9 @@ fn getCursorPosition(row: *usize, col: *usize) !void { } fn getWindowSize(rows: *usize, cols: *usize) !void { - var ws: std.os.linux.winsize = undefined; - const rc = std.os.linux.ioctl(std.os.STDIN_FILENO, std.os.linux.T.IOCGWINSZ, @ptrToInt(&ws)); - switch (std.os.linux.getErrno(rc)) { + var ws: std.os.system.winsize = undefined; + const rc = std.os.system.ioctl(std.os.STDIN_FILENO, std.os.system.T.IOCGWINSZ, @intFromPtr(&ws)); + switch (std.os.system.getErrno(rc)) { .SUCCESS => { cols.* = ws.ws_col; rows.* = ws.ws_row; 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) { diff --git a/src/KeyReader.zig b/src/KeyReader.zig index 2265975..28e6dcb 100644 --- a/src/KeyReader.zig +++ b/src/KeyReader.zig @@ -83,7 +83,7 @@ fn readByte(reader: File.Reader) Error!?u8 { return reader.readByte() catch |err| switch (err) { error.WouldBlock => null, error.EndOfStream => null, - else => return @errSetCast(File.Reader.Error, err), + else => return @as(Error, @errorCast(err)), }; } @@ -135,7 +135,7 @@ fn readControlSequence(self: *KeyReader, reader: File.Reader) !Key { if (parameter_list.len == 0) { return key; } else if (parameter_list.len == 1) { - var count = std.math.max(1, parameter_list[0]) - 1; + var count = @max(1, parameter_list[0]) - 1; try self.key_buf.ensureUnusedCapacity(count); while (count > 0) : (count -= 1) { self.key_buf.appendAssumeCapacity(key); @@ -143,7 +143,7 @@ fn readControlSequence(self: *KeyReader, reader: File.Reader) !Key { return key; } else if (parameter_list.len == 2) { - var count = std.math.max(1, parameter_list[0]) - 1; + var count = @max(1, parameter_list[0]) - 1; if (modKey(key, parameter_list[1])) |mod_key| { try self.key_buf.ensureUnusedCapacity(count); while (count > 0) : (count -= 1) { @@ -159,7 +159,7 @@ fn readControlSequence(self: *KeyReader, reader: File.Reader) !Key { std.log.err( "Unknown terminal sequence '^[[{s}{s}{c}'", - .{parameters.items, intermediates.items, final}, + .{ parameters.items, intermediates.items, final }, ); try self.key_buf.ensureUnusedCapacity(parameters.items.len + intermediates.items.len + 1); @@ -169,7 +169,7 @@ fn readControlSequence(self: *KeyReader, reader: File.Reader) !Key { } else { std.log.err( "Unknown terminal sequence '^[[{s}{s}'", - .{parameters.items, intermediates.items}, + .{ parameters.items, intermediates.items }, ); } @@ -212,11 +212,13 @@ fn splitParameters(allocator: Allocator, parameters_string: []const u8) Allocato usize, parameter_string, 10, - ) catch { return null; }; + ) catch { + return null; + }; try parameters.append(parameter); } } - return parameters.toOwnedSlice(); + return try parameters.toOwnedSlice(); } diff --git a/src/RawMode.zig b/src/RawMode.zig index 7298922..f657ac8 100644 --- a/src/RawMode.zig +++ b/src/RawMode.zig @@ -1,4 +1,4 @@ -const linux = std.os.linux; +const system = std.os.system; const std = @import("std"); const RawMode = @This(); @@ -14,16 +14,16 @@ pub fn init() !RawMode { var raw = orig; raw.iflag &= ~@as( - linux.tcflag_t, - linux.BRKINT | linux.ICRNL | linux.INPCK | linux.ISTRIP | linux.IXON, + system.tcflag_t, + system.BRKINT | system.ICRNL | system.INPCK | system.ISTRIP | system.IXON, ); - raw.lflag &= ~@as(linux.tcflag_t, linux.ECHO | linux.ICANON | linux.IEXTEN | linux.ISIG); - raw.oflag &= ~@as(linux.tcflag_t, linux.OPOST); + raw.lflag &= ~@as(system.tcflag_t, system.ECHO | system.ICANON | system.IEXTEN | system.ISIG); + raw.oflag &= ~@as(system.tcflag_t, system.OPOST); - raw.cflag |= linux.CS8; + raw.cflag |= system.CS8; - raw.cc[linux.V.MIN] = 0; - raw.cc[linux.V.TIME] = 1; + raw.cc[system.V.MIN] = 0; + raw.cc[system.V.TIME] = 1; try std.os.tcsetattr(std.os.STDIN_FILENO, .FLUSH, raw); diff --git a/src/Row.zig b/src/Row.zig index d1de2aa..b8e1674 100644 --- a/src/Row.zig +++ b/src/Row.zig @@ -51,7 +51,7 @@ pub fn appendString(self: *Row, buf: *Buffer, str: []const u8) !void { pub fn cleanWhiteSpace(self: *Row, buf: *Buffer) !void { const orig_len = self.data.items.len; while (self.data.items.len > 0) { - if (std.ascii.isBlank(self.data.items[self.data.items.len - 1])) { + if (std.ascii.isWhitespace(self.data.items[self.data.items.len - 1])) { _ = self.data.pop(); } else { break; @@ -86,7 +86,7 @@ pub fn deleteChar(self: *Row, buf: *Buffer, at: usize) !void { pub fn indentationSize(self: Row) usize { var idx: usize = 0; while (idx < self.data.items.len) : (idx += 1) { - if (!std.ascii.isBlank(self.data.items[idx])) { + if (!std.ascii.isWhitespace(self.data.items[idx])) { break; } } @@ -105,7 +105,7 @@ pub fn rxToCx(self: Row, config: Config, rx: usize) usize { } var cur_rx: usize = 0; - for (self.data.items) |char, cx| { + for (self.data.items, 0..) |char, cx| { if (char == '\t') { cur_rx += config.tab_stop - (cur_rx % config.tab_stop); } else { @@ -139,7 +139,7 @@ pub fn update(self: *Row, buf: *Buffer) !void { const UpdateSyntaxError = std.mem.Allocator.Error; pub fn updateSyntax(self: *Row, buf: *Buffer) UpdateSyntaxError!void { try self.hldata.resize(self.rdata.items.len); - std.mem.set(Highlight, self.hldata.items, .normal); + @memset(self.hldata.items, .normal); if (buf.syntax == null) { return; } @@ -158,7 +158,7 @@ pub fn updateSyntax(self: *Row, buf: *Buffer) UpdateSyntaxError!void { std.debug.assert(scs.len != 0); if (curr_str_quote == null and !in_comment and scs.len + i <= self.rdata.items.len) { if (std.mem.eql(u8, scs, self.rdata.items[i..(i + scs.len)])) { - std.mem.set(Highlight, self.hldata.items[i..], .comment); + @memset(self.hldata.items[i..], .comment); break :main_loop; } } @@ -172,7 +172,7 @@ pub fn updateSyntax(self: *Row, buf: *Buffer) UpdateSyntaxError!void { if (in_comment) { self.hldata.items[i] = .comment_ml; if (mce.len + i <= self.rdata.items.len and std.mem.eql(u8, mce, self.rdata.items[i..(i + mce.len)])) { - std.mem.set(Highlight, self.hldata.items[i..(i + mce.len)], .comment_ml); + @memset(self.hldata.items[i..(i + mce.len)], .comment_ml); i += mce.len; in_comment = false; last_sep = i; @@ -181,7 +181,7 @@ pub fn updateSyntax(self: *Row, buf: *Buffer) UpdateSyntaxError!void { continue :main_loop; } } else if (mcs.len + i <= self.rdata.items.len and std.mem.eql(u8, mcs, self.rdata.items[i..(i + mcs.len)])) { - std.mem.set(Highlight, self.hldata.items[i..(i + mcs.len)], .comment_ml); + @memset(self.hldata.items[i..(i + mcs.len)], .comment_ml); i += mcs.len; in_comment = true; continue :main_loop; @@ -218,9 +218,7 @@ pub fn updateSyntax(self: *Row, buf: *Buffer) UpdateSyntaxError!void { } if (syntax.flags.hl_numbers) { - if ((std.ascii.isDigit(c) and (last_sep == i or prev_hl == .number)) - or (c == '.' and prev_hl == .number) - ) { + if ((std.ascii.isDigit(c) and (last_sep == i or prev_hl == .number)) or (c == '.' and prev_hl == .number)) { self.hldata.items[i] = .number; i += 1; continue :main_loop; @@ -230,7 +228,7 @@ pub fn updateSyntax(self: *Row, buf: *Buffer) UpdateSyntaxError!void { if (syntax.isSeparator(c)) { const id = self.rdata.items[last_sep..i]; if (syntax.keyword_classifier(id)) |hl| { - std.mem.set(Highlight, self.hldata.items[last_sep..i], hl); + @memset(self.hldata.items[last_sep..i], hl); } last_sep = i + 1; @@ -242,7 +240,7 @@ pub fn updateSyntax(self: *Row, buf: *Buffer) UpdateSyntaxError!void { if (!in_comment) { const id = self.rdata.items[last_sep..self.rdata.items.len]; if (syntax.keyword_classifier(id)) |hl| { - std.mem.set(Highlight, self.hldata.items[last_sep..self.rdata.items.len], hl); + @memset(self.hldata.items[last_sep..self.rdata.items.len], hl); } } diff --git a/src/Syntax.zig b/src/Syntax.zig index 6858027..18ed477 100644 --- a/src/Syntax.zig +++ b/src/Syntax.zig @@ -10,8 +10,7 @@ const Syntax = @This(); pub const chooseSyntax = ComptimeStringMap( Syntax, - pairWith(&makefile.filematch, makefile.syntax) - ++ pairWith(&zig.filematch, zig.syntax), + pairWith(&makefile.filematch, makefile.syntax) ++ pairWith(&zig.filematch, zig.syntax), ).get; pub const Flags = struct { @@ -20,7 +19,7 @@ pub const Flags = struct { }; name: []const u8, -keyword_classifier: fn([]const u8) ?Highlight, +keyword_classifier: *const fn ([]const u8) ?Highlight, singleline_comment_start: ?[]const u8, multiline_comment_start: ?[]const u8, multiline_comment_end: ?[]const u8, @@ -28,7 +27,7 @@ separators: []const u8, flags: Flags, pub fn isSeparator(self: Syntax, char: u8) bool { - return std.ascii.isSpace(char) or std.mem.indexOfScalar(u8, self.separators, char) != null; + return std.ascii.isWhitespace(char) or std.mem.indexOfScalar(u8, self.separators, char) != null; } pub fn pairWith( @@ -37,8 +36,8 @@ pub fn pairWith( ) [keys.len]KeyValue(@TypeOf(value)) { @setEvalBranchQuota(20000); - var pairs = [_]KeyValue(@TypeOf(value)) {undefined} ** keys.len; - for (keys) |key, i| { + var pairs = [_]KeyValue(@TypeOf(value)){undefined} ** keys.len; + for (keys, 0..) |key, i| { pairs[i] = .{ .@"0" = key, .@"1" = value }; } @@ -51,4 +50,3 @@ fn KeyValue(comptime V: type) type { @"1": V, }; } - diff --git a/src/c.zig b/src/c.zig new file mode 100644 index 0000000..8fb0a79 --- /dev/null +++ b/src/c.zig @@ -0,0 +1,5 @@ +const std = @import("std"); + +const pid_t = std.c.pid_t; + +pub extern "c" fn getpid() pid_t; diff --git a/src/key.zig b/src/key.zig index f2538bd..d2748e7 100644 --- a/src/key.zig +++ b/src/key.zig @@ -27,7 +27,7 @@ pub const Key = enum(u16) { _, pub fn char(ch: u8) Key { - return @intToEnum(Key, ch); + return @enumFromInt(ch); } pub fn shift(k: anytype) Key { @@ -52,20 +52,16 @@ pub const Key = enum(u16) { } fn mod(comptime modifier: Key, k: Key) Key { - comptime std.debug.assert( - modifier == .mod_shft - or modifier == .mod_meta - or modifier == .mod_ctrl - ); + comptime std.debug.assert(modifier == .mod_shft or modifier == .mod_meta or modifier == .mod_ctrl); - const shft_int = @enumToInt(Key.mod_shft); - const meta_int = @enumToInt(Key.mod_meta); - const ctrl_int = @enumToInt(Key.mod_ctrl); + const shft_int = @intFromEnum(Key.mod_shft); + const meta_int = @intFromEnum(Key.mod_meta); + const ctrl_int = @intFromEnum(Key.mod_ctrl); - const max_char_int = @enumToInt(Key.max_char); + const max_char_int = @intFromEnum(Key.max_char); - const mod_int = @enumToInt(modifier); - const k_int = @enumToInt(k); + const mod_int = @intFromEnum(modifier); + const k_int = @intFromEnum(k); if (k_int & mod_int == mod_int) { return k; } @@ -76,12 +72,12 @@ pub const Key = enum(u16) { // Appending S- to a character is not smart std.debug.assert(modifier != .mod_shft); return switch (modifier) { - .mod_meta => @intToEnum(Key, k_int | meta_int), - .mod_ctrl => @intToEnum(Key, k_origmod | (k_nomod & 0x1f)), + .mod_meta => @enumFromInt(k_int | meta_int), + .mod_ctrl => @enumFromInt(k_origmod | (k_nomod & 0x1f)), else => unreachable, }; } else { - return @intToEnum(Key, k_int | mod_int); + return @enumFromInt(k_int | mod_int); } } @@ -125,15 +121,15 @@ pub const Key = enum(u16) { options: std.fmt.FormatOptions, writer: anytype, ) @TypeOf(writer).Error!void { - const shft_int = @enumToInt(Key.mod_shft); - const meta_int = @enumToInt(Key.mod_meta); - const ctrl_int = @enumToInt(Key.mod_ctrl); + const shft_int = @intFromEnum(Key.mod_shft); + const meta_int = @intFromEnum(Key.mod_meta); + const ctrl_int = @intFromEnum(Key.mod_ctrl); - const key_int = @enumToInt(key); + const key_int = @intFromEnum(key); if (key_int & shft_int == shft_int) { try std.fmt.formatBuf("S-", options, writer); return Key.format( - @intToEnum(Key, key_int & ~shft_int), + @enumFromInt(key_int & ~shft_int), "", options, writer, @@ -141,7 +137,7 @@ pub const Key = enum(u16) { } else if (key_int & meta_int == meta_int) { try std.fmt.formatBuf("M-", options, writer); return Key.format( - @intToEnum(Key, key_int & ~meta_int), + @enumFromInt(key_int & ~meta_int), "", options, writer, @@ -149,22 +145,17 @@ pub const Key = enum(u16) { } else if (key_int & ctrl_int == ctrl_int) { try std.fmt.formatBuf("C-", options, writer); return Key.format( - @intToEnum(Key, key_int & ~ctrl_int), + @enumFromInt(key_int & ~ctrl_int), "", options, writer, ); } else if (key_int < 0x20) { try std.fmt.formatBuf("C-", options, writer); - return Key.format( - Key.char(@intCast(u8, key_int + 0x40)), - "", - options, - writer - ); + return Key.format(Key.char(@intCast(key_int + 0x40)), "", options, writer); } else if (key_int < 0x100) { - const ch = @intCast(u8, key_int); - if (std.ascii.isGraph(ch)) { + const ch: u8 = @intCast(key_int); + if (std.ascii.isPrint(ch)) { return writer.writeByte(ch); } else { try writer.writeAll("<\\x"); diff --git a/src/main.zig b/src/main.zig index 7a3f007..fd1c304 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,4 +1,5 @@ pub const Buffer = @import("Buffer.zig"); +pub const c = @import("c.zig"); pub const conf = @import("es-config"); pub const Config = @import("Config.zig"); pub const Editor = @import("Editor.zig"); @@ -13,6 +14,7 @@ pub const search = @import("search.zig").search; pub const StringBuilder = @import("StringBuilder.zig"); pub const Syntax = @import("Syntax.zig"); +const builtin = @import("builtin"); const std = @import("std"); const Allocator = std.mem.Allocator; @@ -21,6 +23,12 @@ const GPA = std.heap.GeneralPurposeAllocator(.{}); var log_file: ?File = null; +// TODO[zigbug]: Why isn't getpid defined for Darwin? +const getpid = switch (builtin.os.tag) { + .macos, .ios, .tvos, .watchos => c.getpid, + else => std.os.system.getpid, +}; + pub fn log( comptime level: std.log.Level, comptime scope: @TypeOf(.EnumLiteral), @@ -45,7 +53,7 @@ pub fn main() !void { const log_file_name = try std.fmt.allocPrint( allocator, "/tmp/es.{}.log", - .{std.os.linux.getpid()}, + .{getpid()}, ); defer { std.log.info("Logs in {s}", .{log_file_name}); -- cgit v1.2.3