commit 915d416f97e8de5013529b6896c9e61b2000868b from: Brett Fisher date: Sat Jun 27 23:29:38 2026 UTC bin/launchprogram.lua: Refactor and update launcher script. - Refactor the program launcher to align with the current aestel conventions (display, menu, colors modules) and remove no-longer-used logging machinery. - Remove dead lfs/log() plumbing. - Replace print() output with display.status_line() using colors.REVERSE, matching the pattern in setbackground.lua. Collapse the three "Launching / launched / exiting" status lines into two ("Launched X" / "Exiting ") for parity with setbackground.lua's message rhythm. - Render the title in colors.BOLD + colors.RESET instead of the previous emoji-prefixed literal, matching the BOLD/title style in navigate.refresh_headers() and the rest of aestel's display conventions. - Convert the programs table to a typed schema: each entry is now { command = "...", type = "app" } instead of a bare string. The type field drives magenta coloring via display.color_for_type(), which is the same mechanism navigate.lua uses for directories (cyan) and files (white). This is the first use of type = "app" in the codebase; new types can be added by extending TYPE_COLORS in display.lua. - Add BINDIR constant into build_list(). - Use absolute paths for st -e commands (e.g., "$HOME/.local/bin/setbackground") rather than relying on PATH lookup. The launcher is invoked from interactive contexts where st's PATH may not include ~/.local/bin, causing user-installed scripts to silently fail to launch (exit status 1, no error visible). System binaries do not need this treatment. - Introduce a module-level TITLE constant so the launcher name lives in one place. Both the header and the "Exiting ..." status line read from TITLE, eliminating drift if the launcher is renamed. - Update requires to the renamed aestel.menu module (formerly aestel.ui) and add requires for aestel.colors and aestel.display, which the new status_line and color_for_type calls need. - Drop redundant comments that restated the code. - Add blank lines between logical sections inside build_list() and launch_program() to match the visual rhythm used in aestel/menu.lua and aestel/navigate.lua. commit - d6d52199020adbd3c7e32bf725e62dc7c881f8b8 commit + 915d416f97e8de5013529b6896c9e61b2000868b blob - 30289f9bf9b8598148543868567bbbc29fa87f5d blob + 3bab7435e8d7447387c2b82ce00f0661efb55fe9 --- bin/launchprogram.lua +++ bin/launchprogram.lua @@ -1,36 +1,36 @@ #!/usr/bin/env lua5.4 --- A lua program launcher script +-- A Lua program launcher script --- Enforce Lua 5.4+ (for potential luafilesystem if expanded) +-- Enforce Lua 5.4 if not _VERSION:match("5.4") then io.stderr:write("Error: Lua 5.4 required (got " .. _VERSION .. ").\n") os.exit(1) end -- Dependencies -local ui = require("aestel.ui") +local colors = require("aestel.colors") +local display = require("aestel.display") local input = require("aestel.input") +local menu = require("aestel.menu") --- Functin for error handling --- Checks for lfs which is needed for logging -local ok, lfs = pcall(require, "lfs") -if not ok then - lfs = nil -end +local TITLE = "Program Launcher" --- Function for building a sorted list of programs local function build_list() + + local BINDIR = os.getenv("HOME") .. "/.local/bin" + local programs = { - ["File Browser"] = "st -e browsefiles", - ["Office Suite libreoffice"] = "libreoffice", - ["Set Background"] = "st -e setbackground", - ["Web Browser librewolf"] = "librewolf", - ["Web Browser netsurf"] = "netsurf" + ["File Browser"] = {command = "st -e " .. BINDIR .. "/browsefiles", type = "app" }, + ["Office Suite libreoffice"] = {command = "libreoffice", type = "app" }, + ["Set Background"] = {command = "st -e " .. BINDIR .. "/setbackground", type = "app" }, + ["Web Browser librewolf"] = {command = "librewolf", type = "app" }, + ["Web Browser netsurf"] = {command = "netsurf", type = "app" }, } -local sorted_items = {} - for name, command in pairs(programs) do - table.insert(sorted_items, {name = name, command = command}) + local sorted_items = {} + + for name, entry in pairs(programs) do + table.insert(sorted_items, { name = name, command = entry.command, type = entry.type }) end table.sort(sorted_items, function(a, b) @@ -40,66 +40,37 @@ local sorted_items = {} return sorted_items end --- Function for launcher script log -local function log(message, level) - if not lfs then return end -- No logging if lfs unavailable - - local home_dir = os.getenv("HOME") - if not home_dir then return end - - local log_file = "~/.local/var/log/aestel_launchprogram.log" - local expanded_path = log_file:gsub("^~", home_dir) - - -- Ensure log dir exists - local log_dir = expanded_path:match("^(.*)/[^/]+$") - if log_dir and log_dir ~= "" then - lfs.mkdir(log_dir) - end - - local file = io.open(expanded_path, "a") - if file then - file:write(os.date("%Y-%m-%d %H:%M:%S") .. " [" .. (level or "INFO") .. "] " .. message .. "\n") - file:close() - end -end - --- Function for main interactive loop local function launch_program() + local items = build_list() - log("Script started", "INFO") - -- Clear screen and print title manually (ui.menu handles the list only) - input.clear_and_position(1, 1) - io.write("🚀 Program Launcher\r\n\n") + display.clear_and_position(1, 1) + io.write(colors.BOLD .. TITLE .. colors.RESET .. "\n\n") io.flush() - -- Display menu starting at row 3 (after the title); pass full items - local selected_index = ui.menu(nil, items, 3) + local selected_index = menu.menu(nil, items, 3) if selected_index then local sel = items[selected_index] - log("Launching: " .. sel.name, "INFO") - -- Launch the selected program detached from terminal os.execute("nohup " .. sel.command .. " > /dev/null 2>&1 &") - print("\n" .. "... Launching " .. sel.name) - print("... " .. sel.name .. " launched") - print("... Exiting Program Launcher") + display.status_line("... Launched " .. sel.name, colors.REVERSE) + os.execute("sleep 2") + display.status_line("... Exiting " .. TITLE, colors.REVERSE) + os.execute("sleep 2") else - log("No program selected", "INFO") - print("\n... No program selected for launching") - print("... Exiting Program Launcher") + display.status_line("... No program selected for launching", colors.REVERSE) + os.execute("sleep 2") + display.status_line("... Exiting Program Launcher", colors.REVERSE) + os.execute("sleep 2") end - print() - os.execute("sleep 2") + + display.clear_screen() end --- Run the script with error handling local success, err = pcall(launch_program) if not success then input.disable_raw() - log("Fatal error: " .. tostring(err), "FATAL") - print("\nFatal error: " .. tostring(err)) + print("\nFatal error: " .. tostring(err) .. "\n") os.exit(1) end -input.disable_raw() -- Restore terminal on normal exit