commit 076f13abe43fdd57cd7d2e8b1920ca6caead8e2b from: Brett Fisher date: Thu Jul 9 22:33:30 2026 UTC aestel/browse.lua, aestel/navigate.lua: Rename module for clarity with purpose of module. - Refactor module - Update heading comment for consistency across project modules. - Remove redundant narrative comments and unused commented out code commit - 60e1b851d9eaef063c50b64c27f1c1c0ad4efcde commit + 076f13abe43fdd57cd7d2e8b1920ca6caead8e2b blob - /dev/null blob + 3e81c40527435d22cd0680eb42fda45c862eab9b (mode 644) --- /dev/null +++ aestel/browse.lua @@ -0,0 +1,165 @@ +-- aestel/browse.lua +-- A module for browsing directory structure and content. + +local M = {} + +-- Dependencies +local lfs = require("lfs") +local colors = require("aestel.colors") +local display = require("aestel.display") +local input = require("aestel.input") +local menu = require("aestel.menu") + +local home_dir = os.getenv("HOME") + +local function normalize_path(p) + p = p:gsub("//+", "/") + if p == "/." or p == "./" then p = "/" end + return p:gsub("/+$", "") +end + +local function join_path(base, name) + if base == "/" then + return normalize_path("/" .. name) + end + return normalize_path(base .. "/" .. name) +end + +local function change_dir(cur, target, base_dir) + local new_path + if target == ".." then + local cur_no_trail = normalize_path(cur):gsub("/+$", "") + if cur_no_trail == "/" then + return nil, "Cannot go above root directory (/)" + end + new_path = cur_no_trail:match("(.+)/[^/]+$") or "/" + else + new_path = join_path(cur, target) + end + + new_path = normalize_path(new_path) + + if base_dir then + local normalized_base = normalize_path(base_dir) .. "/" + local normalized_new = new_path .. "/" + if not normalized_new:find(normalized_base, 1, true) then + return nil, "Access denied -- cannot navigate above base directory." + end + end + + if new_path ~= "/" then + local attr = lfs.attributes(new_path) + if not attr then + return nil, "Path does not exist: " .. (new_path or "unknown") + end + if attr.mode ~= "directory" then + return nil, new_path .. " is not a directory." + end + end + return new_path +end + +local function build_list(path, show_hidden) + local dirs, files = {}, {} + for item in lfs.dir(path) do + if item ~= "." and item ~= ".." then + if not show_hidden and item:sub(1,1) == "." then + -- skip hidden + else + local full = join_path(path, item) + local attr = lfs.attributes(full) + if attr then + if attr.mode == "directory" then + table.insert(dirs, item) + elseif attr.mode == "file" then + table.insert(files, item) + end + end + end + end + end + table.sort(dirs) + table.sort(files) + + local combined = {} + for _, d in ipairs(dirs) do + table.insert(combined, {name = d, type = "dir"}) + end + for _, f in ipairs(files) do + table.insert(combined, {name = f, type = "file"}) + end + return combined +end + +function M.browse(start_dir, base_dir, title) + title = title or "" + local cwd = normalize_path(start_dir or lfs.currentdir() or home_dir) + local show_hidden = false + local header_lines = display.write_header(title) + + local running = true + local selected_file = nil + + while running do + local items = build_list(cwd, show_hidden) + if #items == 0 then + local selected_index = menu.menu(title, items, header_lines + 1, header_lines, "Empty directory. Press 'h' to go up, 'q' to quit.") + if selected_index == 0 then + local new_cwd, err = change_dir(cwd, "..", base_dir) + if new_cwd then + cwd = new_cwd + display.write_header(title) + else + display.status_line("Error: " .. (err or "unknown"), colors.REVERSE) + os.execute("sleep 1") + end + else + running = false + end + else + local selected_index = menu.menu(title, items, header_lines + 1, header_lines, nil, cwd) + + if not selected_index then + running = false + elseif selected_index == -1 then + show_hidden = not show_hidden + elseif selected_index == 0 then + local new_cwd, err = change_dir(cwd, "..", base_dir) + if new_cwd then + cwd = new_cwd + display.write_header(title) + else + display.status_line("Error: " .. (err or "unknown"), colors.REVERSE) + os.execute("sleep 2") + end + + else + local sel = items[selected_index] + if sel.type == "dir" then + local new_cwd, err = change_dir(cwd, sel.name, base_dir) + if new_cwd then + cwd = new_cwd + display.write_header(title, cwd) + else + display.write_header(title, cwd) + local height = input.get_terminal_height() + io.write(string.format("\27[%d;1H\27[K", height)) + io.write("Error: " .. (err or "unknown") .. "\n") + io.flush() + os.execute("sleep 1") + io.write(string.format("\27[%d;1H\27[K", height)) + io.flush() + end + else + selected_file = join_path(cwd, sel.name) + running = false + end + end + end + end + + return selected_file, cwd +end + +return M + blob - 1ae918510c51a162be90f8426c383b4913c331ef (mode 644) blob + /dev/null --- aestel/navigate.lua +++ /dev/null @@ -1,175 +0,0 @@ --- aestel/navigate.lua --- A Lua module for navigating directories - -local M = {} - --- Dependencies -local lfs = require("lfs") -local colors = require("aestel.colors") -local display = require("aestel.display") -local input = require("aestel.input") -local menu = require("aestel.menu") - -local home_dir = os.getenv("HOME") - --- Path utilities (unchanged) -local function normalize_path(p) - p = p:gsub("//+", "/") - if p == "/." or p == "./" then p = "/" end - return p:gsub("/+$", "") -end - -local function join_path(base, name) - if base == "/" then - return normalize_path("/" .. name) - end - return normalize_path(base .. "/" .. name) -end - -local function change_dir(cur, target, base_dir) - local new_path - if target == ".." then - local cur_no_trail = normalize_path(cur):gsub("/+$", "") - if cur_no_trail == "/" then - return nil, "Cannot go above root directory (/)" - end - new_path = cur_no_trail:match("(.+)/[^/]+$") or "/" - else - new_path = join_path(cur, target) - end - - new_path = normalize_path(new_path) - - if base_dir then - local normalized_base = normalize_path(base_dir) .. "/" - local normalized_new = new_path .. "/" - if not normalized_new:find(normalized_base, 1, true) then - return nil, "Access denied -- cannot navigate above base directory." - end - end - - -- Attr check: Skip for "/", assume exists - if new_path ~= "/" then - local attr = lfs.attributes(new_path) - if not attr then - return nil, "Path does not exist: " .. (new_path or "unknown") - end - if attr.mode ~= "directory" then - return nil, new_path .. " is not a directory." - end - end - return new_path -end - -local function build_list(path, show_hidden) - local dirs, files = {}, {} - for item in lfs.dir(path) do - if item ~= "." and item ~= ".." then - if not show_hidden and item:sub(1,1) == "." then - -- skip hidden - else - local full = join_path(path, item) - local attr = lfs.attributes(full) - if attr then - if attr.mode == "directory" then - table.insert(dirs, item) - elseif attr.mode == "file" then - table.insert(files, item) - end - end - end - end - end - table.sort(dirs) - table.sort(files) - - local combined = {} - for _, d in ipairs(dirs) do - table.insert(combined, {name = d, type = "dir"}) - end - for _, f in ipairs(files) do - table.insert(combined, {name = f, type = "file"}) - end - return combined -end - -function M.browse(start_dir, base_dir, title) - title = title or "" - local cwd = normalize_path(start_dir or lfs.currentdir() or home_dir) - local show_hidden = false - local header_lines = display.write_header(title) - - local running = true - local selected_file = nil - - while running do - local items = build_list(cwd, show_hidden) - if #items == 0 then - local selected_index = menu.menu(title, items, header_lines + 1, header_lines, "Empty directory. Press 'h' to go up, 'q' to quit.") - if selected_index == 0 then - local new_cwd, err = change_dir(cwd, "..", base_dir) - if new_cwd then - cwd = new_cwd - display.write_header(title) - else - display.status_line("Error: " .. (err or "unknown"), colors.REVERSE) - os.execute("sleep 1") - end - else - running = false - end - else - local selected_index = menu.menu(title, items, header_lines + 1, header_lines, nil, cwd) - - if not selected_index then - running = false - elseif selected_index == -1 then - show_hidden = not show_hidden - elseif selected_index == 0 then - local new_cwd, err = change_dir(cwd, "..", base_dir) - if new_cwd then - cwd = new_cwd - display.write_header(title) - else --- display.write_header(title) --- local height = input.get_terminal_height() --- io.write(string.format("\27[%d;1H\27[K", height)) --- io.write("Error: " .. (err or "unknown") .. "\n") --- io.flush() --- os.execute("sleep 1") --- io.write(string.format("\27[%d;1H\27[K", height)) --- io.flush() - display.status_line("Error: " .. (err or "unknown"), colors.REVERSE) - os.execute("sleep 2") - end - - else - local sel = items[selected_index] - if sel.type == "dir" then - local new_cwd, err = change_dir(cwd, sel.name, base_dir) - if new_cwd then - cwd = new_cwd - display.write_header(title, cwd) - else - display.write_header(title, cwd) - local height = input.get_terminal_height() - io.write(string.format("\27[%d;1H\27[K", height)) - io.write("Error: " .. (err or "unknown") .. "\n") - io.flush() - os.execute("sleep 1") - io.write(string.format("\27[%d;1H\27[K", height)) - io.flush() - end - else - selected_file = join_path(cwd, sel.name) - running = false - end - end - end - end - - return selected_file, cwd -end - -return M -