commit 10c33e752bf60594a66bdb3ae861ad8ed8c7f4a1 from: Brett Fisher date: Mon Jul 6 04:45:56 2026 UTC aestel/display.lua, aestel/menu.lua, aestel/navigate.lua, bin/browsefiles.lua, bin/setbackground.lua: Add status bar and unify error handling. - Add display.status_bar to render the (n/total) /path/to/dir footer in reverse video at the bottom of the terminal. - Pass cwd to menu.menu from navigate.browse so the status bar is drawn when navigating directories; pass nil from static menus like launchprogram.lua to suppress it. - Remove the hardcoded "Current Path" from display.write_header; the path is now shown in the status bar. - Remove the start_row parameter from M.browse and update browsefiles.lua and setbackground.lua to match. - Replace the per-render "... more items ..." indicator with the status bar's (n/total) count to avoid a redundant line that consumed a row in small windows. - Unify both error paths in M.browse (go up and select directory) on display.status_line, eliminating io.write calls that were leaking the error to stdout and getting captured by the shell wrapper for cd-on-exit. - Bump the error toast sleep from 1s to 2s so the message is readable. commit - 3e668f2c9f99181b3bd393a330d815fe32d554a3 commit + 10c33e752bf60594a66bdb3ae861ad8ed8c7f4a1 blob - 8537fb186cea61cb2915a7c5760d3ce78803467c blob + 70e5b5ff52af593eb19b5d1efc50a80aa84ddd44 --- aestel/display.lua +++ aestel/display.lua @@ -40,22 +40,12 @@ function M.color_for_type(item_type) return TYPE_COLORS[item_type] or colors.WHITE end --- Write a header block at the top of the terminal: --- line 1: bold title (or omitted if title is empty) --- line 2: "Current Path: " --- line 3: blank separator (only when title is present) --- Returns the number of lines written, for callers to position --- a menu immediately below the header. -function M.write_header(title, cwd) +function M.write_header(title) M.clear_and_position(1, 1) local lines = 0 if title and title ~= "" then io.stderr:write(colors.BOLD .. title .. colors.RESET .. "\n") lines = lines + 1 - end - io.stderr:write("Current Path: " .. (cwd or "") .. "\n") - lines = lines + 1 - if title and title ~= "" then io.stderr:write("\n") lines = lines + 1 end @@ -63,5 +53,10 @@ function M.write_header(title, cwd) return lines end +function M.status_bar(cwd, selected, total) + local message = " (" .. selected .. "/" .. total .. ") " .. cwd + M.status_line(message, colors.REVERSE) +end + return M blob - 1cf47622f08a3b13024c65583164ce73ff48bf2c blob + eec5bedd611d470163ae99559843d23ff39bc980 --- aestel/menu.lua +++ aestel/menu.lua @@ -26,10 +26,11 @@ end -- Display a key-navigated menu and return the selected index -- (1-based, 0 for "up", or nil (quit)) -function M.menu(title, options, start_row, header_lines, empty_message) +function M.menu(title, options, start_row, header_lines, empty_message, cwd) if not options or #options == 0 then if empty_message then start_row = start_row or 1 + -- Note: cwd is ignored for empty directories, empty_message replaces it local terminal_height = input.get_terminal_height() input.enable_raw() @@ -59,7 +60,10 @@ function M.menu(title, options, start_row, header_line local result = nil local terminal_height = input.get_terminal_height() - local max_visible_items = terminal_height - start_row + 1 -- Space from start_row to bottom + local max_visible_items = terminal_height - start_row + 1 + if cwd then + max_visible_items = max_visible_items - 2 -- Reserve one blank line + one status line + end input.enable_raw() @@ -99,13 +103,8 @@ function M.menu(title, options, start_row, header_line visible_count = visible_count + 1 end - -- Overflow indicator if needed - if end_index < #options then - local overflow_row = start_row + visible_count - if overflow_row <= terminal_height then - io.stderr:write(string.format("\27[%d;1H\27[K", overflow_row)) - io.stderr:write("... more items ..." .. "\r\n") - end + if cwd then + display.status_bar(cwd, selected_index, #options) end io.stderr:flush() blob - ab1428b8402fab60b537c59d126ca0120920661b blob + 64eda84279ad104dad24a195f6ffee9ec73ef9cc --- aestel/navigate.lua +++ aestel/navigate.lua @@ -89,25 +89,23 @@ local function build_list(path) return combined end -function M.browse(start_dir, base_dir, start_row, title) +function M.browse(start_dir, base_dir, title) title = title or "" local cwd = normalize_path(start_dir or lfs.currentdir() or home_dir) - local header_lines = title ~= "" and 3 or 1 + local header_lines = display.write_header(title) - display.write_header(title, cwd) - local running = true local selected_file = nil while running do local items = build_list(cwd) if #items == 0 then - local selected_index = menu.menu(title, items, start_row or 4, header_lines, "Empty directory. Press 'h' to go up, 'q' to quit.") + 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, cwd) + display.write_header(title) else display.status_line("Error: " .. (err or "unknown"), colors.REVERSE) os.execute("sleep 1") @@ -116,7 +114,7 @@ function M.browse(start_dir, base_dir, start_row, titl running = false end else - local selected_index = menu.menu(title, items, start_row or 4, header_lines) + local selected_index = menu.menu(title, items, header_lines + 1, header_lines, nil, cwd) if not selected_index then running = false @@ -124,17 +122,20 @@ function M.browse(start_dir, base_dir, start_row, titl local new_cwd, err = change_dir(cwd, "..", base_dir) if new_cwd then cwd = new_cwd - display.write_header(title, cwd) + display.write_header(title) 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 +-- 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 blob - a42cfcdaf11781657dd7fb8b329569cf41b7cf8e blob + 0638b935dd939e0ebe65fd6fe946f9513ca0d797 --- bin/browsefiles.lua +++ bin/browsefiles.lua @@ -69,7 +69,7 @@ local function browse_and_open() local current_dir = start_dir while true do - local selected, final_cwd = navigate.browse(current_dir, home_dir, nil, TITLE) + local selected, final_cwd = navigate.browse(current_dir, home_dir, TITLE) if not selected then display.status_line("... Exiting " .. TITLE, colors.REVERSE) os.execute("sleep 2") blob - e06a0ee7f9d9ec9c6c063058a4a3497adfb3c507 blob + 2675de424efeabf191bb5624c3287b429aeae075 --- bin/setbackground.lua +++ bin/setbackground.lua @@ -27,7 +27,7 @@ local function set_background() -- Main loop: browse, select, set, repeat, or quit while true do - local selected_file, final_cwd = navigate.browse(current_dir, bg_dir, nil, TITLE) + local selected_file, final_cwd = navigate.browse(current_dir, bg_dir, TITLE) if not selected_file then -- Quitting