local bsh = {} local component = require("component") local computer = require("computer") local event = require("event") local fs = require("filesystem") local package = require("package") _G.ExecPath = "/sbin/?.lua;/bin/?.lua" if fs.exists("/etc/motd") then local motd_h = fs.open("/etc/motd", "r") print(fs.read(motd_h)) fs.close(motd_h) end print("\n") -- BUG: when in /bin directory, running something tries to run /binhello.lua -- FEAT: autofill slashes, and .lua -- FEAT: handle .. bsh.running = true local cwd = "/home/" local function keyin(timeout) while true do local _,_,ascii,code,_ = event.pull("key_down",timeout) return ascii,code end end function bsh.split(str) local words = {} for word in str:gmatch("%S+") do table.insert(words, word) end return words end function bsh.is_in_arr(arr,elem) for i in ipairs(arr) do if tostring(arr[i]) == tostring(elem) then return true end end return false end function bsh.command(buffer) if #buffer == 0 then return end local command = bsh.split(buffer) if command[1] == "ls" then local cwdls if command[2] == nil then cwdls = fs.getlisting(cwd) else cwdls = fs.getlisting(command[2]) end if cwdls ~= nil then for i = 1, #cwdls do print(cwdls[i] .. " ") end else print("(Nothing here!)") end print("\r\n") elseif command[1] == "cd" then if command[2] == nil then error("no argument") else cwd = command[2] end elseif command[1] == "clear" then local w,h=component.gpu.getResolution() component.gpu.fill(1,1,w,h," ") component.gpu.setCursor(2,1) elseif command[1] == "exit" then bsh.running = false else -- execute file, this sucks tho local location = command[1] local s,_ = pcall(fs.loadfile,location) -- is in cwd? if not s then if bsh.is_in_arr(fs.getlisting(cwd),command[1]) then location = cwd .. command[1] else -- no, check path local a = package.search(command[1],ExecPath) if a ~= false then location = a else error("command not found") end end end local a = fs.loadfile(location) a(command) end end local function prompt() print(cwd .." #> ") end print("bsh v3\n") local buffer = "" local gpu = component.gpu prompt() local cursor = "█" local cursorOnOff = 1 local history = {} local history_index = 1 while bsh.running do local nextkeycode, code = keyin() local charAtCurLocation = " " local cur = gpu.getCursor() --print(nextkeycode,"=",code," ") if nextkeycode == nil and code == nil then -- timeout reached, invert cursor cursorOnOff = cursorOnOff * -1 if cursorOnOff == 1 then charAtCurLocation = gpu.get(cur.x,cur.y) gpu.set(cur.x,cur.y,cursor) else gpu.set(cur.x,cur.y,charAtCurLocation) end end if nextkeycode == 0 or nextkeycode == nil then local preBuffer=buffer if code == 42 then -- shift -- ignore elseif code == 200 then -- up if history[history_index] then buffer = history[history_index] history_index = history_index - 1 gpu.setCursor(1) prompt() for i=1,#preBuffer do print(" ") end gpu.setCursor(1) prompt() print(buffer) end elseif code == 208 then -- down if history[history_index+1] then history_index = history_index + 2 buffer = history[history_index] gpu.setCursor(1) prompt() for i=1,#preBuffer do print(" ") end gpu.setCursor(1) prompt() print(buffer) end end else gpu.set(cur.x,cur.y,charAtCurLocation) local nextkey = string.char(nextkeycode) if nextkeycode == 13 then --enter table.insert(history, buffer) history_index = #history if cursorOnOff ~= 1 then gpu.set(cur.x,cur.y,charAtCurLocation) end print("\n") local success, reason = xpcall(bsh.command, function(a) return {a, debug.traceback()} end, buffer) if not success then if reason then print(reason[1].."\n\n") component.gpu.setForeground(0xff3333) print(reason[2]) component.gpu.setForeground(0xffffff) end end buffer = "" nextkeycode = nil print("\n") prompt() elseif nextkeycode == 8 then --backsp if #buffer ~= 0 then buffer = buffer:sub(1, -2) gpu.moveCursor(-1) print(" ") gpu.moveCursor(-1) end else buffer = buffer .. nextkey print(nextkey) end end end