moved ini to a lib, fixed alternative langs

pull/596/head
Kinzie 2 months ago
parent 17e87cb6f6
commit 0aa400383a

@ -1,10 +1,15 @@
const std = @import("std");
const ly_version = std.SemanticVersion{ .major = 1, .minor = 0, .patch = 0 };
pub fn build(b: *std.Build) void {
const data_directory = b.option([]const u8, "data_directory", "Specify a default data directory (default is /etc/ly)");
const build_options = b.addOptions();
build_options.addOption([]const u8, "data_directory", data_directory orelse "/etc/ly");
var version_str = b.fmt("{d}.{d}.{d}", .{ ly_version.major, ly_version.minor, ly_version.patch });
build_options.addOption([]const u8, "version", version_str);
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
@ -29,10 +34,10 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
});
exe.addOptions("build_options", build_options);
const zigini = b.dependency("zigini", .{ .target = target, .optimize = optimize });
exe.addModule("zigini", zigini.module("zigini"));
const ini = b.dependency("ini", .{});
exe.addModule("ini", ini.module("ini"));
exe.addOptions("build_options", build_options);
const clap = b.dependency("clap", .{ .target = target, .optimize = optimize });
exe.addModule("clap", clap.module("clap"));

@ -2,13 +2,13 @@
.name = "ly",
.version = "1.0.0",
.dependencies = .{
.ini = .{
.url = "https://github.com/ziglibs/ini/archive/2b11e8fef86d0eefb225156e695be1c1d5c35cbc.tar.gz",
.hash = "1220ed24f7dda09121a175601ddd5c86c1cc937d061a97d38aef049ee4af76e2f594",
},
.clap = .{
.url = "https://github.com/Hejsil/zig-clap/archive/f49b94700e0761b7514abdca0e4f0e7f3f938a93.tar.gz",
.hash = "1220f48518ce22882e102255ed3bcdb7aeeb4891f50b2cdd3bd74b5b2e24d3149ba2",
},
.zigini = .{
.url = "https://github.com/Kawaii-Ash/zigini/archive/91f47e46591982fc559afa3248749c1d29a0fa2a.tar.gz",
.hash = "12209908f2773f730fbca024c80dc7f48dce15a6527b2387f3768968f5bae0d3931e",
},
},
}

@ -1,4 +1,3 @@
[ly]
capslock = Bloq Majús
err_alloc = falla d'assignació de memòria
err_bounds = índex fora de límit

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = alokace paměti selhala
err_bounds = index je mimo hranice pole

@ -1,4 +1,3 @@
[ly]
capslock = Feststelltaste
err_alloc = Speicherzuweisung fehlgeschlagen
err_bounds = Listenindex ist außerhalb des Bereichs

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = failed memory allocation
err_bounds = out-of-bounds index

@ -1,4 +1,3 @@
[ly]
capslock = Bloq Mayús
err_alloc = asignación de memoria fallida
err_bounds = índice fuera de límites

@ -1,5 +1,4 @@
[ly]
capslock = verr.maj
capslock = verr.maj
err_alloc = échec d'allocation mémoire
err_bounds = indice hors-limite
err_chdir = échec de l'ouverture du répertoire home

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = impossibile allocare memoria
err_bounds = indice fuori limite

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = nieudana alokacja pamięci
err_bounds = indeks poza granicami

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = erro na atribuição de memória
err_bounds = índice fora de limites

@ -1,4 +1,3 @@
[ly]
capslock = caixa alta
err_alloc = alocação de memória malsucedida
err_bounds = índice fora de limites

@ -1,4 +1,3 @@
[ly]
capslock = capslock

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = не удалось выделить память
err_bounds = за пределами индекса

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = neuspijesna alokacija memorije
err_bounds = izvan granica indeksa

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = misslyckad minnesallokering
err_bounds = utanför banan index

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = basarisiz bellek ayirma
err_bounds = sinirlarin disinda dizin

@ -1,4 +1,3 @@
[ly]
capslock = capslock
err_alloc = невдале виділення пам'яті
err_bounds = поза межами індексу

@ -13,8 +13,8 @@ bigclock: bool = false,
blank_box: bool = true,
border_fg: u8 = 8,
clear_password: bool = false,
clock: ?[]const u8 = null,
console_dev: []const u8 = "/dev/console",
clock: ?[:0]const u8 = null,
console_dev: [:0]const u8 = "/dev/console",
default_input: Input = .login,
fg: u8 = 8,
hide_borders: bool = false,

@ -1,194 +0,0 @@
const std = @import("std");
const ini = @import("ini");
const Allocator = std.mem.Allocator;
const trueOrFalse = std.ComptimeStringMap(bool, .{ .{ "true", true }, .{ "false", false }, .{ "1", true }, .{ "0", false } });
pub fn Ini(comptime T: type) type {
return struct {
const Self = @This();
data: T,
allocator: std.mem.Allocator,
list: std.ArrayList([]u8),
pub fn init(allocator: std.mem.Allocator) Self {
return .{
.data = T{},
.allocator = allocator,
.list = std.ArrayList([]u8).init(allocator),
};
}
pub fn deinit(self: *Self) void {
for (self.list.items) |item| {
self.allocator.free(item);
}
self.list.deinit();
}
pub fn readToStruct(self: *Self, path: []const u8) !T {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
var parser = ini.parse(self.allocator, file.reader());
defer parser.deinit();
var ns: []u8 = &.{};
defer self.allocator.free(ns);
while (try parser.next()) |record| {
switch (record) {
.section => |heading| {
ns = try self.allocator.realloc(ns, heading.len);
@memcpy(ns, heading);
std.mem.replaceScalar(u8, ns, ' ', '_');
},
.property => |kv| {
inline for (std.meta.fields(T)) |field| {
const field_info = @typeInfo(field.type);
if (field_info == .Struct or (field_info == .Optional and @typeInfo(field_info.Optional.child) == .Struct)) {
if (ns.len != 0 and std.mem.eql(u8, field.name, ns)) {
inline for (std.meta.fields(@TypeOf(@field(self.data, field.name)))) |inner_field| {
if (std.mem.eql(u8, inner_field.name, kv.key)) {
@field(@field(self.data, field.name), inner_field.name) = try self.convert(inner_field.type, kv.value);
}
}
}
} else if (ns.len == 0 and std.mem.eql(u8, field.name, kv.key)) {
@field(self.data, field.name) = try self.convert(field.type, kv.value);
}
}
},
.enumeration => {},
}
}
return self.data;
}
fn convert(self: *Self, comptime T1: type, val: []const u8) !T1 {
return switch (@typeInfo(T1)) {
.Int, .ComptimeInt => try std.fmt.parseInt(T1, val, 0),
.Float, .ComptimeFloat => try std.fmt.parseFloat(T1, val),
.Bool => trueOrFalse.get(val).?,
.Enum => std.meta.stringToEnum(T1, val).?,
.Optional => |opt| {
if (val.len == 0 or std.mem.eql(u8, val, "null")) return null;
return try self.convert(opt.child, val);
},
else => {
const a_val = try self.allocator.alloc(u8, val.len);
@memcpy(a_val, val);
try self.list.append(a_val);
return @as(T1, a_val);
},
};
}
};
}
fn writeProperty(writer: anytype, field_name: []const u8, val: anytype) !void {
switch (@typeInfo(@TypeOf(val))) {
.Bool => {
try writer.print("{s}={d}\n", .{ field_name, @intFromBool(val) });
},
.Int, .ComptimeInt, .Float, .ComptimeFloat => {
try writer.print("{s}={d}\n", .{ field_name, val });
},
.Enum => {
try writer.print("{s}={s}\n", .{ field_name, @tagName(val) });
},
else => {
try writer.print("{s}={s}\n", .{ field_name, val });
},
}
}
fn isDefaultValue(field: anytype, field_value: field.type) bool {
if (field.default_value) |default_value_ao| {
const def_val: *align(field.alignment) const anyopaque = @alignCast(default_value_ao);
const default_value = @as(*const field.type, @ptrCast(def_val)).*;
const field_t_info = @typeInfo(field.type);
if (field_t_info == .Optional) {
if (default_value != null) {
if (field_value != null) {
if (field_t_info == .Pointer) {
return std.mem.eql(field_t_info.Pointer.child, default_value.?, field_value.?);
} else {
return default_value.? == field_value.?;
}
}
return false;
}
return field_value == null;
}
if (field_t_info == .Pointer) {
return std.mem.eql(field_t_info.Pointer.child, default_value, field_value);
} else {
return default_value == field_value;
}
}
return false;
}
pub fn writeFromStruct(data: anytype, writer: anytype, ns: ?[]const u8) !void {
if (@typeInfo(@TypeOf(data)) != .Struct) @compileError("writeFromStruct() requires a struct");
var should_write_ns = ns != null;
inline for (std.meta.fields(@TypeOf(data))) |field| {
switch (@typeInfo(field.type)) {
.Struct => continue,
.Optional => |opt| {
if (@typeInfo(opt.child) != .Struct) {
const val = @field(data, field.name);
if (val) |field_val| {
if (!isDefaultValue(field, @field(data, field.name))) {
if (should_write_ns) {
try writer.print("[{s}]\n", .{ns.?});
should_write_ns = false;
}
try writeProperty(writer, field.name, field_val);
}
} else if (!isDefaultValue(field, @field(data, field.name))) {
if (should_write_ns) {
try writer.print("[{s}]\n", .{ns.?});
should_write_ns = false;
}
try writeProperty(writer, field.name, "");
}
} else continue;
},
else => {
if (!isDefaultValue(field, @field(data, field.name))) {
if (should_write_ns) {
try writer.print("[{s}]\n", .{ns.?});
should_write_ns = false;
}
try writeProperty(writer, field.name, @field(data, field.name));
}
},
}
}
if (ns == null) {
inline for (std.meta.fields(@TypeOf(data))) |field| {
switch (@typeInfo(field.type)) {
.Struct => {
try writeFromStruct(@field(data, field.name), writer, field.name);
},
.Optional => |opt| {
if (@typeInfo(opt.child) == .Struct) {
if (@field(data, field.name)) |inner_data| {
try writeFromStruct(inner_data, writer, field.name);
}
} else continue;
},
else => continue,
}
}
}
}

