From 86ea38f460e654bab58d363dd9cc8789db800fc9 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Sun, 16 Mar 2025 00:24:56 +0100 Subject: [PATCH] Split session crawling from TUI component Signed-off-by: AnErrupTion --- src/Environment.zig | 21 +++++++ src/auth.zig | 6 +- src/main.zig | 93 +++++++++++++++++++++++++-- src/tui/components/Session.zig | 111 ++------------------------------- 4 files changed, 117 insertions(+), 114 deletions(-) create mode 100644 src/Environment.zig diff --git a/src/Environment.zig b/src/Environment.zig new file mode 100644 index 0000000..b21d451 --- /dev/null +++ b/src/Environment.zig @@ -0,0 +1,21 @@ +const enums = @import("enums.zig"); +const ini = @import("zigini"); + +const DisplayServer = enums.DisplayServer; +const Ini = ini.Ini; + +pub const DesktopEntry = struct { + Exec: []const u8 = "", + Name: [:0]const u8 = "", + DesktopNames: ?[:0]u8 = null, +}; + +pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} }; + +entry_ini: ?Ini(Entry) = null, +name: [:0]const u8 = "", +xdg_session_desktop: ?[:0]const u8 = null, +xdg_desktop_names: ?[:0]const u8 = null, +cmd: []const u8 = "", +specifier: []const u8 = "", +display_server: DisplayServer = .wayland, diff --git a/src/auth.zig b/src/auth.zig index 2d2bbf8..35eee5e 100644 --- a/src/auth.zig +++ b/src/auth.zig @@ -2,8 +2,8 @@ const std = @import("std"); const build_options = @import("build_options"); const builtin = @import("builtin"); const enums = @import("enums.zig"); +const Environment = @import("Environment.zig"); const interop = @import("interop.zig"); -const Session = @import("tui/components/Session.zig"); const SharedError = @import("SharedError.zig"); const Allocator = std.mem.Allocator; @@ -33,7 +33,7 @@ pub fn sessionSignalHandler(i: c_int) callconv(.C) void { if (child_pid > 0) _ = std.c.kill(child_pid, i); } -pub fn authenticate(options: AuthOptions, current_environment: Session.Environment, login: [:0]const u8, password: [:0]const u8) !void { +pub fn authenticate(options: AuthOptions, current_environment: Environment, login: [:0]const u8, password: [:0]const u8) !void { var tty_buffer: [3]u8 = undefined; const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{options.tty}); @@ -134,7 +134,7 @@ fn startSession( options: AuthOptions, pwd: *interop.pwd.passwd, handle: ?*interop.pam.pam_handle, - current_environment: Session.Environment, + current_environment: Environment, ) !void { if (builtin.os.tag == .freebsd) { // FreeBSD has initgroups() in unistd diff --git a/src/main.zig b/src/main.zig index 2868b42..e9de028 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5,6 +5,8 @@ const clap = @import("clap"); const ini = @import("zigini"); const auth = @import("auth.zig"); const bigclock = @import("bigclock.zig"); +const enums = @import("enums.zig"); +const Environment = @import("Environment.zig"); const interop = @import("interop.zig"); const Doom = @import("animations/Doom.zig"); const Matrix = @import("animations/Matrix.zig"); @@ -21,6 +23,8 @@ const SharedError = @import("SharedError.zig"); const utils = @import("tui/utils.zig"); const Ini = ini.Ini; +const DisplayServer = enums.DisplayServer; +const Entry = Environment.Entry; const termbox = interop.termbox; const unistd = interop.unistd; const temporary_allocator = std.heap.page_allocator; @@ -254,16 +258,16 @@ pub fn main() !void { try info_line.addMessage(lang.err_numlock, config.error_bg, config.error_fg); }; - var session = Session.init(allocator, &buffer, lang); + var session = Session.init(allocator, &buffer); defer session.deinit(); - session.addEnvironment(.{ .Name = lang.shell }, null, .shell) catch { + addOtherEnvironment(&session, lang, .shell, null) catch { try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg); }; if (build_options.enable_x11_support) { - if (config.xinitrc) |xinitrc| { - session.addEnvironment(.{ .Name = lang.xinitrc, .Exec = xinitrc }, null, .xinitrc) catch { + if (config.xinitrc) |xinitrc_cmd| { + addOtherEnvironment(&session, lang, .xinitrc, xinitrc_cmd) catch { try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg); }; } @@ -283,8 +287,8 @@ pub fn main() !void { try info_line.addMessage(hostname, config.bg, config.fg); } - try session.crawl(config.waylandsessions, .wayland); - if (build_options.enable_x11_support) try session.crawl(config.xsessions, .x11); + try crawl(&session, lang, config.waylandsessions, .wayland); + if (build_options.enable_x11_support) try crawl(&session, lang, config.xsessions, .x11); var login = Text.init(allocator, &buffer, false, null); defer login.deinit(); @@ -844,6 +848,83 @@ pub fn main() !void { } } +fn addOtherEnvironment(session: *Session, lang: Lang, display_server: DisplayServer, exec: ?[]const u8) !void { + const name = switch (display_server) { + .shell => lang.shell, + .xinitrc => lang.xinitrc, + else => unreachable, + }; + + try session.addEnvironment(.{ + .entry_ini = null, + .name = name, + .xdg_session_desktop = null, + .xdg_desktop_names = null, + .cmd = exec orelse "", + .specifier = switch (display_server) { + .wayland => lang.wayland, + .x11 => lang.x11, + else => lang.other, + }, + .display_server = display_server, + }); +} + +fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: DisplayServer) !void { + var iterable_directory = std.fs.openDirAbsolute(path, .{ .iterate = true }) catch return; + defer iterable_directory.close(); + + var iterator = iterable_directory.iterate(); + while (try iterator.next()) |item| { + if (!std.mem.eql(u8, std.fs.path.extension(item.name), ".desktop")) continue; + + const entry_path = try std.fmt.allocPrint(session.label.allocator, "{s}/{s}", .{ path, item.name }); + defer session.label.allocator.free(entry_path); + var entry_ini = Ini(Entry).init(session.label.allocator); + _ = try entry_ini.readFileToStruct(entry_path, .{ + .fieldHandler = null, + .comment_characters = "#", + }); + errdefer entry_ini.deinit(); + + var xdg_session_desktop: []const u8 = undefined; + const maybe_desktop_names = entry_ini.data.@"Desktop Entry".DesktopNames; + if (maybe_desktop_names) |desktop_names| { + xdg_session_desktop = std.mem.sliceTo(desktop_names, ';'); + } else { + // if DesktopNames is empty, we'll take the name of the session file + xdg_session_desktop = std.fs.path.stem(item.name); + } + + // Prepare the XDG_CURRENT_DESKTOP environment variable here + const entry = entry_ini.data.@"Desktop Entry"; + var xdg_desktop_names: ?[:0]const u8 = null; + if (entry.DesktopNames) |desktop_names| { + for (desktop_names) |*c| { + if (c.* == ';') c.* = ':'; + } + xdg_desktop_names = desktop_names; + } + + const session_desktop = try session.label.allocator.dupeZ(u8, xdg_session_desktop); + errdefer session.label.allocator.free(session_desktop); + + try session.addEnvironment(.{ + .entry_ini = entry_ini, + .name = entry.Name, + .xdg_session_desktop = session_desktop, + .xdg_desktop_names = xdg_desktop_names, + .cmd = entry.Exec, + .specifier = switch (display_server) { + .wayland => lang.wayland, + .x11 => lang.x11, + else => lang.other, + }, + .display_server = display_server, + }); + } +} + fn adjustBrightness(allocator: std.mem.Allocator, cmd: []const u8) !void { var brightness = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", cmd }, allocator); brightness.stdout_behavior = .Ignore; diff --git a/src/tui/components/Session.zig b/src/tui/components/Session.zig index d513949..4135283 100644 --- a/src/tui/components/Session.zig +++ b/src/tui/components/Session.zig @@ -1,43 +1,22 @@ const std = @import("std"); const TerminalBuffer = @import("../TerminalBuffer.zig"); const enums = @import("../../enums.zig"); +const ini = @import("zigini"); +const Environment = @import("../../Environment.zig"); const generic = @import("generic.zig"); -const Ini = @import("zigini").Ini; -const Lang = @import("../../config/Lang.zig"); const Allocator = std.mem.Allocator; - const DisplayServer = enums.DisplayServer; - +const Ini = ini.Ini; const EnvironmentLabel = generic.CyclableLabel(Environment); const Session = @This(); -pub const Environment = struct { - entry_ini: ?Ini(Entry) = null, - name: [:0]const u8 = "", - xdg_session_desktop: ?[:0]const u8 = null, - xdg_desktop_names: ?[:0]const u8 = null, - cmd: []const u8 = "", - specifier: []const u8 = "", - display_server: DisplayServer = .wayland, -}; - -const DesktopEntry = struct { - Exec: []const u8 = "", - Name: [:0]const u8 = "", - DesktopNames: ?[:0]u8 = null, -}; - -pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} }; - label: EnvironmentLabel, -lang: Lang, -pub fn init(allocator: Allocator, buffer: *TerminalBuffer, lang: Lang) Session { +pub fn init(allocator: Allocator, buffer: *TerminalBuffer) Session { return .{ .label = EnvironmentLabel.init(allocator, buffer, drawItem), - .lang = lang, }; } @@ -50,86 +29,8 @@ pub fn deinit(self: Session) void { self.label.deinit(); } -pub fn addEnvironment(self: *Session, entry: DesktopEntry, xdg_session_desktop: ?[:0]const u8, display_server: DisplayServer) !void { - var xdg_desktop_names: ?[:0]const u8 = null; - if (entry.DesktopNames) |desktop_names| { - for (desktop_names) |*c| { - if (c.* == ';') c.* = ':'; - } - xdg_desktop_names = desktop_names; - } - - try self.label.addItem(.{ - .entry_ini = null, - .name = entry.Name, - .xdg_session_desktop = xdg_session_desktop, - .xdg_desktop_names = xdg_desktop_names, - .cmd = entry.Exec, - .specifier = switch (display_server) { - .wayland => self.lang.wayland, - .x11 => self.lang.x11, - else => self.lang.other, - }, - .display_server = display_server, - }); -} - -pub fn addEnvironmentWithIni(self: *Session, entry_ini: Ini(Entry), xdg_session_desktop: ?[:0]const u8, display_server: DisplayServer) !void { - const entry = entry_ini.data.@"Desktop Entry"; - var xdg_desktop_names: ?[:0]const u8 = null; - if (entry.DesktopNames) |desktop_names| { - for (desktop_names) |*c| { - if (c.* == ';') c.* = ':'; - } - xdg_desktop_names = desktop_names; - } - - try self.label.addItem(.{ - .entry_ini = entry_ini, - .name = entry.Name, - .xdg_session_desktop = xdg_session_desktop, - .xdg_desktop_names = xdg_desktop_names, - .cmd = entry.Exec, - .specifier = switch (display_server) { - .wayland => self.lang.wayland, - .x11 => self.lang.x11, - else => self.lang.other, - }, - .display_server = display_server, - }); -} - -pub fn crawl(self: *Session, path: []const u8, display_server: DisplayServer) !void { - var iterable_directory = std.fs.openDirAbsolute(path, .{ .iterate = true }) catch return; - defer iterable_directory.close(); - - var iterator = iterable_directory.iterate(); - while (try iterator.next()) |item| { - if (!std.mem.eql(u8, std.fs.path.extension(item.name), ".desktop")) continue; - - const entry_path = try std.fmt.allocPrint(self.label.allocator, "{s}/{s}", .{ path, item.name }); - defer self.label.allocator.free(entry_path); - var entry_ini = Ini(Entry).init(self.label.allocator); - _ = try entry_ini.readFileToStruct(entry_path, .{ - .fieldHandler = null, - .comment_characters = "#", - }); - errdefer entry_ini.deinit(); - - var xdg_session_desktop: []const u8 = undefined; - const maybe_desktop_names = entry_ini.data.@"Desktop Entry".DesktopNames; - if (maybe_desktop_names) |desktop_names| { - xdg_session_desktop = std.mem.sliceTo(desktop_names, ';'); - } else { - // if DesktopNames is empty, we'll take the name of the session file - xdg_session_desktop = std.fs.path.stem(item.name); - } - - const session_desktop = try self.label.allocator.dupeZ(u8, xdg_session_desktop); - errdefer self.label.allocator.free(session_desktop); - - try self.addEnvironmentWithIni(entry_ini, session_desktop, display_server); - } +pub fn addEnvironment(self: *Session, environment: Environment) !void { + try self.label.addItem(environment); } fn drawItem(label: *EnvironmentLabel, environment: Environment, x: usize, y: usize) bool {