port to zig 0.11.0

This commit is contained in:
Leon Henrik Plickat 2024-01-04 06:57:30 +01:00
parent a36891ed77
commit 622caf6f4e
11 changed files with 138 additions and 130 deletions

128
build.zig
View file

@ -1,18 +1,16 @@
const std = @import("std");
const zbs = std.build;
const fs = std.fs;
const mem = std.mem;
const ascii = std.ascii;
const fmt = std.fmt;
const ScanProtocolsStep = @import("deps/zig-wayland/build.zig").ScanProtocolsStep;
const Scanner = @import("deps/zig-wayland/build.zig").Scanner;
pub fn build(b: *zbs.Builder) !void {
const mode = b.standardReleaseOptions();
const options = b.addOptions();
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const options = b.addOptions();
const scanner = ScanProtocolsStep.create(b);
scanner.addProtocolPath("protocol/wlr-layer-shell-unstable-v1.xml");
const scanner = Scanner.create(b, .{});
scanner.addCustomProtocol("protocol/wlr-layer-shell-unstable-v1.xml");
scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
scanner.generate("wl_compositor", 5);
scanner.generate("wl_shm", 1);
@ -21,61 +19,75 @@ pub fn build(b: *zbs.Builder) !void {
scanner.generate("wl_seat", 8);
scanner.generate("wl_output", 4);
const wayprompt_cli = b.addExecutable("wayprompt", "src/wayprompt-cli.zig");
wayprompt_cli.setTarget(target);
wayprompt_cli.setBuildMode(mode);
const wayland = b.createModule(.{ .source_file = scanner.result });
const xkbcommon = b.createModule(.{
.source_file = .{ .path = "deps/zig-xkbcommon/src/xkbcommon.zig" },
});
const pixman = b.createModule(.{
.source_file = .{ .path = "deps/zig-pixman/pixman.zig" },
});
const spoon = b.createModule(.{
.source_file = .{ .path = "deps/zig-spoon/import.zig" },
});
const fcft = b.createModule(.{
.source_file = .{ .path = "deps/zig-fcft/fcft.zig" },
.dependencies = &.{
.{ .name = "pixman", .module = pixman },
},
});
const wayprompt_cli = b.addExecutable(.{
.name = "wayprompt",
.root_source_file = .{ .path = "src/wayprompt-cli.zig" },
.target = target,
.optimize = optimize,
});
wayprompt_cli.linkLibC();
wayprompt_cli.addModule("wayland", wayland);
wayprompt_cli.linkSystemLibrary("wayland-client");
wayprompt_cli.linkSystemLibrary("wayland-cursor");
scanner.addCSource(wayprompt_cli);
wayprompt_cli.addModule("fcft", fcft);
wayprompt_cli.linkSystemLibrary("fcft");
wayprompt_cli.addModule("xkbcommon", xkbcommon);
wayprompt_cli.linkSystemLibrary("xkbcommon");
wayprompt_cli.addModule("pixman", pixman);
wayprompt_cli.linkSystemLibrary("pixman-1");
wayprompt_cli.addModule("spoon", spoon);
wayprompt_cli.addOptions("build_options", options);
try exeSetup(scanner, wayprompt_cli);
b.installArtifact(wayprompt_cli);
const wayprompt_pinentry = b.addExecutable("pinentry-wayprompt", "src/wayprompt-pinentry.zig");
wayprompt_pinentry.setTarget(target);
wayprompt_pinentry.setBuildMode(mode);
const wayprompt_pinentry = b.addExecutable(.{
.name = "river",
.root_source_file = .{ .path = "src/wayprompt-pinentry.zig" },
.target = target,
.optimize = optimize,
});
wayprompt_pinentry.linkLibC();
wayprompt_pinentry.addModule("wayland", wayland);
wayprompt_pinentry.linkSystemLibrary("wayland-client");
wayprompt_pinentry.linkSystemLibrary("wayland-cursor");
scanner.addCSource(wayprompt_pinentry);
wayprompt_pinentry.addModule("fcft", fcft);
wayprompt_pinentry.linkSystemLibrary("fcft");
wayprompt_pinentry.addModule("xkbcommon", xkbcommon);
wayprompt_pinentry.linkSystemLibrary("xkbcommon");
wayprompt_pinentry.addModule("pixman", pixman);
wayprompt_pinentry.linkSystemLibrary("pixman-1");
wayprompt_pinentry.addModule("spoon", spoon);
wayprompt_pinentry.addOptions("build_options", options);
try exeSetup(scanner, wayprompt_pinentry);
b.installArtifact(wayprompt_pinentry);
const tests = b.addTest("src/tests.zig");
tests.setTarget(target);
tests.setBuildMode(mode);
tests.linkLibC();
const test_step = b.step("test", "Run all tests");
test_step.dependOn(&tests.step);
const tests = b.addTest(.{
.root_source_file = .{ .path = "src/tests.zig" },
.target = target,
.optimize = optimize,
});
const run_test = b.addRunArtifact(tests);
const test_step = b.step("test", "Run tests");
test_step.dependOn(&run_test.step);
b.installFile("doc/wayprompt.1", "share/man/man1/wayprompt.1");
b.installFile("doc/pinentry-wayprompt.1", "share/man/man1/pinentry-wayprompt.1");
b.installFile("doc/wayprompt.5", "share/man/man5/wayprompt.5");
}
fn exeSetup(scanner: *ScanProtocolsStep, exe: *zbs.LibExeObjStep) !void {
exe.addPackagePath("spoon", "deps/zig-spoon/import.zig");
const pixman = std.build.Pkg{
.name = "pixman",
.source = .{ .path = "deps/zig-pixman/pixman.zig" },
};
exe.addPackage(pixman);
exe.linkSystemLibrary("pixman-1");
const fcft = std.build.Pkg{
.name = "fcft",
.source = .{ .path = "deps/zig-fcft/fcft.zig" },
.dependencies = &[_]std.build.Pkg{pixman},
};
exe.addPackage(fcft);
exe.linkSystemLibrary("fcft");
exe.addPackagePath("xkbcommon", "deps/zig-xkbcommon/src/xkbcommon.zig");
exe.linkSystemLibrary("xkbcommon");
exe.step.dependOn(&scanner.step);
exe.addPackage(.{
.name = "wayland",
.source = .{ .generated = &scanner.result },
});
exe.linkLibC();
exe.linkSystemLibrary("wayland-client");
exe.linkSystemLibrary("wayland-cursor");
scanner.addCSource(exe);
exe.install();
}

2
deps/zig-fcft vendored

@ -1 +1 @@
Subproject commit 77225b01b3d8caf3e92f39c251b5886dcfeeb3ce
Subproject commit 1091c57e3427a0dcc9945ba02b94a37221689ff3

2
deps/zig-pixman vendored

@ -1 +1 @@
Subproject commit 4a49ba13eb9ebb0c0f991de924328e3d615bf283
Subproject commit b0a961079d80059ef56565e23c5f7a8b6a911196

2
deps/zig-spoon vendored

@ -1 +1 @@
Subproject commit a8bc052f45c18216f03e8f2576ca019a9cc2c1ab
Subproject commit 9fa5bb1eafc30b3ff0cbe297a3e0f51dbc903831

2
deps/zig-wayland vendored

@ -1 +1 @@
Subproject commit 71d21959b4671a848f1d198f6bb919f54d541f41
Subproject commit b9c6fcb8cab3a85c5583ef371055cb589b1e7b18

2
deps/zig-xkbcommon vendored

@ -1 +1 @@
Subproject commit bfd1f97c277c32fddb77dee45979d2f472595d19
Subproject commit e93ceb0436c66a7e4c727fdb59020e889519e489

View file

@ -90,7 +90,6 @@ const WaylandUi = struct {
const info = @typeInfo(WaylandUi).Struct;
inline for (info.fields) |field| {
if (fieldEql(field.name, variable)) {
// TODO[zig]: inline switch
switch (@TypeOf(@field(self, field.name))) {
u31 => {
@field(self, field.name) = fmt.parseInt(u31, value, 10) catch |err| {
@ -219,14 +218,13 @@ fn assignColour(self: *Config, path: []const u8, line: usize, variable: []const
return error.BadConfig;
}
// TODO[zig]: multi for loop
fn fieldEql(field: []const u8, variable: []const u8) bool {
if (field.len != variable.len) return false;
if (field.ptr == variable.ptr) return true;
for (field) |item, index| {
if (item == '_') {
if (variable[index] != '-') return false;
} else if (variable[index] != item) {
for (field, variable) |f, v| {
if (f == '_') {
if (v != '-') return false;
} else if (v != f) {
return false;
}
}
@ -250,7 +248,7 @@ fn pixmanColourFromRGB(descr: []const u8) !pixman.Color {
color |= 0xff;
}
const bytes = @bitCast([4]u8, color);
const bytes = @as([4]u8, @bitCast(color));
const r: u16 = bytes[3];
const g: u16 = bytes[2];

View file

@ -155,7 +155,7 @@ fn render(self: *TTY) !void {
try writer.writeAll(" > ");
const pin_square_amount = self.config.wayland_ui.pin_square_amount;
const len = self.config.secbuf.len;
try writer.writeByteNTimes('*', math.min(pin_square_amount, len));
try writer.writeByteNTimes('*', @min(pin_square_amount, len));
try writer.writeByteNTimes('_', pin_square_amount -| len);
try rpw.finish();
line += 2;

View file

@ -2,7 +2,6 @@ const builtin = @import("builtin");
const std = @import("std");
const ascii = std.ascii;
const os = std.os;
const cstr = std.cstr;
const mem = std.mem;
const math = std.math;
const unicode = std.unicode;
@ -61,7 +60,7 @@ const TextView = struct {
pub fn new(alloc: mem.Allocator, str: []const u8, font: *fcft.Font) !TextView {
if (str.len == 0) return error.EmptyString;
var height = @intCast(u31, font.height);
var height: u31 = @intCast(font.height);
const len = try unicode.utf8CountCodepoints(str);
const codepoints = try alloc.alloc(u32, len);
@ -70,7 +69,7 @@ const TextView = struct {
var i: usize = 0;
var it = (try unicode.Utf8View.init(str)).iterator();
while (it.nextCodepoint()) |cp| : (i += 1) {
if (cp == '\n') height += @intCast(u31, font.height);
if (cp == '\n') height += @as(u31, @intCast(font.height));
codepoints[i] = cp;
}
}
@ -87,7 +86,7 @@ const TextView = struct {
}
width = 0;
} else {
width += @intCast(u31, text_run.glyphs[i].advance.x);
width += @as(u31, @intCast(text_run.glyphs[i].advance.x));
}
}
if (width > max_width) {
@ -122,7 +121,7 @@ const TextView = struct {
}
width = 0;
} else {
width += @intCast(u31, kerns[i] + glyphs[i].advance.x);
width += @as(u31, @intCast(kerns[i] + glyphs[i].advance.x));
}
}
if (width > max_width) {
@ -161,11 +160,11 @@ const TextView = struct {
var Y: u31 = y;
var i: usize = 0;
while (i < glyphs.len) : (i += 1) {
if (self.mode == .glyphs) X += @intCast(u31, self.mode.glyphs.kerns[i]);
if (self.mode == .glyphs) X += @as(u31, @intCast(self.mode.glyphs.kerns[i]));
if (glyphs[i].cp == '\n') {
X = x;
Y += @intCast(u31, self.font.height);
Y += @as(u31, @intCast(self.font.height));
continue;
}
@ -183,8 +182,8 @@ const TextView = struct {
0,
0,
0,
X + @intCast(u31, glyphs[i].x),
Y - @intCast(i32, glyphs[i].y) + self.font.ascent,
X + @as(u31, @intCast(glyphs[i].x)),
Y - @as(i32, @intCast(glyphs[i].y)) + self.font.ascent,
glyphs[i].width,
glyphs[i].height,
),
@ -200,15 +199,15 @@ const TextView = struct {
0,
0,
0,
X + @intCast(i32, glyphs[i].x),
Y - @intCast(i32, glyphs[i].y) + self.font.ascent,
X + @as(i32, @intCast(glyphs[i].x)),
Y - @as(i32, @intCast(glyphs[i].y)) + self.font.ascent,
glyphs[i].width,
glyphs[i].height,
);
},
}
X += @intCast(u31, glyphs[i].advance.x);
X += @as(u31, @intCast(glyphs[i].advance.x));
}
return self.height + vertical_padding;
@ -321,10 +320,10 @@ const Seat = struct {
fn updatePointer(self: *Seat, x: wl.Fixed, y: wl.Fixed, serial: ?u32) void {
const X = x.toInt();
self.pointer_x = if (X > 0) @intCast(u31, X) else 0;
self.pointer_x = if (X > 0) @as(u31, @intCast(X)) else 0;
const Y = y.toInt();
self.pointer_y = if (Y > 0) @intCast(u31, Y) else 0;
self.pointer_y = if (Y > 0) @as(u31, @intCast(Y)) else 0;
if (serial) |s| self.last_enter_serial = s;
@ -382,8 +381,8 @@ const Seat = struct {
self.wl_pointer.?.setCursor(
self.last_enter_serial,
self.cursor_surface.?,
@intCast(i32, @divFloor(cursor_image.hotspot_x, scale)),
@intCast(i32, @divFloor(cursor_image.hotspot_y, scale)),
@intCast(@divFloor(cursor_image.hotspot_x, scale)),
@intCast(@divFloor(cursor_image.hotspot_y, scale)),
);
}
@ -451,9 +450,9 @@ const Seat = struct {
if (self.xkb_state.?.modNameIsActive(
xkb.names.mod.ctrl,
@intToEnum(xkb.State.Component, xkb.State.Component.mods_effective),
@as(xkb.State.Component, @enumFromInt(xkb.State.Component.mods_effective)),
) == 1) {
switch (@enumToInt(keysym)) {
switch (@intFromEnum(keysym)) {
xkb.Keysym.BackSpace, xkb.Keysym.w => {
if (self.w.mode == .getpin) {
self.w.config.secbuf.reset(self.w.config.alloc) catch self.w.abort(error.OutOfMemory);
@ -463,7 +462,7 @@ const Seat = struct {
else => {},
}
} else {
switch (@enumToInt(keysym)) {
switch (@intFromEnum(keysym)) {
xkb.Keysym.Return => {
self.w.abort(error.UserOk);
return;
@ -543,7 +542,7 @@ const Surface = struct {
if (self.w.mode == .getpin) {
if (self.w.prompt) |prompt| {
self.width = math.max(prompt.width + 2 * uiconf.horizontal_padding, self.width);
self.width = @max(prompt.width + 2 * uiconf.horizontal_padding, self.width);
self.height += prompt.height + uiconf.vertical_padding;
}
@ -552,19 +551,19 @@ const Surface = struct {
const pinarea_width = uiconf.pin_square_amount * (uiconf.pin_square_size + square_padding) + square_padding;
self.height += pinarea_height + uiconf.vertical_padding;
self.width = math.max(self.width, pinarea_width + 2 * uiconf.horizontal_padding);
self.width = @max(self.width, pinarea_width + 2 * uiconf.horizontal_padding);
}
if (self.w.title) |title| {
self.width = math.max(title.width + 2 * uiconf.horizontal_padding, self.width);
self.width = @max(title.width + 2 * uiconf.horizontal_padding, self.width);
self.height += title.height + uiconf.vertical_padding;
}
if (self.w.description) |description| {
self.width = math.max(description.width + 2 * uiconf.horizontal_padding, self.width);
self.width = @max(description.width + 2 * uiconf.horizontal_padding, self.width);
self.height += description.height + uiconf.vertical_padding;
}
if (self.w.errmessage) |errmessage| {
self.width = math.max(errmessage.width + 2 * uiconf.horizontal_padding, self.width);
self.width = @max(errmessage.width + 2 * uiconf.horizontal_padding, self.width);
self.height += errmessage.height + uiconf.vertical_padding;
}
@ -576,20 +575,20 @@ const Surface = struct {
if (self.w.ok) |ok| {
button_amount += 1;
combined_button_length += ok.width + uiconf.horizontal_padding + 2 * uiconf.button_inner_padding;
max_button_height = math.max(max_button_height, ok.height + 2 * uiconf.button_inner_padding);
max_button_height = @max(max_button_height, ok.height + 2 * uiconf.button_inner_padding);
}
if (self.w.notok) |notok| {
button_amount += 1;
combined_button_length += notok.width + uiconf.horizontal_padding + 2 * uiconf.button_inner_padding;
max_button_height = math.max(max_button_height, notok.height + 2 * uiconf.button_inner_padding);
max_button_height = @max(max_button_height, notok.height + 2 * uiconf.button_inner_padding);
}
if (self.w.cancel) |cancel| {
button_amount += 1;
combined_button_length += cancel.width + uiconf.horizontal_padding + 2 * uiconf.button_inner_padding;
max_button_height = math.max(max_button_height, cancel.height + 2 * uiconf.button_inner_padding);
max_button_height = @max(max_button_height, cancel.height + 2 * uiconf.button_inner_padding);
}
self.width = math.max(combined_button_length + uiconf.horizontal_padding, self.width);
self.width = @max(combined_button_length + uiconf.horizontal_padding, self.width);
if (max_button_height > 0) self.height += max_button_height + uiconf.vertical_padding;
@ -823,7 +822,7 @@ const Surface = struct {
var i: usize = 0;
while (i < len and i < uiconf.pin_square_amount) : (i += 1) {
const x = @intCast(u31, pinarea_x + (i * uiconf.pin_square_size) + ((i + 1) * square_padding));
const x: u31 = @intCast(pinarea_x + (i * uiconf.pin_square_size) + ((i + 1) * square_padding));
const y = pinarea_y + square_padding;
borderedRectangle(
image,
@ -852,11 +851,11 @@ const Surface = struct {
background_colour: *const pixman.Color,
border_colour: *const pixman.Color,
) void {
const x = @intCast(i16, _x * scale);
const y = @intCast(i16, _y * scale);
const width = @intCast(u15, _width * scale);
const height = @intCast(u15, _height * scale);
const border = @intCast(u15, _border * scale);
const x: i16 = @intCast(_x * scale);
const y: i16 = @intCast(_y * scale);
const width: u15 = @intCast(_width * scale);
const height: u15 = @intCast(_height * scale);
const border: u15 = @intCast(_border * scale);
_ = pixman.Image.fillRectangles(.src, image, background_colour, 1, &[1]pixman.Rectangle16{
.{ .x = x, .y = y, .width = width, .height = height },
});
@ -1009,10 +1008,10 @@ const Buffer = struct {
const pixman_image = pixman.Image.createBitsNoClear(
.a8r8g8b8,
@intCast(c_int, width),
@intCast(c_int, height),
@ptrCast([*c]u32, data),
@intCast(c_int, stride),
@as(c_int, @intCast(width)),
@as(c_int, @intCast(height)),
@as([*c]u32, @ptrCast(data)),
@as(c_int, @intCast(stride)),
);
errdefer _ = pixman_image.unref();
@ -1082,7 +1081,7 @@ pub fn init(self: *Wayland, cfg: *Config) !os.fd_t {
};
log.debug("trying to connect to '{s}'.", .{wayland_display});
self.display = try wl.Display.connect(@ptrCast([*:0]const u8, wayland_display.ptr));
self.display = try wl.Display.connect(@as([*:0]const u8, @ptrCast(wayland_display.ptr)));
errdefer self.deinit();
self.registry = try self.display.getRegistry();
@ -1181,13 +1180,13 @@ pub fn enterMode(self: *Wayland, mode: Frontend.InterfaceMode) !void {
fn initTextViews(self: *Wayland) !void {
const alloc = self.config.alloc;
const labels = self.config.labels;
if (labels.title) |title| self.title = try TextView.new(alloc, mem.trim(u8, title, &ascii.spaces), self.font_large.?);
if (labels.description) |description| self.description = try TextView.new(alloc, mem.trim(u8, description, &ascii.spaces), self.font_regular.?);
if (labels.err_message) |errmessage| self.errmessage = try TextView.new(alloc, mem.trim(u8, errmessage, &ascii.spaces), self.font_regular.?);
if (labels.prompt) |prompt| self.prompt = try TextView.new(alloc, mem.trim(u8, prompt, &ascii.spaces), self.font_large.?);
if (labels.ok) |ok| self.ok = try TextView.new(alloc, mem.trim(u8, ok, &ascii.spaces), self.font_regular.?);
if (labels.not_ok) |notok| self.notok = try TextView.new(alloc, mem.trim(u8, notok, &ascii.spaces), self.font_regular.?);
if (labels.cancel) |cancel| self.cancel = try TextView.new(alloc, mem.trim(u8, cancel, &ascii.spaces), self.font_regular.?);
if (labels.title) |title| self.title = try TextView.new(alloc, mem.trim(u8, title, &ascii.whitespace), self.font_large.?);
if (labels.description) |description| self.description = try TextView.new(alloc, mem.trim(u8, description, &ascii.whitespace), self.font_regular.?);
if (labels.err_message) |errmessage| self.errmessage = try TextView.new(alloc, mem.trim(u8, errmessage, &ascii.whitespace), self.font_regular.?);
if (labels.prompt) |prompt| self.prompt = try TextView.new(alloc, mem.trim(u8, prompt, &ascii.whitespace), self.font_large.?);
if (labels.ok) |ok| self.ok = try TextView.new(alloc, mem.trim(u8, ok, &ascii.whitespace), self.font_regular.?);
if (labels.not_ok) |notok| self.notok = try TextView.new(alloc, mem.trim(u8, notok, &ascii.whitespace), self.font_regular.?);
if (labels.cancel) |cancel| self.cancel = try TextView.new(alloc, mem.trim(u8, cancel, &ascii.whitespace), self.font_regular.?);
}
fn deinitTextViews(self: *Wayland) void {
@ -1313,22 +1312,22 @@ fn abort(self: *Wayland, reason: anyerror) void {
fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, self: *Wayland) void {
switch (event) {
.global => |ev| {
if (cstr.cmp(ev.interface, zwlr.LayerShellV1.getInterface().name) == 0) {
if (mem.orderZ(u8, ev.interface, zwlr.LayerShellV1.getInterface().name) == .eq) {
self.layer_shell = registry.bind(ev.name, zwlr.LayerShellV1, 4) catch {
self.abort(error.OutOfMemory);
return;
};
} else if (cstr.cmp(ev.interface, wl.Compositor.getInterface().name) == 0) {
} else if (mem.orderZ(u8, ev.interface, wl.Compositor.getInterface().name) == .eq) {
self.compositor = registry.bind(ev.name, wl.Compositor, 4) catch {
self.abort(error.OutOfMemory);
return;
};
} else if (cstr.cmp(ev.interface, wl.Shm.getInterface().name) == 0) {
} else if (mem.orderZ(u8, ev.interface, wl.Shm.getInterface().name) == .eq) {
self.shm = registry.bind(ev.name, wl.Shm, 1) catch {
self.abort(error.OutOfMemory);
return;
};
} else if (cstr.cmp(ev.interface, wl.Seat.getInterface().name) == 0) {
} else if (mem.orderZ(u8, ev.interface, wl.Seat.getInterface().name) == .eq) {
const seat = registry.bind(ev.name, wl.Seat, 1) catch {
self.abort(error.OutOfMemory);
return;

View file

@ -33,12 +33,12 @@ fn IniTok(comptime T: type) type {
if (__buf.len == 0) continue;
const buf = blk: {
const _buf = mem.trim(u8, __buf, &ascii.spaces);
const _buf = mem.trim(u8, __buf, &ascii.whitespace);
if (_buf.len == 0) continue;
if (_buf[0] == '#') continue;
for (_buf[1..]) |char, i| {
for (_buf[1..], 0..) |char, i| {
if (char == '#' and _buf[i - 1] != '\\') {
break :blk mem.trim(u8, _buf[0 .. i + 1], &ascii.spaces);
break :blk mem.trim(u8, _buf[0 .. i + 1], &ascii.whitespace);
}
}
break :blk _buf;
@ -53,7 +53,7 @@ fn IniTok(comptime T: type) type {
// Is this line an assignment?
var eq_pos = blk: {
for (buf) |char, i| {
for (buf, 0..) |char, i| {
if (char == '=') {
if (i == buf.len - 1) return error.InvalidLine;
break :blk i;
@ -64,15 +64,14 @@ fn IniTok(comptime T: type) type {
return Content{
.assign = .{
.variable = blk: {
const variable = mem.trim(u8, buf[0..eq_pos], &ascii.spaces);
const variable = mem.trim(u8, buf[0..eq_pos], &ascii.whitespace);
if (variable.len == 0) return error.InvalidLine;
break :blk variable;
},
.value = blk: {
const value = mem.trim(u8, buf[eq_pos + 1 ..], &ascii.spaces);
const value = mem.trim(u8, buf[eq_pos + 1 ..], &ascii.whitespace);
if (value.len < 2 or value[value.len - 1] != ';') return error.InvalidLine;
// TODO[zig] should be inline, but that crashes the zig compiler right now
for ([_]u8{ '\'', '"' }) |q| {
inline for ([_]u8{ '\'', '"' }) |q| {
if (value[0] == q) {
if (value[value.len - 2] == q and value.len > 3) {
break :blk value[1 .. value.len - 2];

View file

@ -251,7 +251,7 @@ fn parseInput(writer: io.BufferedWriter(4096, fs.File.Writer).Writer, line: []co
if (mode != .none) return;
const alloc = gpa.allocator();
var it = mem.tokenize(u8, line, &ascii.spaces);
var it = mem.tokenize(u8, line, &ascii.whitespace);
const command = it.next() orelse return;
if (ascii.eqlIgnoreCase(command, "settitle")) {
try setString(writer, "title", line["settitle".len..]);