@ -18,10 +18,6 @@ pub const xcb = @cImport({
@cInclude("xcb/xcb.h");
});
pub const c_size = u64;
pub const c_uid = u32;
pub const c_gid = u32;
pub const c_time = c_long;
pub const tm = extern struct {
tm_sec: c_int,
tm_min: c_int,
@ -37,8 +33,8 @@ pub const passwd = extern struct {
pw_name: [*:0]u8,
pw_passwd: [*:0]u8,
pw_uid: c_uid,
pw_gid: c_gid,
pw_uid: u32,
pw_gid: u32,
pw_gecos: [*:0]u8,
pw_dir: [*:0]u8,
pw_shell: [*:0]u8,
@ -68,20 +64,20 @@ pub const O_RDWR: c_uint = 0x02;
pub extern "c" fn fileno(stream: *std.c.FILE) c_int;
pub extern "c" fn sysconf(name: c_int) c_long;
pub extern "c" fn time(second: ?*c_time) c_time;
pub extern "c" fn localtime(timer: *const c_time) *tm;
pub extern "c" fn strftime(str: [*:0]u8, maxsize: c_size, format: [*:0]const u8, timeptr: *const tm) c_size;
pub extern "c" fn time(second: ?*c_long) c_long;
pub extern "c" fn localtime(timer: *const c_long) *tm;
pub extern "c" fn strftime(str: [*:0]u8, maxsize: u64, format: [*:0]const u8, timeptr: *const tm) u64;
pub extern "c" fn setenv(name: [*:0]const u8, value: [*:0]const u8, overwrite: c_int) c_int;
pub extern "c" fn getenv(name: [*:0]const u8) [*:0]u8;
pub extern "c" fn putenv(name: [*:0]u8) c_int;
pub extern "c" fn clearenv() c_int;
pub extern "c" fn getuid() c_uid;
pub extern "c" fn getuid() u32;
pub extern "c" fn getpwnam(name: [*:0]const u8) ?*passwd;
pub extern "c" fn endpwent() void;
pub extern "c" fn setusershell() void;
pub extern "c" fn getusershell() [*:0]u8;
pub extern "c" fn endusershell() void;
pub extern "c" fn initgroups(user: [*:0]const u8, group: c_gid) c_int;
pub extern "c" fn initgroups(user: [*:0]const u8, group: u32) c_int;
pub extern "c" fn chdir(path: [*:0]const u8) c_int;
pub extern "c" fn execl(path: [*:0]const u8, arg: [*:0]const u8, ...) c_int;
@ -93,6 +89,7 @@ pub fn getHostName(allocator: Allocator) !struct {
const hostname_max_length: u64 = if (hostname_sysconf < 0) @intCast(_POSIX_HOST_NAME_MAX) else @intCast(hostname_sysconf);
const buffer = try allocator.alloc(u8, hostname_max_length);
errdefer allocator.free(buffer);
const error_code = std.c.gethostname(buffer.ptr, hostname_max_length);
if (error_code < 0) return error.CannotGetHostName;
@ -111,27 +108,21 @@ pub fn getHostName(allocator: Allocator) !struct {
};
}
pub fn timeAsString(allocator: Allocator, format: []const u8, max_length: u64) ![:0]u8 {
pub fn timeAsString(allocator: Allocator, format: [:0]const u8, max_length: u64) ![:0]u8 {
const timer = time(null);
const tm_info = localtime(&timer);
const buffer = try allocator.allocSentinel(u8, max_length, 0);
const format_z = try allocator.dupeZ(u8, format);
defer allocator.free(format_z);
if (strftime(buffer, max_length, format_z, tm_info) < 0) return error.CannotGetFormattedTime;
if (strftime(buffer, max_length, format, tm_info) < 0) return error.CannotGetFormattedTime;
return buffer;
}
pub fn getLockState(allocator: Allocator, console_dev: []const u8) !struct {
pub fn getLockState(console_dev: [:0]const u8) !struct {
numlock: bool,
capslock: bool,
} {
const console_dev_z = try allocator.dupeZ(u8, console_dev);
defer allocator.free(console_dev_z);
const fd = std.c.open(console_dev_z, O_RDONLY);
const fd = std.c.open(console_dev, O_RDONLY);
if (fd < 0) return error.CannotOpenConsoleDev;
var numlock = false;

@ -11,17 +11,16 @@ const TerminalBuffer = @import("tui/TerminalBuffer.zig");
const Desktop = @import("tui/components/Desktop.zig");
const Text = @import("tui/components/Text.zig");
const Config = @import("config/Config.zig");
const ini = @import("config/ini.zig");
const ini = @import("zigini");
const Lang = @import("config/Lang.zig");
const Save = @import("config/Save.zig");
const ViMode = @import("enums.zig").ViMode;
const SharedError = @import("SharedError.zig");
const utils = @import("tui/utils.zig");
const Ini = ini.Ini;
const termbox = interop.termbox;
const LY_VERSION = "1.0.0";
pub fn signalHandler(i: c_int) callconv(.C) void {
termbox.tb_shutdown();
std.c.exit(i);
@ -59,7 +58,7 @@ pub fn main() !void {
std.os.exit(0);
}
if (res.args.version != 0) {
_ = try stderr.write("Ly version " ++ LY_VERSION ++ "\n");
_ = try stderr.write("Ly version " ++ build_options.version ++ "\n");
std.os.exit(0);
}
@ -352,8 +351,11 @@ pub fn main() !void {
buffer.drawLabel(lang.password, label_x, label_y + 6);
if (info_line.len > 0) {
const x = buffer.box_x + ((buffer.box_width - info_line.len) / 2);
buffer.drawLabel(info_line, x, label_y);
const info_line_width = try utils.strWidth(info_line);
if (buffer.box_width > info_line_width) {
const x = buffer.box_x + ((buffer.box_width - info_line_width) / 2);
buffer.drawLabel(info_line, x, label_y);
}
}
if (!config.hide_key_hints) {
@ -364,14 +366,16 @@ pub fn main() !void {
buffer.drawLabel(" ", length - 1, 0);
buffer.drawLabel(lang.shutdown, length, 0);
length += lang.shutdown.len + 1;
const shutdown_len = try utils.strWidth(lang.shutdown);
length += shutdown_len + 1;
buffer.drawLabel(config.restart_key, length, 0);
length += config.restart_key.len + 1;
buffer.drawLabel(" ", length - 1, 0);
buffer.drawLabel(lang.restart, length, 0);
length += lang.restart.len + 1;
const restart_len = try utils.strWidth(lang.restart);
length += restart_len + 1;
if (config.sleep_cmd != null) {
buffer.drawLabel(config.sleep_key, length, 0);
@ -388,7 +392,7 @@ pub fn main() !void {
}
draw_lock_state: {
const lock_state = interop.getLockState(allocator, config.console_dev) catch |err| {
const lock_state = interop.getLockState(config.console_dev) catch |err| {
if (err == error.CannotOpenConsoleDev) {
info_line = lang.err_console_dev;
} else {

@ -161,7 +161,13 @@ pub fn calculateComponentCoordinates(self: TerminalBuffer) struct {
pub fn drawLabel(self: TerminalBuffer, text: []const u8, x: u64, y: u64) void {
const yc: c_int = @intCast(y);
for (0..text.len) |xx| termbox.tb_change_cell(@intCast(x + xx), yc, text[xx], self.fg, self.bg);
const utf8view = std.unicode.Utf8View.init(text) catch return;
var utf8 = utf8view.iterator();
var i = x;
while (utf8.nextCodepoint()) |codepoint| : (i += 1) {
termbox.tb_change_cell(@intCast(i), yc, codepoint, self.fg, self.bg);
}
}
pub fn drawCharMultiple(self: TerminalBuffer, char: u8, x: u64, y: u64, length: u64) void {

@ -1,9 +1,8 @@
const std = @import("std");
const ini = @import("ini");
const enums = @import("../../enums.zig");
const interop = @import("../../interop.zig");
const TerminalBuffer = @import("../TerminalBuffer.zig");
const Ini = @import("../../config/ini.zig").Ini;
const Ini = @import("zigini").Ini;
const Allocator = std.mem.Allocator;
const EnvironmentList = std.ArrayList(Environment);
@ -74,7 +73,7 @@ pub fn addEnvironment(self: *Desktop, name: []const u8, cmd: []const u8, display
.specifier = switch (display_server) {
.wayland => "wayland",
.x11 => "x11",
else => "other",
else => "",
},
.display_server = display_server,
});
@ -91,7 +90,7 @@ pub fn addEnvironmentWithIni(self: *Desktop, entry_ini: Ini(Entry), name: []cons
.specifier = switch (display_server) {
.wayland => "wayland",
.x11 => "x11",
else => "other",
else => "",
},
.display_server = display_server,
});

@ -3,10 +3,20 @@ const interop = @import("../interop.zig");
const termbox = interop.termbox;
pub inline fn initCell(ch: u32, fg: u32, bg: u32) termbox.tb_cell {
pub fn initCell(ch: u32, fg: u32, bg: u32) termbox.tb_cell {
return .{
.ch = ch,
.fg = fg,
.bg = bg,
};
}
// Every codepoint is assumed to have a width of 1.
// Since ly should be running in a tty, this should be fine.
pub fn strWidth(str: []const u8) !u8 {
const utf8view = try std.unicode.Utf8View.init(str);
var utf8 = utf8view.iterator();
var i: u8 = 0;
while (utf8.nextCodepoint()) |_| i += 1;
return i;
}

Loading…
Cancel
Save