From d3231fa281e00dc6b28bf75198bfd8f696fa0be0 Mon Sep 17 00:00:00 2001 From: Kinzie Date: Mon, 15 Apr 2024 21:44:52 +0100 Subject: [PATCH] code improvements --- build.zig | 2 +- changelog.md | 16 ++-- res/lang/en.ini | 4 + src/animations/Matrix.zig | 127 ++++++++++++++++---------------- src/auth.zig | 39 +++++----- src/config/Lang.zig | 2 + src/interop.zig | 1 + src/main.zig | 76 +++++++++---------- src/tui/components/Desktop.zig | 31 ++++---- src/tui/components/InfoLine.zig | 11 +++ 10 files changed, 164 insertions(+), 145 deletions(-) create mode 100644 src/tui/components/InfoLine.zig diff --git a/build.zig b/build.zig index 97df282..8542261 100644 --- a/build.zig +++ b/build.zig @@ -7,7 +7,7 @@ pub fn build(b: *std.Build) void { 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 }); + const version_str = b.fmt("{d}.{d}.{d}", .{ ly_version.major, ly_version.minor, ly_version.patch }); build_options.addOption([]const u8, "version", version_str); diff --git a/changelog.md b/changelog.md index 7278a75..fa1b90d 100644 --- a/changelog.md +++ b/changelog.md @@ -6,21 +6,21 @@ res/config.ini contains all of the available config options and their default va ### Additions -+ border\_fg has been introduced to change the color of the borders. -+ term\_restore\_cursor\_cmd should restore the cursor to it's usual state. -+ vi\_mode to enable vi keybindings. -+ sleep\_key and sleep\_cmd. ++ `border_fg` has been introduced to change the color of the borders. ++ `term_restore_cursor_cmd` should restore the cursor to it's usual state. ++ `vi_mode` to enable vi keybindings. ++ `sleep_key` and `sleep_cmd`. -Note: sleep\_cmd is unset by default, meaning it's hidden and has no effect. +Note: `sleep_cmd` is unset by default, meaning it's hidden and has no effect. ### Changes + xinitrc can be set to null to hide it. -+ blank\_password has been renamed to clear\_password. ++ `blank_password` has been renamed to `clear_password`. ### Removals -+ wayland\_specifier has been removed. ++ `wayland_specifier` has been removed. ## Save File @@ -37,7 +37,7 @@ session_index = 0 + Display server name added next to selected session. + getty@tty2 has been added as a conflict in res/ly.service, so if it is running, ly should still be able to start. -+ XDG\_CURRENT\_DESKTOP is now set by ly. ++ `XDG_CURRENT_DESKTOP` is now set by ly. + LANG is no longer set by ly. + X Server PID is fetched from /tmp/X{d}.lock to be able to kill the process since it detaches. + Non .desktop files are now ignored in sessions directory. diff --git a/res/lang/en.ini b/res/lang/en.ini index 71776e5..9ecb5ac 100644 --- a/res/lang/en.ini +++ b/res/lang/en.ini @@ -34,12 +34,16 @@ err_user_init = failed to initialize user err_user_uid = failed to set user UID err_xsessions_dir = failed to find sessions folder err_xsessions_open = failed to open sessions folder +insert = Insert login = login logout = logged out +normal = Normal numlock = numlock password = password restart = reboot shell = shell shutdown = shutdown +sleep = sleep wayland = wayland xinitrc = xinitrc +x11 = x11 diff --git a/src/animations/Matrix.zig b/src/animations/Matrix.zig index 9c62ee0..52d3cc6 100644 --- a/src/animations/Matrix.zig +++ b/src/animations/Matrix.zig @@ -75,85 +75,84 @@ pub fn draw(self: *Matrix) void { if (self.frame > 4) self.frame = 1; self.count = 0; - var j: u64 = 0; - while (j < self.terminal_buffer.width) : (j += 2) { + var x: u64 = 0; + while (x < self.terminal_buffer.width) : (x += 2) { var tail: u64 = 0; - var line = &self.lines[j]; - if (self.frame > line.update) { - if (self.dots[j].value == -1 and self.dots[self.terminal_buffer.width + j].value == ' ') { - if (line.space > 0) { - line.space -= 1; - } else { - const randint = self.terminal_buffer.random.int(i16); - const h: isize = @intCast(self.terminal_buffer.height); - line.length = @mod(randint, h - 3) + 3; - self.dots[j].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; - line.space = @mod(randint, h + 1); - } - } - - var i: u64 = 0; - var first_col = true; - var seg_len: u64 = 0; - height_it: while (i <= buf_height) { - var dot = &self.dots[buf_width * i + j]; - // Skip over spaces - while (i <= buf_height and (dot.value == ' ' or dot.value == -1)) { - i += 1; - if (i > buf_height) break :height_it; - dot = &self.dots[buf_width * i + j]; - } - - // Find the head of this col - tail = i; - seg_len = 0; - while (i <= buf_height and (dot.value != ' ' and dot.value != -1)) { - dot.is_head = false; - if (MID_SCROLL_CHANGE) { - const randint = self.terminal_buffer.random.int(i16); - if (@mod(randint, 8) == 0) - dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; - } - - i += 1; - seg_len += 1; - // Head's down offscreen - if (i > buf_height) { - self.dots[buf_width * tail + j].value = ' '; - break :height_it; - } - dot = &self.dots[buf_width * i + j]; - } + var line = &self.lines[x]; + if (self.frame <= line.update) continue; + if (self.dots[x].value == -1 and self.dots[self.terminal_buffer.width + x].value == ' ') { + if (line.space > 0) { + line.space -= 1; + } else { const randint = self.terminal_buffer.random.int(i16); - dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; - dot.is_head = true; - - if (seg_len > self.lines[j].length or !first_col) { - self.dots[buf_width * tail + j].value = ' '; - self.dots[j].value = -1; - } - first_col = false; - i += 1; + const h: isize = @intCast(self.terminal_buffer.height); + line.length = @mod(randint, h - 3) + 3; + self.dots[x].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; + line.space = @mod(randint, h + 1); } } + + var y: u64 = 0; + var first_col = true; + var seg_len: u64 = 0; + height_it: while (y <= buf_height) : (y += 1) { + var dot = &self.dots[buf_width * y + x]; + // Skip over spaces + while (y <= buf_height and (dot.value == ' ' or dot.value == -1)) { + y += 1; + if (y > buf_height) break :height_it; + dot = &self.dots[buf_width * y + x]; + } + + // Find the head of this column + tail = y; + seg_len = 0; + while (y <= buf_height and dot.value != ' ' and dot.value != -1) { + dot.is_head = false; + if (MID_SCROLL_CHANGE) { + const randint = self.terminal_buffer.random.int(i16); + if (@mod(randint, 8) == 0) + dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; + } + + y += 1; + seg_len += 1; + // Head's down offscreen + if (y > buf_height) { + self.dots[buf_width * tail + x].value = ' '; + break :height_it; + } + dot = &self.dots[buf_width * y + x]; + } + + const randint = self.terminal_buffer.random.int(i16); + dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; + dot.is_head = true; + + if (seg_len > line.length or !first_col) { + self.dots[buf_width * tail + x].value = ' '; + self.dots[x].value = -1; + } + first_col = false; + } } } - var j: u64 = 0; - while (j < buf_width) : (j += 2) { - var i: u64 = 1; - while (i <= self.terminal_buffer.height) : (i += 1) { - const dot = self.dots[buf_width * i + j]; + var x: u64 = 0; + while (x < buf_width) : (x += 2) { + var y: u64 = 1; + while (y <= self.terminal_buffer.height) : (y += 1) { + const dot = self.dots[buf_width * y + x]; var fg: u32 = @intCast(termbox.TB_GREEN); if (dot.value == -1 or dot.value == ' ') { - termbox.tb_change_cell(@intCast(j), @intCast(i - 1), ' ', fg, termbox.TB_DEFAULT); + termbox.tb_change_cell(@intCast(x), @intCast(y - 1), ' ', fg, termbox.TB_DEFAULT); continue; } if (dot.is_head) fg = @intCast(termbox.TB_WHITE | termbox.TB_BOLD); - termbox.tb_change_cell(@intCast(j), @intCast(i - 1), @intCast(dot.value), fg, termbox.TB_DEFAULT); + termbox.tb_change_cell(@intCast(x), @intCast(y - 1), @intCast(dot.value), fg, termbox.TB_DEFAULT); } } } diff --git a/src/auth.zig b/src/auth.zig index b352502..afb4881 100644 --- a/src/auth.zig +++ b/src/auth.zig @@ -243,7 +243,7 @@ fn loginConv( const message_count: u32 = @intCast(num_msg); const messages = msg.?; - var allocator = std.heap.c_allocator; + const allocator = std.heap.c_allocator; const response = allocator.alloc(interop.pam.pam_response, message_count) catch return interop.pam.PAM_BUF_ERR; var username: ?[:0]u8 = null; @@ -306,10 +306,10 @@ fn getFreeDisplay() !u8 { return i; } -fn getXPid(display_num: u8) !i32 { +fn getXPID(display_num: u8) !i32 { var buf: [15]u8 = undefined; const file_name = try std.fmt.bufPrint(&buf, "/tmp/.X{d}-lock", .{display_num}); - const file = try std.fs.openFileAbsolute(file_name, std.fs.File.OpenFlags{}); + const file = try std.fs.openFileAbsolute(file_name, .{}); defer file.close(); var file_buf: [20]u8 = undefined; @@ -363,8 +363,7 @@ fn createXauthFile(pwd: [:0]const u8) ![:0]const u8 { var buf: [256]u8 = undefined; const xauthority: [:0]u8 = try std.fmt.bufPrintZ(&buf, "{s}/{s}", .{ trimmed_xauth_dir, xauth_file }); - const createFlags = std.fs.File.CreateFlags{}; - const file = try std.fs.createFileAbsolute(xauthority, createFlags); + const file = try std.fs.createFileAbsolute(xauthority, .{}); file.close(); return xauthority; @@ -379,7 +378,6 @@ fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, xaut _ = interop.setenv("DISPLAY", display_name, 1); const pid = try std.os.fork(); - if (pid == 0) { var cmd_buffer: [1024]u8 = undefined; const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . $({s})", .{ xauth_cmd, display_name, mcookie_cmd }) catch std.os.exit(1); @@ -400,10 +398,10 @@ fn executeWaylandCmd(shell: [*:0]const u8, wayland_cmd: []const u8, desktop_cmd: fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, desktop_cmd: []const u8, vt: []const u8) !void { const display_num = try getFreeDisplay(); var buf: [5]u8 = undefined; - var display_name: [:0]u8 = try std.fmt.bufPrintZ(&buf, ":{d}", .{display_num}); + var display_name = try std.fmt.bufPrintZ(&buf, ":{d}", .{display_num}); try xauth(display_name, shell, pw_dir, config.xauth_cmd, config.mcookie_cmd); - const pid = std.c.fork(); + const pid = try std.os.fork(); if (pid == 0) { var cmd_buffer: [1024]u8 = undefined; const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ config.x_cmd, display_name, vt }) catch std.os.exit(1); @@ -417,16 +415,14 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de xcb = interop.xcb.xcb_connect(null, null); ok = interop.xcb.xcb_connection_has_error(xcb); _ = std.c.kill(pid, 0); - if (std.c._errno().* == interop.ESRCH and ok != 0) { - return; - } + if (std.c._errno().* == interop.ESRCH and ok != 0) return; } // X Server detaches from the process. - // Pid can be fetched from /tmp/X{d}.lock - const x_pid = try getXPid(display_num); + // PID can be fetched from /tmp/X{d}.lock + const x_pid = try getXPID(display_num); - const xorg_pid = std.c.fork(); + const xorg_pid = try std.os.fork(); if (xorg_pid == 0) { var cmd_buffer: [1024]u8 = undefined; const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s}", .{ config.x_cmd_setup, desktop_cmd }) catch std.os.exit(1); @@ -435,7 +431,7 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de } var status: c_int = 0; - _ = std.c.waitpid(xorg_pid, &status, 0); + _ = std.os.waitpid(xorg_pid, 0); interop.xcb.xcb_disconnect(xcb); _ = std.c.kill(x_pid, 0); @@ -456,14 +452,14 @@ fn addUtmpEntry(entry: *Utmp, username: [*:0]const u8, pid: c_int) !void { var buf: [4096]u8 = undefined; const ttyname = try std.os.getFdPath(0, &buf); - var ttyname_buf: [32]u8 = std.mem.zeroes([32]u8); - _ = try std.fmt.bufPrint(&ttyname_buf, "{s}", .{ttyname["/dev/".len..]}); + var ttyname_buf: [32]u8 = undefined; + _ = try std.fmt.bufPrintZ(&ttyname_buf, "{s}", .{ttyname["/dev/".len..]}); entry.ut_line = ttyname_buf; entry.ut_id = ttyname_buf["tty".len..7].*; - var username_buf: [32]u8 = std.mem.zeroes([32]u8); - _ = try std.fmt.bufPrint(&username_buf, "{s}", .{username}); + var username_buf: [32]u8 = undefined; + _ = try std.fmt.bufPrintZ(&username_buf, "{s}", .{username}); entry.ut_user = username_buf; @@ -480,12 +476,13 @@ fn addUtmpEntry(entry: *Utmp, username: [*:0]const u8, pid: c_int) !void { utmp.setutent(); _ = utmp.pututline(entry); + utmp.endutent(); } fn removeUtmpEntry(entry: *Utmp) void { entry.ut_type = utmp.DEAD_PROCESS; - entry.ut_line = std.mem.zeroes([32]u8); - entry.ut_user = std.mem.zeroes([32]u8); + entry.ut_line[0] = 0; + entry.ut_user[0] = 0; utmp.setutent(); _ = utmp.pututline(entry); utmp.endutent(); diff --git a/src/config/Lang.zig b/src/config/Lang.zig index 4d3a934..1dd3018 100644 --- a/src/config/Lang.zig +++ b/src/config/Lang.zig @@ -41,6 +41,7 @@ login: []const u8 = "login:", logout: []const u8 = "logged out", normal: []const u8 = "Normal", numlock: []const u8 = "numlock", +other: []const u8 = "other", password: []const u8 = "password:", restart: []const u8 = "reboot", shell: []const u8 = "shell", @@ -48,3 +49,4 @@ shutdown: []const u8 = "shutdown", sleep: []const u8 = "sleep", wayland: []const u8 = "wayland", xinitrc: []const u8 = "xinitrc", +x11: []const u8 = "x11", diff --git a/src/interop.zig b/src/interop.zig index 64f7b83..a397df0 100644 --- a/src/interop.zig +++ b/src/interop.zig @@ -112,6 +112,7 @@ pub fn timeAsString(allocator: Allocator, format: [:0]const u8, max_length: u64) const timer = time(null); const tm_info = localtime(&timer); const buffer = try allocator.allocSentinel(u8, max_length, 0); + errdefer allocator.free(buffer); if (strftime(buffer, max_length, format, tm_info) < 0) return error.CannotGetFormattedTime; diff --git a/src/main.zig b/src/main.zig index 9d10a58..d54a8bf 100644 --- a/src/main.zig +++ b/src/main.zig @@ -10,6 +10,7 @@ const Matrix = @import("animations/Matrix.zig"); const TerminalBuffer = @import("tui/TerminalBuffer.zig"); const Desktop = @import("tui/components/Desktop.zig"); const Text = @import("tui/components/Text.zig"); +const InfoLine = @import("tui/components/InfoLine.zig"); const Config = @import("config/Config.zig"); const ini = @import("zigini"); const Lang = @import("config/Lang.zig"); @@ -49,7 +50,7 @@ pub fn main() !void { var config: Config = undefined; var lang: Lang = undefined; - var info_line: []const u8 = undefined; + var info_line = InfoLine{}; if (res.args.help != 0) { try clap.help(stderr, clap.Help, ¶ms, .{}); @@ -96,16 +97,16 @@ pub fn main() !void { get_host_name: { const host_name_struct = interop.getHostName(allocator) catch |err| { if (err == error.CannotGetHostName) { - info_line = lang.err_hostname; + try info_line.setText(lang.err_hostname); } else { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); } break :get_host_name; }; got_host_name = true; host_name_buffer = host_name_struct.buffer; - info_line = host_name_struct.slice; + try info_line.setText(host_name_struct.slice); } defer { @@ -127,7 +128,7 @@ pub fn main() !void { termbox.tb_clear(); // we need this to reset it after auth. - const orig_tios = try std.os.tcgetattr(std.os.STDIN_FILENO); + const tb_termios = try std.os.tcgetattr(std.os.STDIN_FILENO); // Initialize terminal buffer const labels_max_length = @max(lang.login.len, lang.password.len); @@ -135,15 +136,15 @@ pub fn main() !void { var buffer = TerminalBuffer.init(config, labels_max_length); // Initialize components - var desktop = try Desktop.init(allocator, &buffer, config.max_desktop_len); + var desktop = try Desktop.init(allocator, &buffer, config.max_desktop_len, lang); defer desktop.deinit(); desktop.addEnvironment(lang.shell, "", .shell) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }; if (config.xinitrc) |xinitrc| { desktop.addEnvironment(lang.xinitrc, xinitrc, .xinitrc) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }; } @@ -188,10 +189,10 @@ pub fn main() !void { switch (active_input) { .session => desktop.handle(null, vi_mode), .login => login.handle(null, vi_mode) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }, .password => password.handle(null, vi_mode) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }, } } @@ -215,7 +216,9 @@ pub fn main() !void { const animate = config.animation != .none; const shutdown_key = try std.fmt.parseInt(u8, config.shutdown_key[1..], 10); + const shutdown_len = try utils.strWidth(lang.shutdown); const restart_key = try std.fmt.parseInt(u8, config.restart_key[1..], 10); + const restart_len = try utils.strWidth(lang.restart); const sleep_key = try std.fmt.parseInt(u8, config.sleep_key[1..], 10); var event: termbox.tb_event = undefined; @@ -229,7 +232,7 @@ pub fn main() !void { // Switch to selected TTY if possible open_console_dev: { const console_dev_z = allocator.dupeZ(u8, config.console_dev) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); break :open_console_dev; }; defer allocator.free(console_dev_z); @@ -238,7 +241,7 @@ pub fn main() !void { defer _ = std.c.close(fd); if (fd < 0) { - info_line = lang.err_console_dev; + try info_line.setText(lang.err_console_dev); break :open_console_dev; } @@ -273,10 +276,10 @@ pub fn main() !void { switch (config.animation) { .none => {}, .doom => doom.realloc() catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }, .matrix => matrix.realloc() catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }, } @@ -290,10 +293,10 @@ pub fn main() !void { switch (active_input) { .session => desktop.handle(null, vi_mode), .login => login.handle(null, vi_mode) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }, .password => password.handle(null, vi_mode) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }, } @@ -311,7 +314,7 @@ pub fn main() !void { const yo = (buffer.height - buffer.box_height) / 2 - bigclock.HEIGHT - 2; const clock_str = interop.timeAsString(allocator, format, format.len + 1) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); break :draw_big_clock; }; defer allocator.free(clock_str); @@ -326,7 +329,7 @@ pub fn main() !void { if (config.clock) |clock| draw_clock: { const clock_buffer = interop.timeAsString(allocator, clock, 32) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); break :draw_clock; }; defer allocator.free(clock_buffer); @@ -350,11 +353,10 @@ pub fn main() !void { buffer.drawLabel(lang.login, label_x, label_y + 4); buffer.drawLabel(lang.password, label_x, label_y + 6); - if (info_line.len > 0) { - 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 (info_line.width > 0) { + if (buffer.box_width > info_line.width) { + const x = buffer.box_x + ((buffer.box_width - info_line.width) / 2); + buffer.drawLabel(info_line.text, x, label_y); } } @@ -366,7 +368,6 @@ pub fn main() !void { buffer.drawLabel(" ", length - 1, 0); buffer.drawLabel(lang.shutdown, length, 0); - const shutdown_len = try utils.strWidth(lang.shutdown); length += shutdown_len + 1; buffer.drawLabel(config.restart_key, length, 0); @@ -374,7 +375,6 @@ pub fn main() !void { buffer.drawLabel(" ", length - 1, 0); buffer.drawLabel(lang.restart, length, 0); - const restart_len = try utils.strWidth(lang.restart); length += restart_len + 1; if (config.sleep_cmd != null) { @@ -394,9 +394,9 @@ pub fn main() !void { draw_lock_state: { const lock_state = interop.getLockState(config.console_dev) catch |err| { if (err == error.CannotOpenConsoleDev) { - info_line = lang.err_console_dev; + try info_line.setText(lang.err_console_dev); } else { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); } break :draw_lock_state; }; @@ -472,11 +472,13 @@ pub fn main() !void { } else if (pressed_key == restart_key) { restart = true; run = false; - } else if (pressed_key == sleep_key and config.sleep_cmd != null) { - const pid = try std.os.fork(); - if (pid == 0) { - std.process.execv(allocator, &[_][]const u8{ "/bin/sh", "-c", config.sleep_cmd.? }) catch std.os.exit(1); - std.os.exit(0); + } else if (pressed_key == sleep_key) { + if (config.sleep_cmd) |sleep_cmd| { + const pid = try std.os.fork(); + if (pid == 0) { + std.process.execv(allocator, &[_][]const u8{ "/bin/sh", "-c", sleep_cmd }) catch std.os.exit(1); + std.os.exit(0); + } } } }, @@ -542,14 +544,14 @@ pub fn main() !void { if (auth_err) |err| { auth_fails += 1; active_input = .password; - info_line = getAuthErrorMsg(err, lang); + try info_line.setText(getAuthErrorMsg(err, lang)); if (config.clear_password or err != error.PamAuthError) password.clear(); } else { password.clear(); - info_line = lang.logout; + try info_line.setText(lang.logout); } - try std.os.tcsetattr(std.os.STDIN_FILENO, .FLUSH, orig_tios); + try std.os.tcsetattr(std.os.STDIN_FILENO, .FLUSH, tb_termios); termbox.tb_clear(); termbox.tb_present(); @@ -592,10 +594,10 @@ pub fn main() !void { switch (active_input) { .session => desktop.handle(&event, vi_mode), .login => login.handle(&event, vi_mode) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }, .password => password.handle(&event, vi_mode) catch { - info_line = lang.err_alloc; + try info_line.setText(lang.err_alloc); }, } update = true; diff --git a/src/tui/components/Desktop.zig b/src/tui/components/Desktop.zig index 259a865..0441917 100644 --- a/src/tui/components/Desktop.zig +++ b/src/tui/components/Desktop.zig @@ -3,6 +3,7 @@ const enums = @import("../../enums.zig"); const interop = @import("../../interop.zig"); const TerminalBuffer = @import("../TerminalBuffer.zig"); const Ini = @import("zigini").Ini; +const Lang = @import("../../config/Lang.zig"); const Allocator = std.mem.Allocator; const EnvironmentList = std.ArrayList(Environment); @@ -37,8 +38,9 @@ current: u64, visible_length: u64, x: u64, y: u64, +lang: Lang, -pub fn init(allocator: Allocator, buffer: *TerminalBuffer, max_length: u64) !Desktop { +pub fn init(allocator: Allocator, buffer: *TerminalBuffer, max_length: u64, lang: Lang) !Desktop { return .{ .allocator = allocator, .buffer = buffer, @@ -47,6 +49,7 @@ pub fn init(allocator: Allocator, buffer: *TerminalBuffer, max_length: u64) !Des .visible_length = 0, .x = 0, .y = 0, + .lang = lang, }; } @@ -71,9 +74,9 @@ pub fn addEnvironment(self: *Desktop, name: []const u8, cmd: []const u8, display .xdg_name = name, // TODO .cmd = cmd, .specifier = switch (display_server) { - .wayland => "wayland", - .x11 => "x11", - else => "", + .wayland => self.lang.wayland, + .x11 => self.lang.x11, + else => self.lang.other, }, .display_server = display_server, }); @@ -88,9 +91,9 @@ pub fn addEnvironmentWithIni(self: *Desktop, entry_ini: Ini(Entry), name: []cons .xdg_name = name, // TODO .cmd = cmd, .specifier = switch (display_server) { - .wayland => "wayland", - .x11 => "x11", - else => "", + .wayland => self.lang.wayland, + .x11 => self.lang.x11, + else => self.lang.other, }, .display_server = display_server, }); @@ -104,14 +107,14 @@ pub fn crawl(self: *Desktop, path: []const u8, display_server: DisplayServer) !v var iterator = iterable_directory.iterate(); while (try iterator.next()) |item| { - if (std.mem.eql(u8, std.fs.path.extension(item.name), ".desktop")) { - const entry_path = try std.fmt.allocPrint(self.allocator, "{s}/{s}", .{ path, item.name }); - defer self.allocator.free(entry_path); - var entry_ini = Ini(Entry).init(self.allocator); - var entry = try entry_ini.readToStruct(entry_path); + if (!std.mem.eql(u8, std.fs.path.extension(item.name), ".desktop")) continue; - try self.addEnvironmentWithIni(entry_ini, entry.Desktop_Entry.Name, entry.Desktop_Entry.Exec, display_server); - } + const entry_path = try std.fmt.allocPrint(self.allocator, "{s}/{s}", .{ path, item.name }); + defer self.allocator.free(entry_path); + var entry_ini = Ini(Entry).init(self.allocator); + var entry = try entry_ini.readToStruct(entry_path); + + try self.addEnvironmentWithIni(entry_ini, entry.Desktop_Entry.Name, entry.Desktop_Entry.Exec, display_server); } } diff --git a/src/tui/components/InfoLine.zig b/src/tui/components/InfoLine.zig new file mode 100644 index 0000000..0a216a9 --- /dev/null +++ b/src/tui/components/InfoLine.zig @@ -0,0 +1,11 @@ +const utils = @import("../utils.zig"); + +const InfoLine = @This(); + +text: []const u8 = "", +width: u8 = 0, + +pub fn setText(self: *InfoLine, text: []const u8) !void { + self.width = if (text.len > 0) try utils.strWidth(text) else 0; + self.text = text; +}