added users (spsf untangled by astronand)
This commit is contained in:
299
Src/Hyperion-bash/bin/hysh
Normal file
299
Src/Hyperion-bash/bin/hysh
Normal file
@@ -0,0 +1,299 @@
|
||||
--:Minify:--
|
||||
syscall.open("/dev/tty/TTY1","r") --stdin (Device 0)
|
||||
syscall.open("/dev/tty/TTY1","w") --stdout (Device 1)
|
||||
syscall.open("/dev/null","w") --stderr (device 2)
|
||||
|
||||
local success, errorMsg = xpcall(function()
|
||||
|
||||
|
||||
|
||||
local fs = require("sys.fs")
|
||||
|
||||
syscall.devctl(1,"clear")
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
syscall.devctl(1,"spos",1,1)
|
||||
print("HyperionOS hysh Shell")
|
||||
|
||||
local userhost = (syscall.getUsername() or "Unknown").."@"..(syscall.getHostname() or "Unknown")
|
||||
local commandHistory = {}
|
||||
local terminate = false
|
||||
syscall.setEnviron("SHELL","rtbash")
|
||||
syscall.setEnviron("PATH","/bin/")
|
||||
syscall.chdir("/")
|
||||
local oldWD = ""
|
||||
|
||||
for i = 1, 16 do
|
||||
syscall.devctl(1,"sbgc",i)
|
||||
printInline(" ");
|
||||
end
|
||||
print("\n")
|
||||
|
||||
syscall.sigcatch(function(sig)
|
||||
if sig == 1 then
|
||||
terminate = true
|
||||
end
|
||||
end)
|
||||
|
||||
local builtinCmds = {}
|
||||
|
||||
builtinCmds.cd = function(path)
|
||||
local cwd = syscall.getcwd()
|
||||
local dirIn = (path or "")
|
||||
if dirIn == "-" then
|
||||
if oldWD == "" then
|
||||
print("hysh-cd: No previous working directory set.")
|
||||
else
|
||||
print(oldWD)
|
||||
syscall.chdir(oldWD)
|
||||
oldWD = cwd
|
||||
end
|
||||
return
|
||||
end
|
||||
local dirInMod = dirIn
|
||||
if dirIn:sub(1, 1) ~= "/" then dirInMod = cwd .. "/" .. dirIn end
|
||||
local parts = {}
|
||||
for part in dirInMod:gmatch("[^/]+") do
|
||||
if part == ".." then
|
||||
if #parts > 0 then table.remove(parts) end
|
||||
elseif part ~= "." and part ~= "" then
|
||||
table.insert(parts, part)
|
||||
end
|
||||
end
|
||||
local normDir = "/" .. table.concat(parts, "/")
|
||||
if normDir:sub(#normDir, #normDir) ~= "/" then normDir = normDir .. "/" end
|
||||
|
||||
if not fs.isDir(normDir) then
|
||||
print("hysh-cd: "..dirIn..": No such directory.")
|
||||
return
|
||||
end
|
||||
oldWD = cwd
|
||||
syscall.chdir(normDir)
|
||||
end
|
||||
|
||||
|
||||
local function getUserInput()
|
||||
syscall.devctl(1,"sfgc",3)
|
||||
syscall.write(1, userhost)
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
syscall.write(1, ":")
|
||||
syscall.devctl(1,"sfgc",10)
|
||||
syscall.write(1, syscall.getcwd())
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
syscall.write(1, "$ ")
|
||||
local curOffsetStr = syscall.devctl(1, "gpos")
|
||||
local curOffsetX = tonumber(curOffsetStr:sub(1, curOffsetStr:find(";")-1))
|
||||
local curOffsetY = tonumber(curOffsetStr:sub(curOffsetStr:find(";")+1))
|
||||
|
||||
local input = ""
|
||||
local blinkState = false
|
||||
local cursorPos = 1
|
||||
local history = 0
|
||||
local dirty = true -- redraw on first iteration
|
||||
|
||||
local function redraw()
|
||||
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
|
||||
-- text before cursor
|
||||
syscall.write(1, string.sub(input, 1, cursorPos-1))
|
||||
-- cursor character (inverted if blinking on)
|
||||
if blinkState then
|
||||
syscall.devctl(1,"sfgc",16)
|
||||
syscall.devctl(1,"sbgc",1)
|
||||
end
|
||||
if cursorPos > #input then
|
||||
syscall.write(1, " ")
|
||||
else
|
||||
syscall.write(1, string.sub(input, cursorPos, cursorPos))
|
||||
end
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
syscall.devctl(1,"sbgc",16)
|
||||
-- text after cursor + trailing space to erase old chars
|
||||
syscall.write(1, string.sub(input, cursorPos+1) .. " ")
|
||||
end
|
||||
|
||||
while true do
|
||||
local key = syscall.read(0)
|
||||
if key and key ~= "" then
|
||||
if key == "\19" then -- left arrow
|
||||
if cursorPos > 1 then
|
||||
cursorPos = cursorPos - 1
|
||||
dirty = true
|
||||
end
|
||||
elseif key == "\20" then -- right arrow
|
||||
if cursorPos <= #input then
|
||||
cursorPos = cursorPos + 1
|
||||
dirty = true
|
||||
end
|
||||
elseif key == "\17" then -- up arrow
|
||||
if history < #commandHistory then
|
||||
history = history + 1
|
||||
input = commandHistory[#commandHistory - history + 1]
|
||||
cursorPos = #input + 1
|
||||
dirty = true
|
||||
end
|
||||
elseif key == "\18" then -- down arrow
|
||||
if history > 1 then
|
||||
history = history - 1
|
||||
input = commandHistory[#commandHistory - history + 1]
|
||||
cursorPos = #input + 1
|
||||
dirty = true
|
||||
elseif history == 1 then
|
||||
history = 0
|
||||
input = ""
|
||||
cursorPos = 1
|
||||
dirty = true
|
||||
end
|
||||
elseif key == "\b" then
|
||||
if cursorPos > 1 then
|
||||
input = string.sub(input, 1, cursorPos-2) .. string.sub(input, cursorPos)
|
||||
cursorPos = cursorPos - 1
|
||||
dirty = true
|
||||
end
|
||||
elseif key == "\n" then
|
||||
-- redraw cleanly with no cursor highlight before committing
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
syscall.devctl(1,"sbgc",16)
|
||||
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
|
||||
syscall.write(1, input .. " \n")
|
||||
return input
|
||||
else
|
||||
input = string.sub(input, 1, cursorPos-1) .. key .. string.sub(input, cursorPos)
|
||||
cursorPos = cursorPos + 1
|
||||
dirty = true
|
||||
end
|
||||
end
|
||||
|
||||
-- cursor blink
|
||||
local curBlink = ((math.floor(syscall.getUptime() / 500) % 2) == 0)
|
||||
if curBlink ~= blinkState then
|
||||
blinkState = curBlink
|
||||
dirty = true
|
||||
end
|
||||
|
||||
if dirty then
|
||||
redraw()
|
||||
dirty = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function runCommand(command)
|
||||
do
|
||||
local func = load("return " .. command, "@equation", "t", {})
|
||||
if func then
|
||||
local success, result = pcall(func)
|
||||
if success and type(result) == "number" then
|
||||
print(result)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
terminate = false
|
||||
local args = string.split(command, " ")
|
||||
if builtinCmds[args[1]] then
|
||||
local success, msg = pcall(builtinCmds[args[1]], table.unpack(args, 2))
|
||||
if not success then
|
||||
local errSL = string.sub(msg, string.find(msg, "]") + 2)
|
||||
syscall.devctl(1,"sfgc",2)
|
||||
printInline(args[1]..": Program runtime error on line ")
|
||||
print(string.sub(errSL, 1, string.find(errSL, ":") - 1))
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
print(string.sub(errSL, string.find(errSL, ":") + 1))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local cmdPath = ""
|
||||
if string.find(args[1], "/") then
|
||||
if fs.exists(args[1]) then
|
||||
cmdPath = args[1]
|
||||
end
|
||||
else
|
||||
local paths = string.split(syscall.getEnviron("PATH"), ":")
|
||||
for _, path in pairs(paths) do
|
||||
if fs.exists(path..args[1]) then
|
||||
cmdPath = path..args[1]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if cmdPath == "" then
|
||||
print(args[1]..": Command not found")
|
||||
return
|
||||
end
|
||||
|
||||
local progName = string.sub(cmdPath, #cmdPath - string.find(string.reverse(cmdPath), "/") + 2)
|
||||
|
||||
local text = fs.readAllText(cmdPath)
|
||||
local program, err = load(text, progName)
|
||||
if not program then
|
||||
local errSL = string.sub(err, string.find(err, ":") + 1)
|
||||
syscall.devctl(1,"sfgc",2)
|
||||
printInline(progName..": Program load error on line ")
|
||||
print(string.sub(errSL, 1, string.find(errSL, ":") - 1))
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
print(string.sub(errSL, string.find(errSL, ":") + 1))
|
||||
return
|
||||
end
|
||||
|
||||
local proc = syscall.spawn(function(...)
|
||||
syscall.open("/dev/tty/TTY1","r")
|
||||
syscall.open("/dev/tty/TTY1","w")
|
||||
syscall.open("/dev/null","w")
|
||||
local success, msg = pcall(program, ...)
|
||||
if not success then
|
||||
local errSL = string.sub(msg, string.find(msg, ":") + 1)
|
||||
syscall.devctl(1,"sfgc",2)
|
||||
printInline(progName..": Program runtime error on line ")
|
||||
print(string.sub(errSL, 1, string.find(errSL, ":") - 1))
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
print(string.sub(errSL, string.find(errSL, ":") + 1))
|
||||
end
|
||||
end, progName, nil, {table.unpack(args, 2)})
|
||||
|
||||
while true do
|
||||
local exited, code = syscall.collect(proc)
|
||||
if exited then
|
||||
if code then
|
||||
print("\nTask exited with code:\n"..tostring(code))
|
||||
end
|
||||
return
|
||||
end
|
||||
if terminate then
|
||||
local success, err = syscall.kill(proc)
|
||||
if success then
|
||||
syscall.devctl(1,"sbgc",16)
|
||||
syscall.devctl(1,"sfgc",2)
|
||||
print("\nProgram Terminated.")
|
||||
syscall.devctl(1,"sfgc",1)
|
||||
end
|
||||
terminate = false
|
||||
break
|
||||
end
|
||||
sleep(0.05)
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
local command = getUserInput()
|
||||
if command ~= "" then
|
||||
if command ~= commandHistory[#commandHistory] then
|
||||
table.insert(commandHistory, command)
|
||||
end
|
||||
runCommand(command)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--ERROR HANDLING
|
||||
end, debug.traceback)
|
||||
|
||||
if not success then
|
||||
syscall.log("Error running shell: "..errorMsg, "ERROR")
|
||||
syscall.devctl(1,"sfgc",2)
|
||||
syscall.devctl(1,"sbgc",16)
|
||||
print()
|
||||
print("Error running shell: ")
|
||||
print(errorMsg)
|
||||
end
|
||||
Reference in New Issue
Block a user