Commit Diff


commit - 96122ce9a1fce816da654d60218cce92efc00123
commit + 5840ee4c5f0f9f206cd72b5e535832c630919f5f
blob - ab41080edff33d734e5cc7b84b712ff5515c5da8
blob + 93a0d15e976cc8f5d930bd06d5dc8d9620666a9f
--- aestel/menu.lua
+++ aestel/menu.lua
@@ -1,5 +1,5 @@
--- aestel/ui.lua
--- Generic key-driven menu rendering and navigation
+-- aestel/menu.lua
+-- A module for rendering and navigating menus
 
 local M = {}
 
@@ -7,70 +7,62 @@ local colors = require("aestel.colors")
 local display = require("aestel.display")
 local input = require("aestel.input")
 
--- Utility to read full key (handles arrow escape sequences)
 local function read_key_full()
 	local key = input.read_key()
 	if key == "\27" then  -- ESC prefix for arrows
 		local second = input.read_key()
 		if second == "[" then
 			local third = input.read_key()
-			if third == "A" then return "up"	-- Arrow up
-			elseif third == "B" then return "down"  -- Arrow down
-			elseif third == "C" then return "right"  -- NEW: Arrow right (enter/down dir)
-			elseif third == "D" then return "left"   -- NEW: Arrow left (up dir)
+			if third == "A" then return "up"
+			elseif third == "B" then return "down"
+			elseif third == "C" then return "right"
+			elseif third == "D" then return "left"
 			end
 		end
 	end
-	return key  -- Single char (j, k, q, Enter, etc.)
+	return key
 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, 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()
-
-			-- Write the empty message on the last terminal line
 			local terminal_width = input.get_terminal_width()
 			local padding = string.rep(" ", math.max(0, terminal_width - #empty_message))
 			io.stderr:write(string.format("\27[%d;1H\27[K", terminal_height))
 			io.stderr:write(colors.REVERSE .. empty_message .. padding .. colors.RESET)
 			io.stderr:flush()
-
 			local key = read_key_full()
 			input.disable_raw()
 
 			if key == "h" or key == "left" then
-				return 0  -- Signal "go up"
+				return 0
 			end
-			return nil  -- Quit
+			return nil
 		end
 		return nil
 	end
 
 	start_row = start_row or 1
-	header_lines = header_lines or 0  -- Extra lines above menu (e.g., for path display)
+	header_lines = header_lines or 0
 	local selected_index = 1
 	local scroll_offset = 1
 	local running = true
 	local result = nil
-
 	local terminal_height = input.get_terminal_height()
 	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
+		max_visible_items = max_visible_items - 2
 	end
 
 	input.enable_raw()
 
 	while running do
-		-- Clear menu area ONLY from start_row down (preserve headers)
 		io.stderr:write(string.format("\27[%d;1H", start_row))
-		io.stderr:write("\27[J")  -- Erase down from start_row
+		io.stderr:write("\27[J")
 		io.stderr:flush()
 
 		-- Calculate visible range (ensure selected is always visible)
@@ -89,20 +81,17 @@ function M.menu(title, options, start_row, header_line
 			local option = options[i]
 			local is_selected = (i == selected_index)
 			local display_name = option.name or tostring(option)
-
-			local prefix = (is_selected and "\27[1m > " or "   ")  -- Bold > for selected
-
+			-- Display position
+			local prefix = (is_selected and "\27[1m > " or "   ")
 			-- Determine color by type
 			local option_type = (type(option) == "table") and option.type or nil
 			local color = display.color_for_type(option_type)
-
 			-- Position and write to specific row
 			local row = start_row + visible_count
-			io.stderr:write(string.format("\27[%d;1H\27[K", row))  -- Position and clear line
+			io.stderr:write(string.format("\27[%d;1H\27[K", row))
 			io.stderr:write(prefix .. color .. display_name .. colors.RESET .. "\r\n")
 			visible_count = visible_count + 1
 		end
-
 		if cwd then
 			display.status_bar(cwd, selected_index, #options)
 		end
@@ -119,22 +108,23 @@ function M.menu(title, options, start_row, header_line
 			if selected_index < #options then
 				selected_index = selected_index + 1
 			end
-		elseif key == "h" or key == "left" then  -- CHANGED: Added "left" for up dir
-			result = 0  -- Signal "go up"
+		elseif key == "h" or key == "left" then
+			result = 0
 			running = false
-		elseif key == "." then  -- NEW: Toggle hidden
+		elseif key == "." then -- Hidden files toggle
 			result = -1 
 			running = false
-		elseif key == "l" or key == "right" or key == "\r" or key == "\n" then  -- CHANGED: Added "right" for down dir/select
-			result = selected_index  -- Select current (dir or file)
+		elseif key == "l" or key == "right" or key == "\r" or key == "\n" then
+			result = selected_index
 			running = false
 		elseif key == "q" then
-			result = nil  -- Quit
+			result = nil
 			running = false
 		end
 	end
 
 	input.disable_raw()
+
 	return result
 end