forked from Hyperion/HyperionOS
293 lines
8.4 KiB
Plaintext
293 lines
8.4 KiB
Plaintext
--:Minify:--
|
|
-- help: display command reference with paged scrolling
|
|
|
|
local COMMANDS = {
|
|
-- {name, usage, description, {flags...}}
|
|
-- flags: {flag, desc}
|
|
{
|
|
name = "cat",
|
|
usage = "cat [file]",
|
|
desc = "Print file contents to stdout. Reads from stdin if no file given.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "cd",
|
|
usage = "cd [dir]",
|
|
desc = "Change working directory. Use '-' to return to previous directory.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "clear",
|
|
usage = "clear",
|
|
desc = "Clear the terminal screen.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "echo",
|
|
usage = "echo [text...]",
|
|
desc = "Print arguments to stdout.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "hfetch",
|
|
usage = "hfetch",
|
|
desc = "Display system information in a neofetch-style layout.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "id",
|
|
usage = "id [username]",
|
|
desc = "Print user identity (uid, gid). Defaults to current user.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "login",
|
|
usage = "login",
|
|
desc = "System login prompt. Launched automatically at boot.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "ls",
|
|
usage = "ls [-alh] [dir]",
|
|
desc = "List directory contents.",
|
|
flags = {
|
|
{"-a", "Show hidden files (starting with .)"},
|
|
{"-l", "Long format: permissions, owner, size"},
|
|
{"-h", "Human-readable file sizes"},
|
|
}
|
|
},
|
|
{
|
|
name = "lsusers",
|
|
usage = "lsusers",
|
|
desc = "List all user accounts with uid, gid, home, and shell.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "lua",
|
|
usage = "lua",
|
|
desc = "Interactive Lua REPL prompt.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "mkdir",
|
|
usage = "mkdir <dir>",
|
|
desc = "Create a directory.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "passwd",
|
|
usage = "passwd [username]",
|
|
desc = "Change a user password. Non-root must verify current password first.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "ps",
|
|
usage = "ps",
|
|
desc = "List running tasks with pid, user, name, and status.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "pwd",
|
|
usage = "pwd",
|
|
desc = "Print current working directory.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "su",
|
|
usage = "su [username]",
|
|
desc = "Switch user. Defaults to root. Root can switch without a password.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "sudo",
|
|
usage = "sudo [-u user] <command> [args...]",
|
|
desc = "Run a command as another user (default root). Authenticates as current user.",
|
|
flags = {
|
|
{"-u user", "Run as the specified user (name or uid)"},
|
|
}
|
|
},
|
|
{
|
|
name = "sysdump",
|
|
usage = "sysdump",
|
|
desc = "List all registered kernel syscalls.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "useradd",
|
|
usage = "useradd [-p pw] [-g gid] [-d home] [-s shell] [-M] <username>",
|
|
desc = "Create a new user account.",
|
|
flags = {
|
|
{"-p pw", "Set password (prompted interactively if omitted)"},
|
|
{"-g gid", "Set primary group id"},
|
|
{"-d home", "Set home directory (default: /home/username)"},
|
|
{"-s shell", "Set login shell (default: /bin/hysh)"},
|
|
{"-M", "Do not create home directory"},
|
|
}
|
|
},
|
|
{
|
|
name = "userdel",
|
|
usage = "userdel [-r] <username>",
|
|
desc = "Delete a user account.",
|
|
flags = {
|
|
{"-r", "Also recursively remove the user's home directory"},
|
|
}
|
|
},
|
|
{
|
|
name = "usermod",
|
|
usage = "usermod [-l name] [-p pw] [-g gid] [-d home] [-s shell] [-L] [-U] <username>",
|
|
desc = "Modify an existing user account.",
|
|
flags = {
|
|
{"-l name", "Rename the user"},
|
|
{"-p pw", "Set new password"},
|
|
{"-g gid", "Change primary group id"},
|
|
{"-d home", "Change home directory"},
|
|
{"-s shell", "Change login shell"},
|
|
{"-L", "Lock the account (disable login)"},
|
|
{"-U", "Unlock the account"},
|
|
}
|
|
},
|
|
{
|
|
name = "whoami",
|
|
usage = "whoami",
|
|
desc = "Print the current username.",
|
|
flags = {}
|
|
},
|
|
{
|
|
name = "yes",
|
|
usage = "yes [text]",
|
|
desc = "Repeatedly print 'y' (or given text) until interrupted with Ctrl+C.",
|
|
flags = {}
|
|
},
|
|
}
|
|
|
|
-- Build lines to display
|
|
local C_HEAD = 7 -- yellow (section headers)
|
|
local C_CMD = 5 -- cyan (command name)
|
|
local C_USAGE = 1 -- white (usage line)
|
|
local C_DESC = 13 -- grey (description)
|
|
local C_FLAG = 3 -- green (flag name)
|
|
local C_DIM = 12 -- dark grey
|
|
|
|
-- Each entry is {text, color}
|
|
local lines = {}
|
|
local function push(text, col) lines[#lines+1] = {text, col or 1} end
|
|
|
|
push("HyperionOS Command Reference", C_HEAD)
|
|
push(string.rep("=", 50), C_DIM)
|
|
push("", 1)
|
|
|
|
local args = {...}
|
|
local filter = args[1] -- optional: help <command>
|
|
|
|
local function addCmd(cmd)
|
|
push(cmd.name, C_CMD)
|
|
push(" Usage: " .. cmd.usage, C_USAGE)
|
|
push(" " .. cmd.desc, C_DESC)
|
|
if #cmd.flags > 0 then
|
|
for _, f in ipairs(cmd.flags) do
|
|
push(" " .. f[1], C_FLAG)
|
|
push(" " .. f[2], C_DESC)
|
|
end
|
|
end
|
|
push("", 1)
|
|
end
|
|
|
|
if filter then
|
|
local found = false
|
|
for _, cmd in ipairs(COMMANDS) do
|
|
if cmd.name == filter then addCmd(cmd); found = true; break end
|
|
end
|
|
if not found then
|
|
push("help: unknown command '" .. filter .. "'", 2)
|
|
push("Run 'help' with no arguments for the full list.", C_DESC)
|
|
end
|
|
else
|
|
push("Run 'help <command>' for details on a specific command.", C_DESC)
|
|
push("", 1)
|
|
for _, cmd in ipairs(COMMANDS) do addCmd(cmd) end
|
|
end
|
|
|
|
-- Pager
|
|
local sizeStr = syscall.devctl(1, "size")
|
|
local screenW = tonumber(sizeStr:sub(1, sizeStr:find(";")-1)) or 51
|
|
local screenH = tonumber(sizeStr:sub(sizeStr:find(";")+1)) or 19
|
|
local pageSize = screenH - 2 -- reserve bottom row for status bar
|
|
|
|
local scroll = 0
|
|
local totalLines = #lines
|
|
local dirty = true
|
|
|
|
local function render()
|
|
syscall.devctl(1, "clear")
|
|
syscall.devctl(1, "spos", 1, 1)
|
|
for row = 1, pageSize do
|
|
local li = scroll + row
|
|
if li <= totalLines then
|
|
local text, col = lines[li][1], lines[li][2]
|
|
syscall.devctl(1, "sfgc", col)
|
|
-- truncate to screen width
|
|
if #text > screenW then text = text:sub(1, screenW) end
|
|
syscall.write(1, text .. "\n")
|
|
else
|
|
syscall.write(1, "\n")
|
|
end
|
|
end
|
|
-- status bar
|
|
syscall.devctl(1, "sfgc", 16)
|
|
syscall.devctl(1, "sbgc", 13)
|
|
local pct = math.floor(math.min(100, (scroll + pageSize) / totalLines * 100))
|
|
local status = string.format(" help -- line %d/%d (%d%%) [up/down: scroll q: quit] ",
|
|
scroll + 1, totalLines, pct)
|
|
if #status > screenW then status = status:sub(1, screenW) end
|
|
syscall.devctl(1, "spos", 1, screenH)
|
|
syscall.write(1, status .. string.rep(" ", screenW - #status))
|
|
syscall.devctl(1, "sfgc", 1)
|
|
syscall.devctl(1, "sbgc", 16)
|
|
dirty = false
|
|
end
|
|
|
|
-- If output fits on one screen, just print without pager
|
|
if totalLines <= pageSize then
|
|
syscall.devctl(1, "clear")
|
|
syscall.devctl(1, "spos", 1, 1)
|
|
for _, line in ipairs(lines) do
|
|
syscall.devctl(1, "sfgc", line[2])
|
|
syscall.write(1, line[1] .. "\n")
|
|
end
|
|
syscall.devctl(1, "sfgc", 1)
|
|
return
|
|
end
|
|
|
|
render()
|
|
while true do
|
|
local ch = syscall.read(0)
|
|
if not ch or ch == "" then
|
|
-- idle
|
|
elseif ch == "q" or ch == "Q" then
|
|
break
|
|
elseif ch == "\17" then -- up arrow
|
|
if scroll > 0 then
|
|
scroll = scroll - 1
|
|
dirty = true
|
|
end
|
|
elseif ch == "\18" then -- down arrow
|
|
if scroll + pageSize < totalLines then
|
|
scroll = scroll + 1
|
|
dirty = true
|
|
end
|
|
elseif ch == "\19" then -- left / page up (reuse left arrow)
|
|
scroll = math.max(0, scroll - pageSize)
|
|
dirty = true
|
|
elseif ch == "\20" then -- right / page down
|
|
scroll = math.min(totalLines - pageSize, scroll + pageSize)
|
|
dirty = true
|
|
end
|
|
if dirty then render() end
|
|
end
|
|
|
|
-- Restore screen
|
|
syscall.devctl(1, "clear")
|
|
syscall.devctl(1, "spos", 1, 1)
|
|
syscall.devctl(1, "sfgc", 1)
|
|
syscall.devctl(1, "sbgc", 16)
|