BananaOS/test/sbin/bsh.lua
2025-02-21 00:33:21 -05:00

204 lines
5.4 KiB
Lua

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