Advertisement
Rukerisu

OS - Menu

Jun 8th, 2025 (edited)
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.53 KB | None | 0 0
  1. -- Neobox OS Alpha Menu
  2. -- Simple operating system menu with navigation and file manager
  3.  
  4. -- Menu configuration
  5. local menuItems = {
  6.     {name = "Calculator", description = "Simple calculator", type = "calculator"},
  7.     {name = "Programs", description = "Program List", program = "programs"},
  8.     {name = "File Manager", description = "Browse Files", type = "filemanager"},
  9.     {name = "Shell", description = "Command Line", type = "shell"},
  10.     {name = "Reboot", description = "Restart", type = "reboot"},
  11.     {name = "Shutdown", description = "Power Off", type = "shutdown"}
  12. }
  13.  
  14. -- State variables
  15. local selectedIndex = 1
  16. local running = true
  17.  
  18. -- Display functions
  19. local function clearScreen()
  20.     term.clear()
  21.     term.setCursorPos(1, 1)
  22. end
  23.  
  24. local function drawHeader()
  25.     local w, h = term.getSize()
  26.    
  27.     -- Header
  28.     term.setTextColor(colors.blue)
  29.     local title = "| Neobox OS Alpha |"
  30.     local titleX = math.floor((w - #title) / 2) + 1
  31.     term.setCursorPos(titleX, 2)
  32.     term.write(title)
  33.    
  34.     -- Subtitle
  35.     term.setTextColor(colors.lightGray)
  36.     local subtitle = "Select a program to run"
  37.     local subtitleX = math.floor((w - #subtitle) / 2) + 1
  38.     term.setCursorPos(subtitleX, 3)
  39.     term.write(subtitle)
  40.    
  41.     -- Separator line
  42.     term.setCursorPos(1, 5)
  43.     term.setTextColor(colors.gray)
  44.     term.write(string.rep("-", w))
  45. end
  46.  
  47. local function drawMenuItem(index, item, isSelected)
  48.     local w, h = term.getSize()
  49.     local y = 6 + index
  50.    
  51.     if y > h - 2 then
  52.         return
  53.     end
  54.    
  55.     term.setCursorPos(1, y)
  56.    
  57.     if isSelected then
  58.         term.setTextColor(colors.black)
  59.         term.setBackgroundColor(colors.white)
  60.         term.write(" > " .. item.name)
  61.        
  62.         -- Fill spaces
  63.         local spaces = w - #item.name - 3 - #item.description
  64.         if spaces > 0 then
  65.             term.write(string.rep(" ", spaces))
  66.         end
  67.         term.write(item.description .. " ")
  68.     else
  69.         term.setTextColor(colors.white)
  70.         term.setBackgroundColor(colors.black)
  71.         term.write("   " .. item.name)
  72.        
  73.         -- Description on the right
  74.         local spaces = w - #item.name - 3 - #item.description
  75.         if spaces > 0 then
  76.             term.write(string.rep(" ", spaces))
  77.             term.setTextColor(colors.lightGray)
  78.             term.write(item.description)
  79.         end
  80.     end
  81.    
  82.     -- Reset colors
  83.     term.setTextColor(colors.white)
  84.     term.setBackgroundColor(colors.black)
  85. end
  86.  
  87. local function drawFooter()
  88.     local w, h = term.getSize()
  89.    
  90.     term.setCursorPos(1, h - 1)
  91.     term.setTextColor(colors.gray)
  92.     term.write(string.rep("-", w))
  93.    
  94.     term.setCursorPos(2, h)
  95.     term.setTextColor(colors.lightGray)
  96.     term.write("Arrow Keys: navigate | Enter: select | Q: back")
  97. end
  98.  
  99. local function drawMenu()
  100.     clearScreen()
  101.     drawHeader()
  102.    
  103.     for i, item in ipairs(menuItems) do
  104.         drawMenuItem(i, item, i == selectedIndex)
  105.     end
  106.    
  107.     drawFooter()
  108. end
  109.  
  110. -- File Manager functionality
  111. local function showFileManager()
  112.     local currentPath = ""
  113.     local files = {}
  114.     local selectedFile = 1
  115.     local fileManagerRunning = true
  116.     local scrollOffset = 0
  117.     local maxDisplayFiles = 15
  118.    
  119.     local function loadFiles(path)
  120.         files = {}
  121.         local fullPath = path == "" and "/" or path
  122.        
  123.         -- Add parent directory option if not in root
  124.         if path ~= "" then
  125.             table.insert(files, {name = "..", type = "directory", path = fs.getDir(path)})
  126.         end
  127.        
  128.         -- Get all files and directories
  129.         if fs.exists(fullPath) then
  130.             local items = fs.list(fullPath)
  131.             for _, item in ipairs(items) do
  132.                 local itemPath = fs.combine(fullPath, item)
  133.                 local fileType = fs.isDir(itemPath) and "directory" or "file"
  134.                 table.insert(files, {name = item, type = fileType, path = itemPath})
  135.             end
  136.         end
  137.        
  138.         selectedFile = 1
  139.         scrollOffset = 0
  140.     end
  141.    
  142.     local function drawFileManager()
  143.         clearScreen()
  144.         local w, h = term.getSize()
  145.        
  146.         -- Header
  147.         term.setTextColor(colors.blue)
  148.         local title = "| File Manager |"
  149.         local titleX = math.floor((w - #title) / 2) + 1
  150.         term.setCursorPos(titleX, 2)
  151.         term.write(title)
  152.        
  153.         -- Current path
  154.         term.setTextColor(colors.lightGray)
  155.         local pathText = "Path: /" .. currentPath
  156.         term.setCursorPos(2, 4)
  157.         term.write(pathText)
  158.        
  159.         -- Separator
  160.         term.setCursorPos(1, 5)
  161.         term.setTextColor(colors.gray)
  162.         term.write(string.rep("-", w))
  163.        
  164.         -- File list with scrolling
  165.         local displayStart = scrollOffset + 1
  166.         local displayEnd = math.min(#files, scrollOffset + maxDisplayFiles)
  167.        
  168.         for i = displayStart, displayEnd do
  169.             local file = files[i]
  170.             local y = 6 + (i - displayStart)
  171.            
  172.             term.setCursorPos(1, y)
  173.            
  174.             if i == selectedFile then
  175.                 term.setTextColor(colors.black)
  176.                 term.setBackgroundColor(colors.white)
  177.                 term.write(" > ")
  178.             else
  179.                 term.setTextColor(colors.white)
  180.                 term.setBackgroundColor(colors.black)
  181.                 term.write("   ")
  182.             end
  183.            
  184.             -- File icon and name
  185.             if file.type == "directory" then
  186.                 term.setTextColor(i == selectedFile and colors.black or colors.yellow)
  187.                 term.write("[DIR] ")
  188.             else
  189.                 term.setTextColor(i == selectedFile and colors.black or colors.white)
  190.                 term.write("[FILE] ")
  191.             end
  192.            
  193.             -- Truncate long filenames
  194.             local displayName = file.name
  195.             if #displayName > w - 10 then
  196.                 displayName = string.sub(displayName, 1, w - 13) .. "..."
  197.             end
  198.             term.write(displayName)
  199.            
  200.             -- Reset colors
  201.             term.setTextColor(colors.white)
  202.             term.setBackgroundColor(colors.black)
  203.         end
  204.        
  205.         -- Scroll indicator
  206.         if #files > maxDisplayFiles then
  207.             term.setCursorPos(w - 8, h - 2)
  208.             term.setTextColor(colors.lightGray)
  209.             term.write(string.format("%d/%d", selectedFile, #files))
  210.         end
  211.        
  212.         -- Footer
  213.         term.setCursorPos(1, h - 1)
  214.         term.setTextColor(colors.gray)
  215.         term.write(string.rep("-", w))
  216.        
  217.         term.setCursorPos(2, h)
  218.         term.setTextColor(colors.lightGray)
  219.         term.write("Arrow Keys: navigate | Enter: open/run | Q: back")
  220.     end
  221.    
  222.     local function executeFile(filePath)
  223.         clearScreen()
  224.         term.setTextColor(colors.yellow)
  225.         print("Running: " .. filePath)
  226.         print()
  227.        
  228.         local success, error = pcall(function()
  229.             if string.find(filePath, "%.lua$") then
  230.                 dofile(filePath)
  231.             else
  232.                 shell.run(filePath)
  233.             end
  234.         end)
  235.        
  236.         if not success then
  237.             term.setTextColor(colors.red)
  238.             print("Error: " .. tostring(error))
  239.         end
  240.        
  241.         term.setTextColor(colors.yellow)
  242.         print("\nPress any key to continue...")
  243.         os.pullEvent("key")
  244.         drawFileManager()
  245.     end
  246.    
  247.     -- Initialize file manager
  248.     loadFiles(currentPath)
  249.     drawFileManager()
  250.    
  251.     -- Handle file manager input
  252.     while fileManagerRunning do
  253.         local event, key = os.pullEvent("key")
  254.        
  255.         if key == keys.up then
  256.             selectedFile = selectedFile - 1
  257.             if selectedFile < 1 then
  258.                 selectedFile = #files
  259.             end
  260.            
  261.             -- Adjust scroll offset
  262.             if selectedFile < scrollOffset + 1 then
  263.                 scrollOffset = selectedFile - 1
  264.             elseif selectedFile > scrollOffset + maxDisplayFiles then
  265.                 scrollOffset = selectedFile - maxDisplayFiles
  266.             end
  267.            
  268.             drawFileManager()
  269.            
  270.         elseif key == keys.down then
  271.             selectedFile = selectedFile + 1
  272.             if selectedFile > #files then
  273.                 selectedFile = 1
  274.             end
  275.            
  276.             -- Adjust scroll offset
  277.             if selectedFile < scrollOffset + 1 then
  278.                 scrollOffset = selectedFile - 1
  279.             elseif selectedFile > scrollOffset + maxDisplayFiles then
  280.                 scrollOffset = selectedFile - maxDisplayFiles
  281.             end
  282.            
  283.             drawFileManager()
  284.            
  285.         elseif key == keys.enter then
  286.             if #files > 0 then
  287.                 local selectedItem = files[selectedFile]
  288.                 if selectedItem.type == "directory" then
  289.                     if selectedItem.name == ".." then
  290.                         currentPath = selectedItem.path
  291.                     else
  292.                         currentPath = selectedItem.path
  293.                     end
  294.                     loadFiles(currentPath)
  295.                     drawFileManager()
  296.                 else
  297.                     executeFile(selectedItem.path)
  298.                 end
  299.             end
  300.            
  301.         elseif key == keys.q then
  302.             fileManagerRunning = false
  303.         end
  304.     end
  305.    
  306.     drawMenu()
  307. end
  308.  
  309. -- Calculator with scrollable menu
  310. local function calculator()
  311.     local options = {
  312.         "Addition",
  313.         "Subtraction",
  314.         "Multiplication",
  315.         "Division",
  316.         "Back to Menu"
  317.     }
  318.  
  319.     local function drawCalculatorMenu(selected)
  320.         term.clear()
  321.         term.setCursorPos(1,1)
  322.         print("=== Calculator ===")
  323.         print("Use UP/DOWN arrows to navigate, ENTER to select.\n")
  324.  
  325.         for i, option in ipairs(options) do
  326.             if i == selected then
  327.                 term.setTextColor(colors.yellow)
  328.                 print("> " .. option)
  329.                 term.setTextColor(colors.white)
  330.             else
  331.                 print("  " .. option)
  332.             end
  333.         end
  334.     end
  335.  
  336.     local function readNumber(prompt)
  337.         while true do
  338.             write(prompt)
  339.             local input = read()
  340.             local num = tonumber(input)
  341.             if num then
  342.                 return num
  343.             else
  344.                 print("Invalid input, please enter a number.")
  345.             end
  346.         end
  347.     end
  348.  
  349.     local selected = 1
  350.     drawCalculatorMenu(selected)
  351.  
  352.     while true do
  353.         local event, key = os.pullEvent("key")
  354.         if key == keys.up then
  355.             selected = selected - 1
  356.             if selected < 1 then selected = #options end
  357.             drawCalculatorMenu(selected)
  358.         elseif key == keys.down then
  359.             selected = selected + 1
  360.             if selected > #options then selected = 1 end
  361.             drawCalculatorMenu(selected)
  362.         elseif key == keys.enter then
  363.             if options[selected] == "Back to Menu" then
  364.                 term.clear()
  365.                 return
  366.             else
  367.                 local a = readNumber("Enter first number: ")
  368.                 local b = readNumber("Enter second number: ")
  369.                 local result
  370.  
  371.                 if options[selected] == "Addition" then
  372.                     result = a + b
  373.                     print(string.format("Result: %.2f + %.2f = %.2f", a, b, result))
  374.                 elseif options[selected] == "Subtraction" then
  375.                     result = a - b
  376.                     print(string.format("Result: %.2f - %.2f = %.2f", a, b, result))
  377.                 elseif options[selected] == "Multiplication" then
  378.                     result = a * b
  379.                     print(string.format("Result: %.2f * %.2f = %.2f", a, b, result))
  380.                 elseif options[selected] == "Division" then
  381.                     if b == 0 then
  382.                         print("Error: Division by zero is not allowed.")
  383.                     else
  384.                         result = a / b
  385.                         print(string.format("Result: %.2f / %.2f = %.2f", a, b, result))
  386.                     end
  387.                 end
  388.  
  389.                 print("\nPress any key to return to calculator menu...")
  390.                 os.pullEvent("key")
  391.                 drawCalculatorMenu(selected)
  392.             end
  393.         end
  394.     end
  395. end
  396.  
  397. -- Shutdown procedure with farewell message
  398. local function shutdown()
  399.     clearScreen()
  400.     term.setTextColor(colors.red)
  401.     print("\nNeobox OS Alpha shutting down. Goodbye!")
  402.     sleep(1.5)
  403.     os.shutdown()
  404. end
  405.  
  406. -- Launch selected program or special function
  407. local function launchProgram(item)
  408.     if item.type == "shell" then
  409.         clearScreen()
  410.         shell.run("shell")
  411.         drawMenu()
  412.         return
  413.     elseif item.type == "filemanager" then
  414.         showFileManager()
  415.         return
  416.     elseif item.type == "reboot" then
  417.         os.reboot()
  418.         return
  419.     elseif item.type == "shutdown" then
  420.         shutdown()
  421.         return
  422.     elseif item.type == "calculator" then
  423.         calculator()
  424.         drawMenu()
  425.         return
  426.     end
  427.  
  428.     if item.program then
  429.         clearScreen()
  430.  
  431.         if fs.exists(item.program) or fs.exists("rom/programs/" .. item.program .. ".lua") then
  432.             local success, error = pcall(function()
  433.                 shell.run(item.program)
  434.             end)
  435.  
  436.             if not success then
  437.                 term.setTextColor(colors.red)
  438.                 print("Error running program: " .. tostring(error))
  439.             end
  440.         else
  441.             term.setTextColor(colors.red)
  442.             print("Program not found: " .. item.program)
  443.         end
  444.  
  445.         term.setTextColor(colors.yellow)
  446.         print("\nPress any key to return to menu...")
  447.         os.pullEvent("key")
  448.  
  449.         drawMenu()
  450.     end
  451. end
  452.  
  453. -- Main loop
  454. drawMenu()
  455.  
  456. while running do
  457.     local event, key = os.pullEvent("key")
  458.  
  459.     if key == keys.up then
  460.         selectedIndex = selectedIndex - 1
  461.         if selectedIndex < 1 then
  462.             selectedIndex = #menuItems
  463.         end
  464.         drawMenu()
  465.  
  466.     elseif key == keys.down then
  467.         selectedIndex = selectedIndex + 1
  468.         if selectedIndex > #menuItems then
  469.             selectedIndex = 1
  470.         end
  471.         drawMenu()
  472.  
  473.     elseif key == keys.enter then
  474.         launchProgram(menuItems[selectedIndex])
  475.  
  476.     elseif key == keys.q then
  477.         running = false
  478.     end
  479. end
  480.  
  481. clearScreen()
  482. term.setCursorPos(1,1)
  483. print("Neobox OS Alpha shutting down. Goodbye!")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement