v0.7.0 - Added basic CLI tools: ls, cd, cp, mv, rm, lua
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
local args = {...}
|
||||||
|
local file = args[1]
|
||||||
|
args = nil
|
||||||
|
local fs = import("filesystem")
|
||||||
|
|
||||||
|
if file:sub(1, 1) ~= "/" then
|
||||||
|
file = shell.workingDirectory .. file
|
||||||
|
end
|
||||||
|
if not fs.exists(file) then
|
||||||
|
print("\27[91mFile does not exist.")
|
||||||
|
end
|
||||||
|
local handle = fs.open(file, "r")
|
||||||
|
local data
|
||||||
|
repeat
|
||||||
|
data = handle:read(math.huge or math.maxinteger)
|
||||||
|
print(data, false)
|
||||||
|
until not data
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
local args = {...}
|
||||||
|
local directory = args[1]
|
||||||
|
args = nil
|
||||||
|
local fs = import("filesystem")
|
||||||
|
|
||||||
|
if directory == ".." then
|
||||||
|
local backDirectory = shell.workingDirectory:match("(.+)/.-/")
|
||||||
|
if backDirectory then
|
||||||
|
backDirectory = backDirectory .. "/"
|
||||||
|
else
|
||||||
|
backDirectory = "/"
|
||||||
|
end
|
||||||
|
shell.workingDirectory = backDirectory
|
||||||
|
else
|
||||||
|
if directory:sub(-1, -1) ~= "/" then
|
||||||
|
directory = directory .. "/"
|
||||||
|
end
|
||||||
|
if directory:sub(1, 1) ~= "/" then
|
||||||
|
directory = shell.workingDirectory .. directory
|
||||||
|
end
|
||||||
|
if fs.exists(directory) and fs.isDirectory(directory) or fs.exists(shell.workingDirectory .. directory) and fs.isDirectory(shell.workingDirectory .. directory) then
|
||||||
|
shell.workingDirectory = directory
|
||||||
|
else
|
||||||
|
print("error: no such directory")
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
clear()
|
||||||
|
-- truly so much going on here
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
local args = {...}
|
||||||
|
local fromFile, toFile = args[1], args[2]
|
||||||
|
args = nil
|
||||||
|
local fs = import("filesystem")
|
||||||
|
|
||||||
|
if fromFile:sub(1, 1) ~= "/" then
|
||||||
|
fromFile = shell.workingDirectory .. fromFile
|
||||||
|
end
|
||||||
|
if toFile:sub(1, 1) ~= "/" then
|
||||||
|
toFile = shell.workingDirectory .. toFile
|
||||||
|
end
|
||||||
|
if fromFile == toFile then
|
||||||
|
print("\27[91mSource and destination are the same.")
|
||||||
|
end
|
||||||
|
if not fs.exists(fromFile) then
|
||||||
|
print("\27[91mSource file does not exist.")
|
||||||
|
end
|
||||||
|
if fs.exists(toFile) then
|
||||||
|
print("Destination file already exists. Overwrite it? [Y/n] ", false)
|
||||||
|
if read():lower() == "n" then
|
||||||
|
print("Aborted.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
fs.copy(fromFile, toFile)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
print("\27[40m \27[41m \27[42m \27[43m \27[44m \27[45m \27[46m \27[47m \n\27[100m \27[101m \27[102m \27[103m \27[104m \27[105m \27[106m \27[107m ")
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
local args = {...}
|
||||||
|
local target = args[1]
|
||||||
|
args = nil
|
||||||
|
local fs = import("filesystem")
|
||||||
|
local maxLength = 0
|
||||||
|
local margin = 2 -- minimum space between filename and size
|
||||||
|
local dirTable = {}
|
||||||
|
local fileTable = {}
|
||||||
|
|
||||||
|
if target then
|
||||||
|
if target:sub(1, 1) ~= "/" then
|
||||||
|
target = shell.workingDirectory .. target
|
||||||
|
end
|
||||||
|
if target:sub(-1, -1) ~= "/" then
|
||||||
|
target = target .. "/"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
target = shell.workingDirectory
|
||||||
|
end
|
||||||
|
|
||||||
|
local files = fs.list(target)
|
||||||
|
|
||||||
|
for _, file in pairs(files) do
|
||||||
|
if file:sub(-1, -1) == "/" then
|
||||||
|
table.insert(dirTable, file)
|
||||||
|
file = file:sub(1, -2)
|
||||||
|
else
|
||||||
|
table.insert(fileTable, file)
|
||||||
|
end
|
||||||
|
if unicode.wlen(file) > maxLength then
|
||||||
|
maxLength = unicode.wlen(file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(dirTable)
|
||||||
|
table.sort(fileTable)
|
||||||
|
files = {}
|
||||||
|
for _, v in ipairs(dirTable) do
|
||||||
|
table.insert(files, v)
|
||||||
|
end
|
||||||
|
for _, v in ipairs(fileTable) do
|
||||||
|
table.insert(files, v)
|
||||||
|
end
|
||||||
|
dirTable, fileTable = nil, nil
|
||||||
|
for _, file in ipairs(files) do
|
||||||
|
local dir = false
|
||||||
|
local filetext
|
||||||
|
if file:sub(-1, -1) == "/" then -- i think this is a more efficient way to check if it's a directory
|
||||||
|
dir = true
|
||||||
|
filetext = "\27[93m"..file:sub(1, -2)
|
||||||
|
elseif file:find(".") and file:match("[^.]+$") == "lua" then
|
||||||
|
filetext = "\27[92m"..file
|
||||||
|
end
|
||||||
|
filetext = (filetext or file)..string.rep(" ", maxLength - unicode.wlen(file) + margin)
|
||||||
|
if dir then
|
||||||
|
print(filetext.." \27[0m[DIR]")
|
||||||
|
else
|
||||||
|
local size = fs.size(target .. file)
|
||||||
|
local sizeString
|
||||||
|
if convert(size, "B", "GiB") >= 1 then
|
||||||
|
sizeString = tostring(math.floor(convert(size, "B", "GiB") * 100 + 0.5) / 100).." GiB"
|
||||||
|
elseif convert(size, "B", "MiB") >= 1 then
|
||||||
|
sizeString = tostring(math.floor(convert(size, "B", "MiB") * 100 + 0.5) / 100).." MiB"
|
||||||
|
elseif convert(size, "B", "KiB") >= 1 then
|
||||||
|
sizeString = tostring(math.floor(convert(size, "B", "KiB") * 100 + 0.5) / 100).." KiB"
|
||||||
|
else
|
||||||
|
sizeString = tostring(size).." B"
|
||||||
|
end
|
||||||
|
print(filetext.."\27[0m"..sizeString)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
print("\27[44m".._VERSION.."\27[0m shell")
|
||||||
|
print('Type "exit" to exit.')
|
||||||
|
while true do
|
||||||
|
print("\27[44mlua>\27[0m ", false)
|
||||||
|
local command = read()
|
||||||
|
if command == "exit" then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
local function runCommand()
|
||||||
|
assert(load(command))()
|
||||||
|
end
|
||||||
|
local result, reason = xpcall(runCommand, function(errMsg)
|
||||||
|
return errMsg .. "\n\n" .. debug.traceback()
|
||||||
|
end)
|
||||||
|
if not result then
|
||||||
|
print("\27[91m" .. reason)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
local args = {...}
|
||||||
|
local fromFile, toFile = args[1], args[2]
|
||||||
|
args = nil
|
||||||
|
local fs = import("filesystem")
|
||||||
|
|
||||||
|
if fromFile:sub(1, 1) ~= "/" then
|
||||||
|
fromFile = shell.workingDirectory .. fromFile
|
||||||
|
end
|
||||||
|
if toFile:sub(1, 1) ~= "/" then
|
||||||
|
toFile = shell.workingDirectory .. toFile
|
||||||
|
end
|
||||||
|
if fromFile == toFile then
|
||||||
|
print("\27[91mSource and destination are the same.")
|
||||||
|
end
|
||||||
|
if not fs.exists(fromFile) then
|
||||||
|
print("\27[91mSource file does not exist.")
|
||||||
|
end
|
||||||
|
if fs.exists(toFile) then
|
||||||
|
print("Destination file already exists. Overwrite it? [Y/n] ", false)
|
||||||
|
if read():lower() == "n" then
|
||||||
|
print("Aborted.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
fs.rename(fromFile, toFile)
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
local args = {...}
|
||||||
|
local file = args[1]
|
||||||
|
args = nil
|
||||||
|
local fs = import("filesystem")
|
||||||
|
|
||||||
|
if file:sub(1, 1) ~= "/" then
|
||||||
|
file = shell.workingDirectory .. file
|
||||||
|
end
|
||||||
|
if not fs.exists(file) then
|
||||||
|
print("\27[91mFile does not exist.")
|
||||||
|
end
|
||||||
|
fs.remove(file)
|
||||||
+11
-1
@@ -2,7 +2,17 @@ local shellcfg = {
|
|||||||
["startupMessage"] = "\n │\n │ ".._OSVERSION.." running on ".._VERSION..'\n │ Welcome! Type "help" to get started.\n │\n ', -- message shown on startup
|
["startupMessage"] = "\n │\n │ ".._OSVERSION.." running on ".._VERSION..'\n │ Welcome! Type "help" to get started.\n │\n ', -- message shown on startup
|
||||||
["prompt"] = "\x1b[92m%s > \x1b[0m", -- shell prompt, %s will be replaced with working directory. example: "%s > " turns to "/current/working/directory > "
|
["prompt"] = "\x1b[92m%s > \x1b[0m", -- shell prompt, %s will be replaced with working directory. example: "%s > " turns to "/current/working/directory > "
|
||||||
["path"] = { -- default locations where programs will be run from
|
["path"] = { -- default locations where programs will be run from
|
||||||
"/halyde/apps/"}
|
"/halyde/apps/"
|
||||||
|
}, ["aliases"] = { -- shell command aliases
|
||||||
|
["copy"] = "cp",
|
||||||
|
["move"] = "mv",
|
||||||
|
["rename"] = "mv",
|
||||||
|
["ren"] = "mv",
|
||||||
|
["dir"] = "ls",
|
||||||
|
["man"] = "help",
|
||||||
|
["del"] = "rm",
|
||||||
|
[".."] = "cd .."
|
||||||
|
}, ["defaultWorkingDirectory"] = "/home/" -- the working directory that gets set when halyde starts
|
||||||
}
|
}
|
||||||
|
|
||||||
return shellcfg
|
return shellcfg
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local loadfile = ...
|
local loadfile = ...
|
||||||
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
|
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
|
||||||
|
|
||||||
_G._OSVERSION = "Halyde 0.6.0"
|
_G._OSVERSION = "Halyde 0.7.0"
|
||||||
|
|
||||||
function _G.import(module, ...)
|
function _G.import(module, ...)
|
||||||
local args = table.pack(...)
|
local args = table.pack(...)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ local function runCoroutines()
|
|||||||
end
|
end
|
||||||
if coroutine.status(_G.cormgr.corList[i]) == "dead" then
|
if coroutine.status(_G.cormgr.corList[i]) == "dead" then
|
||||||
table.remove(_G.cormgr.corList, i)
|
table.remove(_G.cormgr.corList, i)
|
||||||
break
|
i = i - 1
|
||||||
end
|
end
|
||||||
--computer.pullSignal(0)
|
--computer.pullSignal(0)
|
||||||
--coroutine.yield()
|
--coroutine.yield()
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
|
local conversionTables = {
|
||||||
|
["bytes"] = {
|
||||||
|
["B"] = 1,
|
||||||
|
["KB"] = 1000,
|
||||||
|
["MB"] = 1000000,
|
||||||
|
["GB"] = 1000000000
|
||||||
|
}, ["bibytes"] = {
|
||||||
|
["B"] = 1,
|
||||||
|
["KiB"] = 1024,
|
||||||
|
["MiB"] = 1048576,
|
||||||
|
["GiB"] = 1073741824
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function table.find(table, item)
|
function table.find(table, item)
|
||||||
for k, v in pairs(table) do
|
for k, v in pairs(table) do
|
||||||
if v == item then
|
if v == item then
|
||||||
return(v)
|
return k
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -20,3 +34,12 @@ function table.copy(orig)
|
|||||||
end
|
end
|
||||||
return copy
|
return copy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function convert(amount, fromUnit, toUnit)
|
||||||
|
for _, convTable in pairs(conversionTables) do
|
||||||
|
if convTable[toUnit] then
|
||||||
|
return amount / convTable[toUnit] * convTable[fromUnit]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false, "unit does not exist"
|
||||||
|
end
|
||||||
|
|||||||
+10
-7
@@ -1,15 +1,19 @@
|
|||||||
local shellcfg = import("/halyde/config/shell.cfg")
|
local shellcfg = import("/halyde/config/shell.cfg")
|
||||||
import("termlib")
|
import("/halyde/core/termlib.lua")
|
||||||
local event = import("event")
|
local event = import("event")
|
||||||
local ocelot = component.proxy(component.list("ocelot")())
|
--local ocelot = component.proxy(component.list("ocelot")())
|
||||||
local filesystem = import("filesystem")
|
local filesystem = import("filesystem")
|
||||||
|
|
||||||
_G.shell = {}
|
_G.shell = {}
|
||||||
_G.shell.workingDirectory = "/"
|
_G.shell.workingDirectory = shellcfg["defaultWorkingDirectory"]
|
||||||
|
_G.shell.aliases = shellcfg["aliases"]
|
||||||
|
|
||||||
local function parseCommand(command)
|
local function parseCommand(command)
|
||||||
checkArg(1, command, "string")
|
if shell.aliases[command:match("[^ ]+")] then
|
||||||
local gm, result, args, trimmedCommand = command:gmatch('[^ ]+'), nil, {}, command
|
local _, cmdend = command:find("[^ ]+")
|
||||||
|
command = shell.aliases[command:match("[^ ]+")] .. command:sub(cmdend + 1)
|
||||||
|
end
|
||||||
|
local gm, result, args, trimmedCommand = command:gmatch("[^ ]+"), nil, {}, command
|
||||||
while true do
|
while true do
|
||||||
result = gm()
|
result = gm()
|
||||||
if not result then
|
if not result then
|
||||||
@@ -63,7 +67,7 @@ local function parseCommand(command)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not foundfile then
|
if not foundfile then
|
||||||
print("no such file or command: "..args[1])
|
print("No such file or command: "..args[1])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -75,6 +79,5 @@ while true do
|
|||||||
-- termlib.cursorPosX = #(shell.workingDirectory .. " > ")
|
-- termlib.cursorPosX = #(shell.workingDirectory .. " > ")
|
||||||
-- termlib.cursorPosY = termlib.cursorPosY - 1
|
-- termlib.cursorPosY = termlib.cursorPosY - 1
|
||||||
local shellCommand = read()
|
local shellCommand = read()
|
||||||
ocelot.log("parsing "..shellCommand)
|
|
||||||
parseCommand(shellCommand)
|
parseCommand(shellCommand)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ function _G.print(text,endNewLine)
|
|||||||
if not text or not tostring(text) then
|
if not text or not tostring(text) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
text = "\27[0m" .. text:gsub("\t", " ")
|
||||||
text = tostring(text)
|
text = tostring(text)
|
||||||
readBreak = 0
|
readBreak = 0
|
||||||
-- readBreak is for when, inside the for loop, there normally would have been an increase in the "i" variable because it has read more than one character.
|
-- readBreak is for when, inside the for loop, there normally would have been an increase in the "i" variable because it has read more than one character.
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
local componentlib = {}
|
local componentlib
|
||||||
|
if table.copy then
|
||||||
|
componentlib = table.copy(component)
|
||||||
|
else
|
||||||
|
componentlib = {}
|
||||||
|
end
|
||||||
|
|
||||||
function componentlib.get(address)
|
function componentlib.get(address)
|
||||||
checkArg(1, address, "string")
|
checkArg(1, address, "string")
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ local component
|
|||||||
|
|
||||||
if loadfile then
|
if loadfile then
|
||||||
component = loadfile("/halyde/lib/component.lua")(loadfile)
|
component = loadfile("/halyde/lib/component.lua")(loadfile)
|
||||||
else
|
elseif import then
|
||||||
component = import("component")
|
component = import("component")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -67,11 +67,102 @@ function filesystem.open(path, mode) -- opens a file and returns its handle
|
|||||||
end
|
end
|
||||||
|
|
||||||
function filesystem.list(path)
|
function filesystem.list(path)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
if path == "/mnt/" then
|
||||||
|
-- list drives
|
||||||
|
local returnTable = {}
|
||||||
|
for address, _ in component.list("filesystem") do
|
||||||
|
table.insert(returnTable, address:sub(1, 3) .. "/")
|
||||||
|
end
|
||||||
|
return returnTable
|
||||||
|
else
|
||||||
|
local address, absPath = filesystem.processPath(path)
|
||||||
|
if not address then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return component.invoke(address, "list", absPath)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function filesystem.size(path)
|
||||||
checkArg(1, path, "string")
|
checkArg(1, path, "string")
|
||||||
local address, absPath = filesystem.processPath(path)
|
local address, absPath = filesystem.processPath(path)
|
||||||
if not address then
|
if not address then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return component.invoke(address, "list", absPath)
|
return component.invoke(address, "size", absPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function filesystem.isDirectory(path)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
local address, absPath = filesystem.processPath(path)
|
||||||
|
if not address then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return component.invoke(address, "isDirectory", absPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function filesystem.rename(fromPath, toPath)
|
||||||
|
checkArg(1, fromPath, "string")
|
||||||
|
checkArg(2, toPath, "string")
|
||||||
|
local fromAddress, fromAbsPath = filesystem.processPath(fromPath)
|
||||||
|
local toAddress, toAbsPath = filesystem.processPath(toPath)
|
||||||
|
if not fromAddress or not toAddress then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if fromAddress == toAddress then
|
||||||
|
return component.invoke(fromAddress, "rename", fromAbsPath, toAbsPath)
|
||||||
|
else
|
||||||
|
local handle = component.invoke(fromAddress, "open", fromAbsPath, "r")
|
||||||
|
local data, tmpdata
|
||||||
|
repeat
|
||||||
|
tmpdata = component.invoke(fromAddress, "read", handle, math.huge or math.maxinteger)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
tmpdata = component.invoke(fromAddress, "close", handle)
|
||||||
|
local handle = component.invoke(toAddress, "open", toAbsPath, "w")
|
||||||
|
component.invoke(toAddress, "write", handle, data)
|
||||||
|
component.invoke(toAddress, "close", handle)
|
||||||
|
component.invoke(fromAddress, "remove", fromAbsPath)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function filesystem.copy(fromPath, toPath)
|
||||||
|
checkArg(1, fromPath, "string")
|
||||||
|
checkArg(2, toPath, "string")
|
||||||
|
local fromAddress, fromAbsPath = filesystem.processPath(fromPath)
|
||||||
|
local toAddress, toAbsPath = filesystem.processPath(toPath)
|
||||||
|
if not fromAddress or not toAddress then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local handle = component.invoke(fromAddress, "open", fromAbsPath, "r")
|
||||||
|
local data, tmpdata = "", nil
|
||||||
|
repeat
|
||||||
|
tmpdata = component.invoke(fromAddress, "read", handle, math.huge or math.maxinteger)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
tmpdata = component.invoke(fromAddress, "close", handle)
|
||||||
|
local handle = component.invoke(toAddress, "open", toAbsPath, "w")
|
||||||
|
component.invoke(toAddress, "write", handle, data)
|
||||||
|
component.invoke(toAddress, "close", handle)
|
||||||
|
end
|
||||||
|
|
||||||
|
function filesystem.isDirectory(path)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
local address, absPath = filesystem.processPath(path)
|
||||||
|
if not address then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return component.invoke(address, "isDirectory", absPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function filesystem.remove(path)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
local address, absPath = filesystem.processPath(path)
|
||||||
|
if not address then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return component.invoke(address, "remove", absPath)
|
||||||
|
end
|
||||||
|
|
||||||
return(filesystem)
|
return(filesystem)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ local function loadfile(file)
|
|||||||
data = data .. (tmpdata or "")
|
data = data .. (tmpdata or "")
|
||||||
until not tmpdata
|
until not tmpdata
|
||||||
component.invoke(computer.getBootAddress(), "close", handle)
|
component.invoke(computer.getBootAddress(), "close", handle)
|
||||||
return(assert(load(data, "=" .. file)))
|
return assert(load(data, "=" .. file))
|
||||||
end
|
end
|
||||||
|
|
||||||
local function handleError(errorMessage)
|
local function handleError(errorMessage)
|
||||||
|
|||||||
Reference in New Issue
Block a user