diff --git a/.github/workflows/minify.yml b/.github/workflows/minify.yml new file mode 100644 index 0000000..3730cf7 --- /dev/null +++ b/.github/workflows/minify.yml @@ -0,0 +1,59 @@ +name: Minify all Lua files to minified branch + +on: + push: + branches: + - main + +jobs: + minify: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout main branch + uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + + - name: Get latest commit info + id: commit + run: | + COMMIT_MSG=$(git log -1 --pretty=%s) + echo "message=${COMMIT_MSG}" >> $GITHUB_OUTPUT + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install luamin + run: npm install -g luamin + + - name: Switch to minified branch + run: git checkout minified + + - name: Copy files from main + run: | + git checkout main -- . + git reset HEAD + + - name: Minify all Lua files + run: | + set -e + for file in $(find . -name "*.lua" -not -path "./.git/*"); do + luamin -f "$file" > "$file.min" || true + # For some stupid fucking reason, luamin returns exit code 1 + mv "$file.min" "$file" + done + + - name: Commit and push to minified branch + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + git add -A + git commit -m "${{ steps.commit.outputs.message }} (minified)" + git push origin minified diff --git a/halyde/apps/argentum.lua b/halyde/apps/argentum.lua index 4edff50..fddefd5 100644 --- a/halyde/apps/argentum.lua +++ b/halyde/apps/argentum.lua @@ -1,691 +1 @@ -local packages = {...} -local command = packages[1] -table.remove(packages, 1) -local fs = import("filesystem") -local component = import("component") -local agReg = import("/argentum/registry.cfg") -if not command then - shell.run("help argentum") - return -end -if not component.list("internet")() then - print("\27[91mThis program requires an internet card to run.") - return -end -local internet = component.internet -local source -if table.find(packages, "-s") then - source = table.remove(packages, table.find(packages, "-s") + 1) - table.remove(packages, table.find(packages, "-s")) - print("Using " .. source .. " as package source") -elseif table.find(packages, "--source") then - source = table.remove(packages, table.find(packages, "--source") + 1) - table.remove(packages, table.find(packages, "--source")) - print("Using " .. source .. " as package source") -else - print("Using main registry as package source") -end -if source and source:sub(1, 1) == "/" and source:sub(-1, -1) ~= "/" then - source = source .. "/" -end -local packageList = table.copy(packages) - -local function getFile(path) - if path:sub(1,1) == "/" then - if not fs.exists(path) then - return false, "file does not exist" - end - local handle, data, tmpdata = fs.open(path, "r"), "", nil - repeat - tmpdata = handle:read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() - return data - else - local request, data, tmpdata = nil, "", nil - local status, errorMessage = pcall(function() - request = internet.request(path) - request:finishConnect() - end) - if not status then - return false, errorMessage - end - local responseCode = request:response() - if responseCode and responseCode ~= 200 then - return false, responseCode - end - repeat - tmpdata = request.read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - return data - end -end - -local i = 1 - -local function getAgConfig(package, source) - source = source or agReg[package] - local data, errorMessage = getFile(source .. "argentum.cfg") - if not data or data == "" then - print("\27[91mCould not fetch Ag config: " .. (errorMessage or "returned nil data")) - return false - end - local func, errorMessage = load(data, "=argentum.cfg", "bt", {}) - if not func then - print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.") - return false - end - local agcfg - local status, errorMessage = pcall(function() - agcfg = func() - end) - if not status then - print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.") - return false - end - if not agcfg[package] or not agcfg[package].maindir or not agcfg[package].directories or not agcfg[package].files or not agcfg[package].version then - local response = ("\27[91mAg config of " .. package .. " is improperly configured.\nPlease contact the package owner.") - end - return agcfg -end - -local function doChecks(package) - if not agReg[package] and not source then - print("\27[91mPackage " .. package .. " does not exist.") - return false - end - if fs.exists("/argentum/store/" .. package) then - print("\27[91mPackage " .. package .. " is already installed.") - return false - end - agcfg = getAgConfig(package, source) - if not agcfg then - return false - end - if agcfg[package].dependencies then - for _, dependency in ipairs(agcfg[package].dependencies) do - if not agReg[dependency] and not agcfg[dependency] then - local response = read(nil, "\27[91mPackage " .. package .. " requires dependency " .. dependency .. " that does not exist.\n[A - Abort/s - Skip]") - if response:lower() ~= "s" then - fs.remove("/argentum/store/" .. package) - return false - end - end - end - for _, dependency in pairs(agcfg[package].dependencies) do - print(package .. " depends on " .. dependency) - if not table.find(packages, dependency) and doChecks(dependency) then - table.insert(packages, table.find(packages, package), dependency) - table.insert(packageList, dependency) - i = i + 1 - end - end - end - return true -end - -local function lpad(str, len, char) - str=tostring(str) - if char == nil then char = ' ' end - return string.rep(char, len - #str) .. str -end - -local gpu = component.gpu -local width,height = gpu.getResolution() -local function progress(package,progress) - local info = string.format("%s %s%%",package,lpad(math.floor(progress*100),2)) - - info=info..string.rep(" ",width-#info) - local progX = math.floor(progress*width) - gpu.setBackground(0x00FF00) - gpu.setForeground(0x000000) - gpu.set(1,height,info:sub(1,progX)) - gpu.setBackground(0x000000) - gpu.setForeground(0xFFFFFF) - gpu.set(progX+1,height,info:sub(progX+1)) -end - -local function clearProgress() - gpu.setBackground(0x000000) - gpu.fill(1,height,width,1," ") -end - -local function installPackage(package, overwriteFlag) - if not overwriteFlag then - overwriteFlag = false - end - if not overwriteFlag then print("Installing " .. package .. "...") end - local agcfg = getAgConfig(package, source) - if not agcfg then - return false - end - local source = source or agReg[package] - local packageStore = "V" .. agcfg[package].version - if agcfg[package].dependencies then - for _, dependency in ipairs(agcfg[package].dependencies) do - if not agReg[dependency] and not agcfg[dependency] then - local response = read(nil, "\27[91mPackage " .. package .. " requires dependency " .. dependency .. " that does not exist.\n[A - Abort/s - Skip]") - if response:lower() ~= "s" then - fs.remove("/argentum/store/" .. package) - return false - end - end - end - for _, dependency in pairs(agcfg[package].dependencies) do - if agReg[dependency] or agcfg[dependency] then - --installPackage(dependency) - packageStore = packageStore .. "\nD" .. dependency - end - end - end - if agcfg[package].directories then - for _, directory in pairs(agcfg[package].directories) do - if directory:sub(-1, -1) ~= "/" then - directory = directory .. "/" - end - packageStore = "A" .. directory .. "\n" .. packageStore - if not fs.exists(directory) then - fs.makeDirectory(directory) - end - end - end - for idx, file in ipairs(agcfg[package].files) do - clearProgress() - ::retry:: - print(" Downloading " .. file .. "...") - progress(package,idx/#agcfg[package].files) - local data, errorMessage = getFile(source .. agcfg[package].maindir .. file) - if not data then - clearProgress() - local response = read(nil, "\27[91mCould not fetch " .. file .. ": " .. errorMessage .. "\n\27[0m[a - Abort/R - Retry/s - Skip]") - if response:lower() == "a" then - fs.remove("/argentum/store/" .. package) - return false - elseif response:lower() == "s" then - goto skip - else - goto retry - end - end - if fs.exists(file) and not overwriteFlag then - if not fs.exists("/argentum/store/" .. package .. "/files/" .. file:match("(.*/)")) then - fs.makeDirectory("/argentum/store/" .. package .. "/files/" .. file:match("(.*/)")) - end - fs.copy(file, "/argentum/store/" .. package .. "/files/" .. file) - packageStore = packageStore .. "\nM" .. file - else - packageStore = packageStore .. "\nA" .. file - end - local handle = fs.open(file, "w") - handle:write(data) - handle:close() - ::skip:: - end - clearProgress() - fs.makeDirectory("/argentum/store/" .. package) - local handle = fs.open("/argentum/store/" .. package .. "/package.cfg", "w") - handle:write(packageStore) - handle:close() - return true -end - -local function removePackage(package) - print("Removing " .. package .. "...") - if not fs.exists("/argentum/store/" .. package .. "/package.cfg") then - print("\27[91mLocal Ag config of " .. package .. " does not exist.") - return false - end - local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/package.cfg", "r"), "", nil - repeat - tmpdata = handle:read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() - data = data .. "\n" - local idx = 0 - for line in data:gmatch("(.-)\n") do - idx=idx+1 - if line:sub(1, 1) == "A" then - clearProgress() - ::retry:: - print(" Removing " .. line:sub(2) .. "...") - if line:sub(-1, -1) == "/" and fs.list(line:sub(2))[1] then - print(" There are still files in " .. line:sub(2) .. ". Skipping.") - else - progress(package,idx/select(2,data:gsub("\n","\n"))) - local result, errorMessage = fs.remove(line:sub(2)) - if not result then - clearProgress() - local response = read(nil, "\27[91mFailed to remove " .. line:sub(2) .. ": " .. errorMessage .. "\n\27[0m[a - Abort/r - Retry/S - Skip]") - if response:lower() == "a" then - return false - elseif response:lower() == "r" then - goto retry - end - end - end - elseif line:sub(1, 1) == "M" then - clearProgress() - ::retry:: - print(" Reverting " .. line:sub(2) .. "...") - progress(package,idx/select(2,data:gsub("\n","\n"))) - local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/files/" .. line:sub(2), "r"), "", nil - if not handle then - clearProgress() - local response = read(nil, "\27[91mFailed to revert " .. line:sub(2) .. ": " .. data .. "\n\27[0m[a - Abort/R - Retry/s - Skip]") -- this is pretty stupid but i think the error message would get pushed to data - if response:lower() == "a" then - return false - elseif response:lower() == "s" then - goto skip - else - goto retry - end - end - repeat - tmpdata = handle:read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() - local handle = fs.open(line:sub(2), "w") - handle:write(data) - handle:close() - ::skip:: - end - end - clearProgress() - fs.remove("/argentum/store/" .. package .. "/") - return true -end - -local function updatePackage(package) - print("Updating " .. package .. "...") - local agcfg = getAgConfig(package, source) - if not agcfg then - return false - end - local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/package.cfg", "r"), "", nil - repeat - tmpdata = handle:read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() - local oldFiles = {} - for line in (data .. "\n"):gmatch("(.-)\n") do - if line:sub(1, 1) == "A" or line:sub(1, 1) == "M" then - if agcfg[package].directories then - if not table.find(agcfg[package].files, line:sub(2)) and not table.find(agcfg[package].directories, line:sub(2, -2)) then - table.insert(oldFiles, line:sub(2)) - end - else - if not table.find(agcfg[package].files, line:sub(2)) then - table.insert(oldFiles, line:sub(2)) - end - end - end - end - for _, oldFile in pairs(oldFiles) do - print(" Removing " .. oldFile .. "...") - end - return installPackage(package, true) -end - -local fails = {} -if command == "install" then - if not packages or not packages[1] then - print("Please specify packages to install.") - return - end - print("Fetching Ag registry...") - local newRegistry, errorMessage = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/argentum/registry.cfg") - if newRegistry then - local handle = fs.open("/argentum/registry.cfg", "w") - handle:write(newRegistry) - handle:close() - else - print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) - end - agReg = import("/argentum/registry.cfg") - while true do - if not doChecks(packages[i]) then - table.insert(fails, packages[i]) - table.remove(packageList, table.find(packageList, packages[i])) - end - i = i + 1 - if i > #packages then - break - end - end - local answer - if #fails == 0 then - print("Packages that will be installed: " .. table.concat(packageList, ", ")) - if read(nil, "Would you like to proceed? [Y/n] "):lower() == "n" then - return - end - elseif #packageList == 0 then - print("None of the packages can be installed.") - return - else - print("Some packages cannot be installed.") - print("Packages that will be installed: " .. table.concat(packageList, ", ")) - print("Packages that cannot be installed: " .. table.concat(fails, ", ")) - if read(nil, "Would you like to proceed? [y/N] "):lower() ~= "y" then - return - end - end - for _, failedPackage in pairs(fails) do - table.remove(packages, table.find(packages, failedPackage)) - end - fails = {} - for _, package in ipairs(packages) do - if not installPackage(package) then - table.insert(fails, package) - table.remove(packageList, table.find(packageList, package)) - end - end - if #fails == 0 then - print("Installation completed successfully.") - print("Packages installed: " .. table.concat(packageList, ", ")) - elseif #packageList == 0 then - print("All packages failed to install.") - print("Packages that could not be installed: " .. table.concat(fails, ", ")) - else - print("Some packages failed to install.") - print("Packages installed: " .. table.concat(packageList, ", ")) - print("Packages that could not be installed: " .. table.concat(fails, ", ")) - end -elseif command == "remove" then - if not packages or not packages[1] then - print("Please specify packages to remove.") - return - end - while true do - if not fs.exists("/argentum/store/" .. packages[i]) then - print("\27[91mPackage " .. packages[i] .. " is not installed.") - table.insert(fails, packages[i]) - table.remove(packageList, table.find(packageList, packages[i])) - table.remove(packages, table.find(packages, packages[i])) - i = i - 1 - elseif packages[i] == "halyde" then -- yes, this stuff is hard-coded. - print("\27[91mFor obvious reasons, you can't uninstall Halyde.") - table.insert(fails, packages[i]) - table.remove(packageList, table.find(packageList, packages[i])) - table.remove(packages, table.find(packages, packages[i])) - i = i - 1 - elseif packages[i] == "argentum" then - print("\27[91mFor obvious reasons, you can't uninstall Argentum.") - table.insert(fails, packages[i]) - table.remove(packageList, table.find(packageList, packages[i])) - table.remove(packages, table.find(packages, packages[i])) - i = i - 1 - end - i = i + 1 - if i > #packages then - break - end - end - -- do dependency checks - local packagesInstalled = fs.list("/argentum/store") - for _, currentPackage in pairs(packagesInstalled) do - if currentPackage:sub(-1, -1) == "/" and fs.exists("/argentum/store/" .. currentPackage .. "package.cfg") then - local handle, data, tmpdata = fs.open("/argentum/store/" .. currentPackage .. "package.cfg", "r"), "", nil - repeat - tmpdata = handle:read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() - for line in (data.."\n"):gmatch("(.-)\n") do - for i = 1, #packages do - if line == "D" .. packages[i] then - print(packages[i] .. " depends on " .. currentPackage:sub(1, -2)) - if not table.find(packages, currentPackage:sub(1, -2)) then - table.insert(packages, table.find(packages, packages[i]), currentPackage:sub(1, -2)) - table.insert(packageList, currentPackage:sub(1, -2)) - i = i + 1 - end - end - end - end - end - end - local answer - if #fails == 0 then - print("Packages that will be removed: " .. table.concat(packageList, ", ")) - if read(nil, "Would you like to proceed? [Y/n] "):lower() == "n" then - return - end - elseif #packageList == 0 then - print("None of the packages can be removed.") - return - else - print("Some packages cannot be removed.") - print("Packages that will be removed: " .. table.concat(packageList, ", ")) - print("Packages that cannot be removed: " .. table.concat(fails, ", ")) - if read(nil, "Would you like to proceed? [y/N] "):lower() ~= "y" then - return - end - end - for _, failedPackage in pairs(fails) do - table.remove(packages, table.find(packages, failedPackage)) - end - fails = {} - for _, package in ipairs(packages) do - if not removePackage(package) then - table.insert(fails, package) - table.remove(packageList, table.find(packageList, package)) - end - end - if #fails == 0 then - print("Removal completed successfully.") - print("Packages removed: " .. table.concat(packageList, ", ")) - elseif #packageList == 0 then - print("All packages failed to be removed.") - print("Packages that could not be removed: " .. table.concat(fails, ", ")) - else - print("Some packages failed to be removed.") - print("Packages removed: " .. table.concat(packageList, ", ")) - print("Packages that could not be removed: " .. table.concat(fails, ", ")) - end -elseif command == "update" then - print("Fetching Ag registry...") - local newRegistry, errorMessage = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/argentum/registry.cfg") - if newRegistry then - local handle = fs.open("/argentum/registry.cfg", "w") - handle:write(newRegistry) - handle:close() - else - print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) - end - agReg = import("/argentum/registry.cfg") - if not packages[1] then - local packagesInstalled = fs.list("/argentum/store/") - for _, currentPackage in pairs(packagesInstalled) do - if currentPackage:sub(-1, -1) == "/" and fs.exists("/argentum/store/" .. currentPackage .. "package.cfg") then - table.insert(packages, currentPackage:sub(1, -2)) - table.insert(packageList, currentPackage:sub(1, -2)) - end - end - end - while true do - local nonexistent = false -- I couldn't figure out a better way to do this, so I have to use a flag if the package doesn't exist - if not fs.exists("/argentum/store/" .. packages[i]) then - print("\27[91mPackage " .. packages[i] .. " is not installed.") - table.insert(fails, packages[i]) - table.remove(packageList, table.find(packageList, packages[i])) - table.remove(packages, table.find(packages, packages[i])) - i = i - 1 - nonexistent = true - end - if not nonexistent then - -- Check if up to date - local agcfg = getAgConfig(packages[i], source) - if not agcfg then - return false - end - local handle, data, tmpdata = fs.open("/argentum/store/" .. packages[i] .. "/package.cfg", "r"), "", nil - repeat - tmpdata = handle:read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() - local version = "0.0.0" - for line in (data.."\n"):gmatch("(.-)\n") do - if line:sub(1, 1) == "V" then - version = line:sub(2) - break - end - end - if agcfg[packages[i]].version == version then - table.remove(packageList, table.find(packageList, packages[i])) - table.remove(packages, table.find(packages, packages[i])) - i = i - 1 - else - print(packages[i].." is out of date [\x1b[93m"..version.."\x1b[39m < \x1b[92m"..agcfg[packages[i]].version.."\x1b[39m]") - end - end - i = i + 1 - if i > #packages then - break - end - end - local answer - if #packageList == 0 then - if #fails == 0 then - print("All packages are up to date.") - return - else - print("None of the packages can be updated.") - return - end - elseif #fails == 0 then - print("Packages that will be updated: " .. table.concat(packageList, ", ")) - if read(nil, "Would you like to proceed? [Y/n] "):lower() == "n" then - return - end - else - print("Some packages cannot be updated.") - print("Packages that will be updated: " .. table.concat(packageList, ", ")) - print("Packages that cannot be updated: " .. table.concat(fails, ", ")) - if read(nil, "Would you like to proceed? [y/N] "):lower() ~= "y" then - return - end - end - for _, failedPackage in pairs(fails) do - table.remove(packages, table.find(packages, failedPackage)) - end - fails = {} - for _, package in pairs(packages) do - -- Previous up-to-date check - - --local agcfg = getAgConfig(package, source) - --if not agcfg then - -- return false - --end - --local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/package.cfg", "r"), "", nil - --repeat - -- tmpdata = handle:read(math.huge) - -- data = data .. (tmpdata or "") - --until not tmpdata - --handle:close() - --local version = "0.0.0" - --for line in (data.."\n"):gmatch("(.-)\n") do - -- if line:sub(1, 1) == "V" then - -- version = line:sub(2) - -- break - -- end - --end - --if agcfg[package].version == version then - -- print(package .. " is up to date") - -- goto skip - --end - if not updatePackage(package) then - table.insert(fails, packages[i]) - table.remove(packageList, table.find(packageList, packages[i])) - table.remove(packages, table.find(packages, packages[i])) - goto skip - end - ::skip:: - end - if #fails == 0 then - print("Update completed successfully.") - print("Packages updated: " .. table.concat(packageList, ", ")) - elseif #packageList == 0 then - print("All packages failed to update.") - print("Packages that could not update: " .. table.concat(fails, ", ")) - else - print("Some packages failed to update.") - print("Packages updated: " .. table.concat(packageList, ", ")) - print("Packages that could not update: " .. table.concat(fails, ", ")) - end -elseif command == "info" then - if not packages[1] then - print("Please specify a package to show information about.") - return - end - print("Fetching Ag registry...") - local newRegistry, errorMessage = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/argentum/registry.cfg") - if newRegistry then - local handle = fs.open("/argentum/registry.cfg", "w") - handle:write(newRegistry) - handle:close() - else - print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) - end - agReg = import("/argentum/registry.cfg") - if not agReg[packages[1]] and not source then - print("\27[91mPackage " .. packages[1] .. " does not exist.") - return - end - local agcfg = getAgConfig(packages[1], source) - if not agcfg then - return false - end - print("\27[93m" .. packages[1] .. "\27[0m v" .. agcfg[packages[1]].version .. "\n " .. (agcfg[packages[1]].description or "No description."):gsub("\n", " \n")) -elseif command == "search" then - if not packages[1] then - print("Please specify a search term.") - return - end - print("Fetching Ag registry...") - local newRegistry, errorMessage = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/argentum/registry.cfg") - if newRegistry then - local handle = fs.open("/argentum/registry.cfg", "w") - handle:write(newRegistry) - handle:close() - else - print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) - end - agReg = import("/argentum/registry.cfg") - local searchResults = {} - for packageName, _ in pairs(agReg) do - if packageName:find(packages[1], 1, true) then - table.insert(searchResults, packageName) - end - end - if not searchResults[1] then - print("No search results found for " .. packages[1] .. ".") - return - end - table.sort(searchResults) - print("Search results: \n " .. table.concat(searchResults, "\n ")) -elseif command == "list" then - print("Fetching Ag registry...") - local newRegistry, errorMessage = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/argentum/registry.cfg") - if newRegistry then - local handle = fs.open("/argentum/registry.cfg", "w") - handle:write(newRegistry) - handle:close() - else - print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) - end - agReg = import("/argentum/registry.cfg") - local sortedPackages = {} - for packageName, _ in pairs(agReg) do - table.insert(sortedPackages, packageName) - end - table.sort(sortedPackages) - print("List of available Ag packages: \n " .. table.concat(sortedPackages, "\n ")) -else - shell.run("help ag") -end +Error: no such file. (``) diff --git a/halyde/apps/boot.lua b/halyde/apps/boot.lua index d08ef3d..fddefd5 100644 --- a/halyde/apps/boot.lua +++ b/halyde/apps/boot.lua @@ -1,60 +1 @@ -local component = import("component") -local computer = import("computer") -local args = {...} - -local force = false - -local forceArgIdx = table.find(args,"-f") or table.find(args,"--force") -if forceArgIdx then - table.remove(args,forceArgIdx) - force = true -end - -local function getComponentID(str) - local function fromSlot(slot) - for i,v in component.list() do - if component.slot(i)==slot then - return i - end - end - end - if str=="hdd1" or str=="#1" then return fromSlot(5) end - if str=="hdd2" or str=="#2" then return fromSlot(6) end - if str=="floppy" or str=="#3" then return fromSlot(7) end - - if #str<3 then return nil,"Abbreviated ID must atleast have 3 characters" end - return component.get(str) -end - -local function fileExists(compID,file) - return component.invoke(compID,"exists",file) and not component.invoke(compID,"isDirectory",file) -end - -if type(args[1])=="string" then - local compID,err = getComponentID(args[1]) - if not compID then - print("\x1b[91mCould not get component ID from '"..args[1].."'.") - if type(err)=="string" then print("\x1b[91m"..err) end - return - end - if not force then - if componentlib.additions[compID] then - return print("\x1b[91mThis component is virtual and cannot be booted from directly.\nID: "..compID) - end - local type = component.type(compID) - if type~="filesystem" and type~="drive" then - return print("\x1b[91mThis component is not a storage medium.\nID: "..compID) - end - if type=="filesystem" and not fileExists(compID,"/init.lua") then - return print("\x1b[91mThis storage medium doesn't have an \"init.lua\" file.\nID: "..compID) - end - end - - computer.setBootAddress(compID) - if computer.getBootAddress()~=compID then - return print("\x1b[91mFailed to set the boot address.") - end - computer.shutdown(true) -else - shell.run("help boot") -end +Error: no such file. (``) diff --git a/halyde/apps/cat.lua b/halyde/apps/cat.lua index 1c5dc93..fddefd5 100644 --- a/halyde/apps/cat.lua +++ b/halyde/apps/cat.lua @@ -1,20 +1 @@ -local files = {...} -local fs = import("filesystem") -if not files or not files[1] then - shell.run("help cat") - return -end -for _, file in ipairs(files) do - if file:sub(1, 1) ~= "/" then - file = fs.concat(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) - termlib.write(data) - until not data -end +Error: no such file. (``) diff --git a/halyde/apps/cd.lua b/halyde/apps/cd.lua index 72aee9e..fddefd5 100644 --- a/halyde/apps/cd.lua +++ b/halyde/apps/cd.lua @@ -1,14 +1 @@ -local directory = ... -local fs = import("filesystem") - -if not directory then - return -end -if directory:sub(1, 1) ~= "/" then - directory = fs.concat(shell.workingDirectory, directory) -end -if fs.exists(directory) and fs.isDirectory(directory) then - shell.workingDirectory = fs.canonical(directory) -else - print("\27[91mNo such directory.") -end +Error: no such file. (``) diff --git a/halyde/apps/clear.lua b/halyde/apps/clear.lua index 12b9b4e..fddefd5 100644 --- a/halyde/apps/clear.lua +++ b/halyde/apps/clear.lua @@ -1,2 +1 @@ -clear() --- truly so much going on here +Error: no such file. (``) diff --git a/halyde/apps/cp.lua b/halyde/apps/cp.lua index ecd1316..fddefd5 100644 --- a/halyde/apps/cp.lua +++ b/halyde/apps/cp.lua @@ -1,26 +1 @@ -local fromFile, toFile = ... -local fs = import("filesystem") - -if not fromFile or not toFile then - shell.run("help cp") - return -end -if fromFile:sub(1, 1) ~= "/" then - fromFile = fs.concat(shell.workingDirectory, fromFile) -end -if toFile:sub(1, 1) ~= "/" then - toFile = fs.concat(shell.workingDirectory, toFile) -end -if fromFile == toFile then - print("\27[91mSource and destination are the same.") - return -end -if not fs.exists(fromFile) then - print("\27[91mSource file does not exist.") - return -end -if fs.exists(toFile) and not (table.find({...}, "-o") or table.find({...}, "--overwrite")) then - print("\27[91mDestination file already exists. Run this command again with -o to overwrite it.") - return -end -fs.copy(fromFile, toFile) +Error: no such file. (``) diff --git a/halyde/apps/download.lua b/halyde/apps/download.lua index 96fdd5b..fddefd5 100644 --- a/halyde/apps/download.lua +++ b/halyde/apps/download.lua @@ -1,57 +1 @@ -local url = ... - -local component = import("component") -local fs = import("filesystem") - -if not component.list("internet")() then - print("\27[91mThis program requires an internet card to run.") - return -end - -if not url then - print("Please enter a URL to download from.") - shell.run("help download") - return -end - -if url:sub(-1, -1) == "/" then - url = url:sub(1, -2) -end - -local internet = component.internet - -local request, data, tmpdata = nil, "", nil -local status, errorMessage = pcall(function() - request = internet.request(url) - request:finishConnect() -end) -if not status then - print("\27[91mDownload failed: " .. errorMessage) -end -local responseCode = request:response() -if responseCode and responseCode ~= 200 then - print("\27[91mDownload failed: " .. tostring(responseCode)) -end -repeat - tmpdata = request.read(math.huge) - data = data .. (tmpdata or "") -until not tmpdata -local saveLocation -local saveLocationOK = false -repeat - saveLocation = read(nil, "File save location: ", fs.concat(shell.workingDirectory, url:match("/([^/]+)$"))) - if fs.isDirectory(saveLocation) then - print("\27[91mThe specified location is a directory.") - elseif fs.exists(saveLocation) then - local answer = read(nil, "\27[91mThere is already a file at the specified directory. Overwrite it? [Y/n]") - if answer:lower() ~= "n" then - saveLocationOK = true - end - else - saveLocationOK = true - end -until saveLocationOK -local handle = fs.open(saveLocation, "w") -handle:write(data) -handle:close() -print("File downloaded successfully.") +Error: no such file. (``) diff --git a/halyde/apps/echo.lua b/halyde/apps/echo.lua index 97b1171..fddefd5 100644 --- a/halyde/apps/echo.lua +++ b/halyde/apps/echo.lua @@ -1,7 +1 @@ -local args = {...} -local concatText = args[1] -table.remove(args, 1) -for _, item in pairs(args) do - concatText = concatText .. " " .. item -end -print(concatText) +Error: no such file. (``) diff --git a/halyde/apps/edit.lua b/halyde/apps/edit.lua index 467a5cf..fddefd5 100644 --- a/halyde/apps/edit.lua +++ b/halyde/apps/edit.lua @@ -1,351 +1 @@ -local file = ... -local fs = import("filesystem") -local event = import("event") -local component = import("component") -local unicode = import("unicode") -local gpu = component.gpu -local width, height = gpu.getResolution() -local scrollPosX, scrollPosY = 1, 1 -local cursorPosX, cursorPosY = 1, 1 -local cursorWhite = true -local changesMade = false -local renderBuffer = gpu.allocateBuffer() -local scrollSpeed = 5 -local tab = " " ---local ocelot = component.ocelot - -local function rawset(x, y, text) - termlib.cursorPosX = x - termlib.cursorPosY = y - termlib.write(text, false) -end - -local filestring, filepath, handle, data, tmpdata -if file then - if file:sub(1, 1) == "/" then - filepath = file - else - filepath = shell.workingDirectory .. file - end - handle, data, tmpdata = fs.open(filepath, "r"), "", nil - if fs.exists(filepath) then - filestring = filepath - repeat - tmpdata = handle:read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - tmpdata = {} - if data:gmatch("(.-)\n")() then - for line in data:gmatch("(.-)\n") do - local newLine = line:gsub("\r", "") -- this took me SO LONG TO FIGURE OUT AAAAAAAA I HATE CRLF I HATE CRLF I HATE CRLF - table.insert(tmpdata, newLine) - end - else - tmpdata = {data} - end - else - filepath = shell.workingDirectory .. file - filestring = "[NEW FILE]" - tmpdata = {""} - end -else - filepath = "" - filestring = "[NEW FILE]" - tmpdata = {""} -end -local function render() - gpu.setActiveBuffer(renderBuffer) - clear() - --ocelot.log(tostring(scrollPosY)) - local realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2) - if realCursorX < 1 then - scrollPosX = scrollPosX + realCursorX - 1 - cursorPosX = 1 - realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2) - end - for i = scrollPosY, height + scrollPosY - 3 do - gpu.set(1, i - scrollPosY + 1, (tmpdata[i] or ""):sub(scrollPosX)) - end - rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width)) - rawset(1, height, "\27[107m\27[30m^X\27[0m Exit \27[107m\27[30m^S\27[0m Save" .. string.rep(" ", width)) - local char = gpu.get(realCursorX, cursorPosY) - if cursorWhite then - gpu.setForeground(0) - gpu.setBackground(0xFFFFFF) - end - gpu.set(realCursorX, cursorPosY, char) - gpu.bitblt() - gpu.setActiveBuffer(0) -end - -local renderFlag, cursorRenderFlag = false, false - -local function scrollUp() - cursorPosY = cursorPosY - 1 - cursorRenderFlag = true - cursorWhite = true - if cursorPosY < 1 then - renderFlag = true - scrollPosY = scrollPosY - 1 - cursorPosY = 1 - end - if scrollPosY < 1 then - renderFlag = false - scrollPosY = 1 - end - if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2) < 1 then - renderFlag = true - end -end - -local function scrollDown() - cursorPosY = cursorPosY + 1 - cursorRenderFlag = true - cursorWhite = true - if cursorPosY + scrollPosY - 1 > #tmpdata then - renderFlag = false - cursorPosY = #tmpdata - scrollPosY + 1 - end - if cursorPosY > height - 2 then - renderFlag = true - scrollPosY = scrollPosY + 1 - cursorPosY = height - 2 - end - if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2) < 1 then - renderFlag = true - end -end - -local function scrollLeft() - cursorRenderFlag = true - cursorWhite = true - if cursorPosX > 1 then - if cursorPosX <= unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2 then - cursorPosX = cursorPosX - 1 - elseif unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 1 > 1 then - cursorPosX = unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 1 - end - elseif scrollPosX > 1 then - scrollPosX = scrollPosX - 1 - renderFlag = true - end - if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2) < 1 then - renderFlag = true - end -end - -local function scrollRight() - cursorRenderFlag = true - cursorWhite = true - if cursorPosX <= unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 1 then - cursorPosX = cursorPosX + 1 - end - if cursorPosX > width then - cursorPosX = width - scrollPosX = scrollPosX + 1 - renderFlag = true - end -end - -local function processEvent(args) - renderFlag, cursorRenderFlag = false, false - if args[1] == "key_down" then - local keycode = args[4] - local key = keyboard.keys[keycode] - if keyboard.ctrlDown then - return false, false, key - end - if key == "down" and cursorPosY < #tmpdata then - scrollDown() - end - if key == "up" then - scrollUp() - end - if key == "left" then - scrollLeft() - end - if key == "right" then - scrollRight() - end - if key == "enter" then - changesMade = true - renderFlag = true - cursorWhite = true - table.insert(tmpdata, cursorPosY + 1, tmpdata[cursorPosY + scrollPosY - 1]:sub(cursorPosX)) - tmpdata[cursorPosY + scrollPosY - 1] = tmpdata[cursorPosY + scrollPosY - 1]:sub(1, cursorPosX - 1) - cursorPosX = 1 - cursorPosY = cursorPosY + 1 - scrollPosX = 1 - if cursorPosY > height - 2 then - scrollPosY = scrollPosY + 1 - cursorPosY = height - 2 - end - end - if key == "back" then - changesMade = true - cursorRenderFlag = true - cursorWhite = true - if cursorPosX == 1 and cursorPosY + scrollPosY - 1 > 1 then - cursorPosY = cursorPosY - 1 - if cursorPosY < 1 then - scrollPosY = scrollPosY - 1 - cursorPosY = 1 - end - if scrollPosY < 1 then - scrollPosY = 1 - end - cursorPosX = unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2 - if cursorPosX > width then - scrollPosX = cursorPosX - width + 1 - cursorPosX = width - end - tmpdata[cursorPosY + scrollPosY - 1] = tmpdata[cursorPosY + scrollPosY - 1] .. tmpdata[cursorPosY + 1] - table.remove(tmpdata, cursorPosY + 1) - renderFlag = true - else - tmpdata[cursorPosY + scrollPosY - 1] = tmpdata[cursorPosY + scrollPosY - 1]:sub(1, cursorPosX + scrollPosX - 3) .. tmpdata[cursorPosY + scrollPosY - 1]:sub(cursorPosX + scrollPosX - 1) - cursorPosX = math.min(cursorPosX - 1, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) + 1) - if cursorPosX < 1 then - cursorPosX = 1 - scrollPosX = scrollPosX - 1 - renderFlag = true - else - gpu.set(1, cursorPosY, tmpdata[cursorPosY + scrollPosY - 1]:sub(scrollPosX) .. " ") - end - end - end - if key == "tab" then - changesMade = true - cursorRenderFlag = true - cursorWhite = true - tmpdata[cursorPosY + scrollPosY - 1] = tmpdata[cursorPosY + scrollPosY - 1]:sub(1, cursorPosX + scrollPosX - 2) .. tab .. tmpdata[cursorPosY + scrollPosY - 1]:sub(cursorPosX + scrollPosX - 1) - cursorPosX = cursorPosX + unicode.wlen(tab) - if cursorPosX > width then - scrollPosX = scrollPosX + cursorPosX - width - cursorPosX = width - renderFlag = true - else - gpu.set(1, cursorPosY, tmpdata[cursorPosY + scrollPosY - 1]:sub(scrollPosX)) - end - end - if args[3] >= 32 and args[3] <= 126 then - changesMade = true - cursorRenderFlag = true - cursorWhite = true - tmpdata[cursorPosY + scrollPosY - 1] = tmpdata[cursorPosY + scrollPosY - 1]:sub(1, cursorPosX + scrollPosX - 2) .. unicode.char(args[3]) .. tmpdata[cursorPosY + scrollPosY - 1]:sub(cursorPosX + scrollPosX - 1) - cursorPosX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1])) + 1 - --ocelot.log(tostring(cursorPosX)) - if cursorPosX > width then - cursorPosX = width - scrollPosX = scrollPosX + 1 - renderFlag = true - else - gpu.set(1, cursorPosY, tmpdata[cursorPosY + scrollPosY - 1]:sub(scrollPosX)) - end - end - elseif args[1] == "scroll" then - if args[5] == 1 then - for i = 1, scrollSpeed do - scrollUp() - end - elseif args[5] == -1 and cursorPosY < #tmpdata then - for i = 1, scrollSpeed do - scrollDown() - end - end - end - return renderFlag, cursorRenderFlag -end - -local function save() - gpu.setBackground(0xFFFFFF) - gpu.setForeground(0) - gpu.set(1, height - 1, string.rep(" ", width)) - termlib.cursorPosX = 1 - termlib.cursorPosY = height - 1 - local savepath = read(nil, "\27[107m\27[30mSave location: ", filepath) - gpu.setBackground(0xFFFFFF) - gpu.setForeground(0) - if fs.exists(savepath) then - gpu.set(1, height - 1, string.rep(" ", width)) - local answer = read(nil, "\27[107m\27[30mFile already exists. Overwrite it? [Y/n] ") - if answer:lower() == "n" then - gpu.setBackground(0xFFFFFF) - gpu.setForeground(0) - gpu.set(1, height - 1, filestring .. string.rep(" ", width)) - return - end - end - local handle, errorMessage = fs.open(savepath, "w") - if handle then - if table.concat(tmpdata, "\n"):sub(-1, -1) == "\n" then - handle:write(table.concat(tmpdata, "\n")) - else - handle:write(table.concat(tmpdata, "\n") .. "\n") -- add a newline at the end to follow POSIX standards - end - handle:close() - gpu.set(1, height - 1, filestring .. string.rep(" ", width)) - else - gpu.set(1, height - 1, "ERROR: " .. errorMessage:gsub("\n", "") .. string.rep(" ", width)) - end - changesMade = false -end - -render() -while true do - local args = {event.pull(0.5)} - local renderFlag, cursorRenderFlag, specialKey = false, false, nil - local previousCursorX, previousCursorY = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2), cursorPosY - if args and args[1] then - cursorWhite = true - renderFlag, cursorRenderFlag, specialKey = processEvent(args) - if specialKey == "x" then - if changesMade then - termlib.cursorPosX = 1 - termlib.cursorPosY = height - 1 - local response = read(nil, "\27[107m\27[30mWould you like to save changes? [Y/n] ") - if response:lower() ~= "n" then - save() - end - end - gpu.freeAllBuffers() - clear() - return - end - if specialKey == "s" then - save() - end - repeat - args = {event.pull("key_down", 0)} - if args and args[1] then - processEvent(args) - end - until not args or not args[1] - else - cursorWhite = not cursorWhite - cursorRenderFlag = true - end - if cursorRenderFlag then - local char = gpu.get(previousCursorX, previousCursorY) - gpu.set(previousCursorX, previousCursorY, char) - local realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2) - if realCursorX < 1 then - scrollPosX = scrollPosX + realCursorX - 1 - cursorPosX = 1 - realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY + scrollPosY - 1]) - scrollPosX + 2) - end - local char = gpu.get(realCursorX, cursorPosY) - if cursorWhite then - gpu.setBackground(0xFFFFFF) - gpu.setForeground(0) - end - gpu.set(realCursorX, cursorPosY, char) - if cursorWhite then - gpu.setForeground(0xFFFFFF) - gpu.setBackground(0) - end - end - if renderFlag then - render() - end -end +Error: no such file. (``) diff --git a/halyde/apps/fetch.lua b/halyde/apps/fetch.lua index add0a0d..fddefd5 100644 --- a/halyde/apps/fetch.lua +++ b/halyde/apps/fetch.lua @@ -1,70 +1 @@ -local component = import("component") -local computer = import("computer") - -local function printstat(text) - termlib.cursorPosX = 35 - termlib.write(text .. "\n", false) -end - -termlib.write(_OSLOGO, false) -termlib.cursorPosY = termlib.cursorPosY - 17 -printstat("\27[92mOS\27[0m: ".._OSVERSION) -printstat("\27[92mArchitecture\27[0m: ".._VERSION) -local componentCounter = 0 -for _, _ in component.list() do - componentCounter = componentCounter + 1 -end -printstat("\27[92mComponents\27[0m: "..tostring(componentCounter)) -printstat("\27[92mCoroutines\27[0m: "..tostring(#cormgr.corList)) -printstat("\27[92mBattery\27[0m: "..tostring(math.floor(computer.energy() / computer.maxEnergy() * 1000 + 0.5) / 10).."%") -local totalMemory = computer.totalMemory() -local usedMemory = computer.totalMemory() - computer.freeMemory() -local totalMemoryString -if convert(totalMemory, "B", "GiB") >= 1 then - totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "GiB") * 100 + 0.5) / 100) .. " GiB" -elseif convert(totalMemory, "B", "MiB") >= 1 then - totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "MiB") * 100 + 0.5) / 100) .. " MiB" -elseif convert(totalMemory, "B", "KiB") >= 1 then - totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "KiB") * 100 + 0.5) / 100) .. " KiB" -else - totalMemoryString = tostring(totalMemory) .. " B" -end -local usedMemoryString -if convert(usedMemory, "B", "GiB") >= 1 then - usedMemoryString = tostring(math.floor(convert(usedMemory, "B", "GiB") * 100 + 0.5) / 100) .. " GiB" -elseif convert(usedMemory, "B", "MiB") >= 1 then - usedMemoryString = tostring(math.floor(convert(usedMemory, "B", "MiB") * 100 + 0.5) / 100) .. " MiB" -elseif convert(usedMemory, "B", "KiB") >= 1 then - usedMemoryString = tostring(math.floor(convert(usedMemory, "B", "KiB") * 100 + 0.5) / 100) .. " KiB" -else - usedMemoryString = tostring(usedMemory) .. " B" -end -printstat("\27[92mMemory\27[0m: "..usedMemoryString.." / "..totalMemoryString) -local totalDisk = component.invoke(computer.getBootAddress(), "spaceTotal") -local usedDisk = component.invoke(computer.getBootAddress(), "spaceUsed") -local totalDiskString -if convert(totalDisk, "B", "GiB") >= 1 then - totalDiskString = tostring(math.floor(convert(totalDisk, "B", "GiB") * 100 + 0.5) / 100) .. " GiB" -elseif convert(totalDisk, "B", "MiB") >= 1 then - totalDiskString = tostring(math.floor(convert(totalDisk, "B", "MiB") * 100 + 0.5) / 100) .. " MiB" -elseif convert(totalDisk, "B", "KiB") >= 1 then - totalDiskString = tostring(math.floor(convert(totalDisk, "B", "KiB") * 100 + 0.5) / 100) .. " KiB" -else - totalDiskString = tostring(totalDisk) .. " B" -end -local usedDiskString -if convert(usedDisk, "B", "GiB") >= 1 then - usedDiskString = tostring(math.floor(convert(usedDisk, "B", "GiB") * 100 + 0.5) / 100) .. " GiB" -elseif convert(usedDisk, "B", "MiB") >= 1 then - usedDiskString = tostring(math.floor(convert(usedDisk, "B", "MiB") * 100 + 0.5) / 100) .. " MiB" -elseif convert(usedDisk, "B", "KiB") >= 1 then - usedDiskString = tostring(math.floor(convert(usedDisk, "B", "KiB") * 100 + 0.5) / 100) .. " KiB" -else - usedDiskString = tostring(usedDisk) .. " B" -end -printstat("\27[92mDisk\27[0m: "..usedDiskString.." / "..totalDiskString) -local width, height = component.invoke(component.list("gpu")(), "getResolution") -printstat("\27[92mResolution\27[0m: "..tostring(width).."x"..tostring(height).."\n") -printstat("\27[40m \27[41m \27[42m \27[43m \27[44m \27[45m \27[46m \27[47m ") -printstat("\27[100m \27[101m \27[102m \27[103m \27[104m \27[105m \27[106m \27[107m ") -termlib.cursorPosY = termlib.cursorPosY + 5 +Error: no such file. (``) diff --git a/halyde/apps/help.lua b/halyde/apps/help.lua index 47cd216..fddefd5 100644 --- a/halyde/apps/help.lua +++ b/halyde/apps/help.lua @@ -1,38 +1 @@ -local fs = import("filesystem") -local args = {...} -local command = args[1] -args = nil -if not command then - local handle, data, tmpdata = fs.open("/halyde/apps/helpdb/default.txt", "r"), "", nil - repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") - until not tmpdata - print(data) - return -end -if shell.aliases[command] then - command = shell.aliases[command] -end -if fs.exists("/halyde/apps/helpdb/" .. command .. ".txt") then - local handle, data, tmpdata = fs.open("/halyde/apps/helpdb/" .. command .. ".txt", "r"), "", nil - repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") - until not tmpdata - print(data) - local aliases = table.copy(shell.aliases) - if table.find(aliases, command) then - local aliasIndex = table.find(aliases, command) - local aliasString = "Aliases:\n " .. aliasIndex - aliases[aliasIndex] = nil - while table.find(aliases, command) do - aliasIndex = table.find(aliases, command) - aliasString = aliasString .. ", " .. aliasIndex - aliases[aliasIndex] = nil - end - print(aliasString) - end -else - print("Could not find help file for: " .. command .. ".") -end +Error: no such file. (``) diff --git a/halyde/apps/label.lua b/halyde/apps/label.lua index 0c12ee4..fddefd5 100644 --- a/halyde/apps/label.lua +++ b/halyde/apps/label.lua @@ -1,92 +1 @@ -local component = import("component") -local computer = import("computer") -local args = {...} -if not args then return print("\x1b[91mCannot get arguments.") end -if not args[1] then - return shell.run("help label") -end -local inputID = args[1] -local comp - -local function componentFromSlot(slotNum) - if slotNum>=5 and slotNum<=8 then slotNum=slotNum-1 end - for i,v in component.list() do - if component.slot(i)==slotNum then - comp=component.proxy(i) - end - end -end - -if inputID=="eeprom" then - comp = component.eeprom -elseif inputID=="halyde" then - comp = component.proxy(computer.getBootAddress()) -elseif inputID:sub(1,4)=="slot" and tonumber(inputID:sub(5)) then - local slotNum = tonumber(inputID:sub(5))-1 - componentFromSlot(slotNum) -elseif inputID:sub(1,1)=="#" and tonumber(inputID:sub(2)) then - local slotNum = tonumber(inputID:sub(2))+5 - componentFromSlot(slotNum) -elseif #inputID>=3 then - local fullID = component.get(inputID) - if not fullID then return print("\x1b[91mCould not find entire component ID from \""..inputID.."\".") end - comp = component.proxy(fullID) -else - print("\x1b[91mAddress must have atleast 3 characters") - return shell.run("help label") -end -if not comp then - return print("\x1b[91mCould not find component from \""..inputID.."\".") -end -local compID = comp.address - -local function formatID(id) - return id:sub(1,8).."\x1b[37m"..id:sub(9).."\x1b[39m" -end - -local function unsupported(act) - print("This \x1b[92m"..(comp.type or "unknown").."\x1b[39m component doesn't support "..act.." labels.\nID: "..formatID(compID)) -end - -local function compError(act,reason) - print("\x1b[91mAn error occured while "..act.." the label of this component.\nComponent: "..(compID or "unknown id").." ("..((comp or {}).type or "unknown type")..")\n\n"..reason) -end - -local function formatLabel(label) - local res = "No label defined" - if label then res="\""..label.."\"" end - return res -end - -if type(args[2])~="string" then - if not comp.getLabel then - return unsupported("getting") - end - local label - local success,reason = pcall(function() - label = comp.getLabel() - end) - if success then - print("Label of "..formatID(compID)..((comp.type and comp.type~="filesystem") and " ("..comp.type..")" or "")..":\n \x1b[92m"..formatLabel(label).."\x1b[39m") - else - compError("getting",reason) - end -else - if not comp.setLabel then - return unsupported("setting") - end - local newLabel = "" - for i=2,#args do - newLabel=newLabel..tostring(args[i]) - if i<#args then newLabel=newLabel.." " end - end - local label - local success,reason = pcall(function() - label = comp.setLabel(newLabel) - end) - if success then - print("Successfully set label of "..formatID(compID)..(comp.type and " ("..comp.type..")" or "").." to:\n \x1b[92m"..formatLabel(label).."\x1b[39m") - else - compError("setting",reason) - end -end +Error: no such file. (``) diff --git a/halyde/apps/ls.lua b/halyde/apps/ls.lua index f7149b8..fddefd5 100644 --- a/halyde/apps/ls.lua +++ b/halyde/apps/ls.lua @@ -1,70 +1 @@ -local args = {...} -local target = args[1] -args = nil -local fs = import("filesystem") -local unicode = import("unicode") -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 = fs.concat(shell.workingDirectory, target) - end -else - target = shell.workingDirectory -end - -local files = fs.list(target) - -if files then - 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 - 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(fs.concat(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 -end +Error: no such file. (``) diff --git a/halyde/apps/lscor.lua b/halyde/apps/lscor.lua index ffe3495..fddefd5 100644 --- a/halyde/apps/lscor.lua +++ b/halyde/apps/lscor.lua @@ -1,9 +1 @@ -print("\27[93m"..tostring(#cormgr.corList).."\27[0m coroutines active") -for i=1, #cormgr.corList do - if i==#cormgr.corList then - print("\27[93m└ "..i.."\27[0m - "..cormgr.labelList[i].." \27[0m") - else - print("\27[93m├ "..i.."\27[0m - "..cormgr.labelList[i].." \27[0m") - end - -end +Error: no such file. (``) diff --git a/halyde/apps/lsdrv.lua b/halyde/apps/lsdrv.lua index 55133fb..fddefd5 100644 --- a/halyde/apps/lsdrv.lua +++ b/halyde/apps/lsdrv.lua @@ -1,320 +1 @@ -local serialize = import("serialize") -local component = import("component") -local computer = import("computer") -local unicode = import("unicode") - -local width,height = component.gpu.getResolution() - -local args = {...} -local showAll = not not (table.find(args,"-a") or table.find(args,"--all")) - -local tablePos = {} -local tableOut = {} -local headers = { - ["slot"]="SLOT", - ["capacity"]="CAPACITY", - ["managed"]="MANAGED", - ["readOnly"]="READ-ONLY", - ["id"]="FULL COMPONENT ID", - ["mount"]="MOUNT", - ["bootable"]="BOOTABLE", - ["label"]="LABEL" -} -local headerAlign = { - ["slot"]=false, - ["capacity"]=true, - ["managed"]=false, - ["readOnly"]=false, - ["id"]=false, - ["mount"]=false, - ["bootable"]=false, - ["label"]=false -} -local function addHeader(id) - table.insert(tableOut,{headerAlign[id],headers[id]}) - tablePos[id]=#tableOut -end -for i,v in pairs(tablePos) do print(i,v) end - -local function everyHeader() - addHeader("slot") - addHeader("capacity") - addHeader("managed") - addHeader("readOnly") - addHeader("id") - addHeader("mount") - addHeader("bootable") - addHeader("label") -end - -local function defaultHeaders() - if width>100 then addHeader("slot") end - addHeader("capacity") - if width>80 then addHeader("id") end - addHeader("mount") - addHeader("label") -end - -local function invalidArgSyntax(err) - print(err) - return shell.run("help lsdrv") -end - -local outArgIdx = table.find(args,"-o") or table.find(args,"--output") -if showAll then - everyHeader() -elseif outArgIdx then - table.remove(args,outArgIdx) - local arg = table.remove(args,outArgIdx) - if not arg then return invalidArgSyntax("Argument -o must have a value") end - if arg=="all" then - everyHeader() - else - if arg:sub(1,1)=="+" then - defaultHeaders() - end - for word in string.gmatch(arg:sub(2),"([^,]+)") do - if headers[word] then - addHeader(word) - else - print("\x1b[93mCategory \""..word.."\" doesn't exist\x1b[39m") - end - end - end -else - defaultHeaders() -end - -local function headerUsed(id) - return not not tablePos[id] -end - -local bibytes = not (table.find(args,"-H") or table.find(args,"--si")) -local function formatSize(mem) - local units = bibytes and {"B","KiB","MiB","GiB"} or {"B","KB","MB","GB"} - local unit = 1 - local unitStep = bibytes and 1024 or 1000 - while mem > unitStep and units[unit] do - unit = unit + 1 - mem = mem/unitStep - end - local memStr = tostring(mem):sub(1,5) - if unicode.sub(memStr,-2)==".0" then - memStr=unicode.sub(memStr,1,-3) - end - return memStr.." "..units[unit] -end - -local function fileExists(proxy,path) - return proxy.exists(path) and not proxy.isDirectory(path) -end - -local function getBootCode(proxy) - local sector1 = proxy.readSector(1) - for i = 1,#sector1 do - if sector1:sub(i,i)=="\0" then - sector1 = sector1:sub(1,i-1) - break - end - end - return sector1 -end - -local function isBootable(proxy,type) - if type=="drive" then - return not not load(getBootCode(proxy)) - elseif type=="filesystem" then - return not not (fileExists(proxy,"/init.lua") or fileExists(proxy,"/OS.lua")) - end -end - -local function formatBoolean(bool) - return ({[true]="Yes",[false]="No"})[bool] -end - -local function handleComponent(id,type) - if not id then return end - local proxy = component.proxy(id) - if not proxy then return end - -- local out = {} - -- for i=1,#tableOut do table.insert(out,"unknown") end - local slot,capacity,managed,readOnly,mount,bootable,label - - local cslot = component.slot(id) - if cslot==-1 then - slot="Virtual" - elseif cslot==9 then - slot="EEPROM" - else - slot="#"..(cslot+2) - end - - managed="Yes" - readOnly="No" - if type=="drive" then - managed="No" - capacity=formatSize(proxy.getCapacity()) - mount="/special/drive/"..id:sub(1,3) - elseif type=="filesystem" then - capacity=formatSize(proxy.spaceTotal()) - if proxy.isReadOnly() then - readOnly="Yes" - end - mount="/mnt/"..id:sub(1,3) - if computer.getBootAddress()==id then mount="/" end - if computer.tmpAddress()==id then - mount="/tmp" - slot="Temporary" - end - elseif type=="eeprom" then - capacity=formatSize(proxy.getSize()+proxy.getDataSize()) - mount="/special/eeprom/" - end - - if headerUsed("bootable") then - bootable = formatBoolean(isBootable(proxy,type)) - end - - if proxy.getLabel then - local clabel = proxy.getLabel() - label=clabel and serialize.string(clabel) or "None" - else - label="Unsupported" - end - - local function insertElement(i,v) - if not tablePos[i] then return end - table.insert(tableOut[tablePos[i]],v or "unknown") - end - insertElement("slot",slot) - insertElement("capacity",capacity) - insertElement("managed",managed) - insertElement("readOnly",readOnly) - insertElement("id",id) - insertElement("mount",mount) - insertElement("bootable",bootable) - insertElement("label",label) -end - -local function filter(tbl,test) - local i=1 - while i<=#tbl do - if not test(tbl[i]) then - table.remove(tbl,i) - i=i-1 - end - i=i+1 - end -end - -local function luaExpr(arg) - local func,err = load("local component,computer,type,id,readonly,capacity=... local managed,eeprom,halyde,tmp,proxy,slot,all=type==\"drive\",type==\"eeprom\",id==\""..computer.getBootAddress().."\",id==\""..computer.tmpAddress().."\",component.proxy(id),component.slot(id)+2,true return "..arg) - if func then - return function(comp) - local readOnly,capacity=false,nil - if comp[2]=="filesystem" then - readOnly=component.invoke(comp[1],"isReadOnly") - capacity=component.invoke(comp[1],"spaceTotal") - elseif comp[2]=="drive" then - capacity=component.invoke(comp[1],"getCapacity") - elseif comp[2]=="eeprom" then - capacity=component.invoke(comp[1],"getSize")+component.invoke(comp[1],"getDataSize") - end - return func(component,computer,comp[2],comp[1],readOnly,capacity) - end - else - return nil,err - end -end - -local function boolToNum(val) - if type(val)=="boolean" then - if val then - return 1 - else - return 0 - end - end - return val -end - -local comps = {} -for i,v in component.list("filesystem") do table.insert(comps,{i,v}) end -for i,v in component.list("drive") do table.insert(comps,{i,v}) end -for i,v in component.list("eeprom") do table.insert(comps,{i,v}) end - -if not showAll then - local showArgIdx = table.find(args,"-s") or table.find(args,"--show") - if showArgIdx then - table.remove(args,showArgIdx) - local arg = table.remove(args,showArgIdx) - if not arg then return invalidArgSyntax("Argument -s must have a value") end - local func,err = luaExpr(arg) - if func then - filter(comps,func) - else - return print("\x1b[91mInvalid component filter:\n\n"..tostring(err).."\x1b[39m") - end - else - filter(comps,function(comp) - return comp[2]~="eeprom" and comp[1]~=computer.tmpAddress() - end) - end -end - -local sortArgIdx = table.find(args,"-S") or table.find(args,"--sort") -if sortArgIdx then - table.remove(args,sortArgIdx) - local arg = table.remove(args,sortArgIdx) - if not arg then return invalidArgSyntax("Argument -S must have a value") end - local func,err = luaExpr(arg) - if func then - table.sort(comps,function(a,b) - return (boolToNum(func(a)) or 0)<(boolToNum(func(b)) or 0) - end) - else - return print("\x1b[91mInvalid sort expression:\n\n"..tostring(err).."\x1b[39m") - end -else - table.sort(comps,function(a,b) - return a[1]0 then - for i,v in ipairs(comps) do handleComponent(v[1],v[2]) end -else - return print("Could not find storage components for this filter.") -end - -local function renderTableOutput() - local lines = {} - for i=1,#tableOut[1]-1 do - table.insert(lines,"") - end - - for i=1,#tableOut do - local length = 1 - for j=1,#lines do - tableOut[i][j+1]=tableOut[i][j+1] or "[nil]" - length = math.max(length,unicode.wlen(tableOut[i][j+1])) - end - for j=1,#lines do - if tableOut[i][1] then - lines[j]=lines[j]..string.rep(" ",length-unicode.wlen(tableOut[i][j+1]))..tableOut[i][j+1] - elseif i<#tableOut then - lines[j]=lines[j]..tableOut[i][j+1]..string.rep(" ",length-unicode.wlen(tableOut[i][j+1])) - else - lines[j]=lines[j]..tableOut[i][j+1] - end - if i<#tableOut then lines[j]=lines[j].." " end - end - end - - print(lines[1].."\n") - for i=2,#lines do - print(lines[i]) - end -end - -renderTableOutput() +Error: no such file. (``) diff --git a/halyde/apps/lua.lua b/halyde/apps/lua.lua index 03629f6..fddefd5 100644 --- a/halyde/apps/lua.lua +++ b/halyde/apps/lua.lua @@ -1,31 +1 @@ -print("\27[44m".._VERSION.."\27[0m shell") -print('Type "exit" to exit.') -termlib.readHistory["lua"] = {""} -local fs = import("filesystem") - -local loadedLibraries = "" -local libList = fs.list("halyde/lib") -for _, lib in pairs(libList) do - if lib:match("(.+)%.lua") then - loadedLibraries = loadedLibraries .. "local " .. lib:match("(.+)%.lua") .. ' = import("' .. lib:match("(.+)%.lua") .. '")\n' - end -end - -while true do - local command = read("lua", "\27[44mlua>\27[0m ") - if command == "exit" then - return - else - local function runCommand() - local func = load(loadedLibraries.."return "..command,"=stdin") or load(loadedLibraries..command,"=stdin") - local res = {assert(func)()} - if res and (type(res[1])~="nil" or type(res[2])~="nil") then print(table.unpack(res)) end - 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 +Error: no such file. (``) diff --git a/halyde/apps/maindrv.lua b/halyde/apps/maindrv.lua index 74aaf2a..fddefd5 100644 --- a/halyde/apps/maindrv.lua +++ b/halyde/apps/maindrv.lua @@ -1,8 +1 @@ -local computer = import("computer") - -if type(computer)~="table" then - return print("\x1b[91mComputer library returned '"..type(computer).."' type\x1b[39m") -end - -local address = computer.getBootAddress() -print(address) +Error: no such file. (``) diff --git a/halyde/apps/mkdir.lua b/halyde/apps/mkdir.lua index b1a8c1a..fddefd5 100644 --- a/halyde/apps/mkdir.lua +++ b/halyde/apps/mkdir.lua @@ -1,14 +1 @@ -local directory = ... -local fs = import("filesystem") - -if not directory then - shell.run("help mkdir") - return -end -if directory:sub(1, 1) ~= "/" then - directory = fs.concat(shell.workingDirectory, directory) -end -if fs.exists(directory) then - print("\27[91mAn object already exists at the specified path.") -end -fs.makeDirectory(directory) +Error: no such file. (``) diff --git a/halyde/apps/mv.lua b/halyde/apps/mv.lua index 6ffd880..fddefd5 100644 --- a/halyde/apps/mv.lua +++ b/halyde/apps/mv.lua @@ -1,24 +1 @@ -local fromFile, toFile = ... -local fs = import("filesystem") - -if not fromFile or not toFile then - shell.run("help mv") - return -end -if fromFile:sub(1, 1) ~= "/" then - fromFile = fs.concat(shell.workingDirectory, fromFile) -end -if toFile:sub(1, 1) ~= "/" then - toFile = fs.concat(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) and not (table.find({...}, "-o") or table.find({...}, "--overwrite")) then - print("\27[91mDestination file already exists. Run this command again with -o to overwrite it.") - return -end -fs.rename(fromFile, toFile) +Error: no such file. (``) diff --git a/halyde/apps/reboot.lua b/halyde/apps/reboot.lua index a11869a..fddefd5 100644 --- a/halyde/apps/reboot.lua +++ b/halyde/apps/reboot.lua @@ -1 +1 @@ -import("computer").shutdown(true) +Error: no such file. (``) diff --git a/halyde/apps/rm.lua b/halyde/apps/rm.lua index f83b695..fddefd5 100644 --- a/halyde/apps/rm.lua +++ b/halyde/apps/rm.lua @@ -1,15 +1 @@ -local file = ... -local fs = import("filesystem") - -if not file then - shell.run("help rm") - return -end -if file:sub(1, 1) ~= "/" then - file = fs.concat(shell.workingDirectory, file) -end -if not fs.exists(file) then - print("\27[91mFile does not exist.") - return -end -fs.remove(file) +Error: no such file. (``) diff --git a/halyde/apps/rtest.lua b/halyde/apps/rtest.lua index 825e54f..fddefd5 100644 --- a/halyde/apps/rtest.lua +++ b/halyde/apps/rtest.lua @@ -1,91 +1 @@ -local raster = import("raster") - -raster.init() - ---[[for i=4,20 do - raster.set(i,i) - raster.set(i,i+4,0xFF00FF) -end]] - ---[[ for x=4,20 do - for y=4,20 do - if (x+y)%2==0 then - raster.set(x,y,0xFF00FF) - end - end -end ]] - -local event = import("event") -local x=0 -local y=0 -local vx=1 -local vy=1 -local col = 0x808080 -local i=0 - -while event.pull("key_down",0)==nil do - i = i + 1 - raster.set(x,y,col) - - x = x + vx - y = y + vy - - if x>raster.displayWidth then - x=raster.displayWidth - vx = -math.abs(vx) - col = math.random(0,0xFFFFFF) - end - if x<1 then - x=1 - vx = math.abs(vx) - col = math.random(0,0xFFFFFF) - end - if y>raster.displayHeight-6 then - y=raster.displayHeight-6 - vy = -math.abs(vy) - col = math.random(0,0xFFFFFF) - end - if y<1 then - y=1 - vy = math.abs(vy) - col = math.random(0,0xFFFFFF) - end - - if i>10 and i%15>0 then - while true do - local tries=0 - local dx,dy=math.random(1,raster.displayWidth),math.random(1,raster.displayHeight-6) - if raster.get(dx,dy)~=0 then - raster.set(dx,dy,0) - break - end - tries = tries + 1 - if tries>20 then - break - end - end - end - - if i%10==0 then - raster.update() - coroutine.yield() - end -end - ---[[ for i=0,360,4 do - local angle = i/180*math.pi - if false then - local x1,y1,x2,y2=raster.displayWidth/2,raster.displayHeight/2,raster.displayWidth/2+math.sin(angle)*80,raster.displayHeight/2+math.cos(angle)*80 - raster.fillEllipse(x1,y1,x2,y2,0xFF00FF) - raster.update() - raster.fillEllipse(x1,y1,x2,y2,0x000000) - else - local x,y,c=raster.displayWidth/2,raster.displayHeight/2,math.abs(math.sin(angle)*100) - raster.drawCircle(x,y,c,0xFF00FF) - raster.update() - raster.drawCircle(x,y,c,0x000000) - end -end ]] - -raster.free() -termlib.cursorPosY=1 \ No newline at end of file +Error: no such file. (``) diff --git a/halyde/apps/rtest3d.lua b/halyde/apps/rtest3d.lua index 62c0c2c..fddefd5 100644 --- a/halyde/apps/rtest3d.lua +++ b/halyde/apps/rtest3d.lua @@ -1,141 +1 @@ -local component = import("component") -local computer = import("computer") -local raster = import("raster") -local event = import("event") - --- Initialize the 3D renderer for a spinning cube --- Using the raster library for drawing - --- Screen dimensions -local SCREEN_WIDTH, SCREEN_HEIGHT = component.invoke(component.list("gpu")(), "getResolution") -SCREEN_WIDTH, SCREEN_HEIGHT = SCREEN_WIDTH * 2, SCREEN_HEIGHT * 4 -local CENTER_X = SCREEN_WIDTH / 2 -local CENTER_Y = SCREEN_HEIGHT / 2 - --- Cube properties -local CUBE_SIZE = 10 -local increment = 0 -local WHITE = 0xFFFFFF -local ROTATION_SPEED = 0.1 - --- 3D cube vertices (centered at origin) -local vertices = { - {-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 0: left bottom back - {CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 1: right bottom back - {CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 2: right top back - {-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 3: left top back - {-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 4: left bottom front - {CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 5: right bottom front - {CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, -- 6: right top front - {-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} -- 7: left top front -} - --- Cube edges defined by vertex indices -local edges = { - {0, 1}, {1, 2}, {2, 3}, {3, 0}, -- back face - {4, 5}, {5, 6}, {6, 7}, {7, 4}, -- front face - {0, 4}, {1, 5}, {2, 6}, {3, 7} -- connecting edges -} - --- Projection parameters -local FOV = 256 -- Field of view (distance from camera to screen) -local Z_OFFSET = 300 -- Distance from camera to cube center - --- Initialize rotation angles -local angleX, angleY, angleZ = 0, 0, 0 - --- Matrix multiplication function (apply rotation to a 3D point) -local function rotatePoint(x, y, z) - -- Rotation around X axis - local cosX, sinX = math.cos(angleX), math.sin(angleX) - local y1 = y * cosX - z * sinX - local z1 = y * sinX + z * cosX - - -- Rotation around Y axis - local cosY, sinY = math.cos(angleY), math.sin(angleY) - local x1 = x * cosY + z1 * sinY - local z2 = -x * sinY + z1 * cosY - - -- Rotation around Z axis - local cosZ, sinZ = math.cos(angleZ), math.sin(angleZ) - local x2 = x1 * cosZ - y1 * sinZ - local y2 = x1 * sinZ + y1 * cosZ - - return x2, y2, z2 -end - --- Perspective projection function (3D to 2D) -local function projectPoint(x, y, z) - -- Apply perspective projection - local scale = FOV / (z + Z_OFFSET) - local x2d = x * scale + CENTER_X - local y2d = y * scale + CENTER_Y - - return x2d, y2d -end - --- Render a single frame -local function renderFrame() - local time = computer.uptime()*20 - increment = time*0.05 -- increment + 0.05 - CUBE_SIZE = (math.sin(increment) + 1) * 25 - vertices = { - {-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 0: left bottom back - {CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 1: right bottom back - {CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 2: right top back - {-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 3: left top back - {-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 4: left bottom front - {CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 5: right bottom front - {CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, -- 6: right top front - {-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} -- 7: left top front - } - -- Update rotation angles - raster.clear() - angleX = time * ROTATION_SPEED -- angleX - angleY = time * ROTATION_SPEED * 0.7 -- angleY - angleZ = time * ROTATION_SPEED * 0.5 -- angleZ - - -- Project all vertices - local projectedPoints = {} - for i, vertex in ipairs(vertices) do - -- Rotate the point - local x, y, z = rotatePoint(vertex[1], vertex[2], vertex[3]) - - -- Project the point to 2D - local x2d, y2d = projectPoint(x, y, z) - projectedPoints[i] = {x2d, y2d} - end - - -- Draw all edges - for _, edge in ipairs(edges) do - local p1 = projectedPoints[edge[1] + 1] -- +1 because Lua indices start at 1 - local p2 = projectedPoints[edge[2] + 1] - - -- Draw the line - raster.drawLine(p1[1], p1[2], p2[1], p2[2], WHITE) - end - - -- Render the frame - raster.update() -end - --- Main program -function main() - -- Initialize raster engine - raster.init() - - -- Main loop (assume this is called repeatedly by the host environment) - while true do - renderFrame() - coroutine.yield() - if event.pull("key_down", 0) then - raster.free() - break - end - end - -- Return a reference to renderFrame so it can be called for animation - return renderFrame -end - --- Start the program -return main() +Error: no such file. (``) diff --git a/halyde/apps/shutdown.lua b/halyde/apps/shutdown.lua index d2544dc..fddefd5 100644 --- a/halyde/apps/shutdown.lua +++ b/halyde/apps/shutdown.lua @@ -1 +1 @@ -import("computer").shutdown() +Error: no such file. (``) diff --git a/halyde/core/boot.lua b/halyde/core/boot.lua index 0405c25..fddefd5 100644 --- a/halyde/core/boot.lua +++ b/halyde/core/boot.lua @@ -1,98 +1 @@ -local loadfile = ... -local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile) - -_G._OSVERSION = "Halyde 2.8.1" -_G._OSLOGO = "" -local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil -repeat - tmpdata = handle:read(math.huge) - _OSLOGO = _OSLOGO .. (tmpdata or "") -until not tmpdata - -_G.package = {["preloaded"] = {}} - -loadfile("/halyde/core/datatools.lua")() - -function _G.import(module, ...) - local args = table.pack(...) - if package.preloaded[module] then - return package.preloaded[module] - end - local modulepath - if filesystem.exists(module) then - modulepath = module - elseif filesystem.exists("/halyde/lib/"..module..".lua") then - modulepath = "/halyde/lib/"..module..".lua" - elseif shell and shell.workingDirectory and filesystem.exists(shell.workingDirectory..module) then - modulepath = shell.workingDirectory..module - end - assert(modulepath, "module not found\npossible locations:\n/halyde/lib/"..module..".lua") - local handle, data, tmpdata = filesystem.open(modulepath), "", nil - repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() - return(assert(load(data, "="..modulepath))(table.unpack(args))) -end - -local function preload(module) - local handle, data, tmpdata = assert(filesystem.open("/halyde/lib/" .. module .. ".lua", "r")), "", nil - repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") - until not tmpdata - package.preloaded[module] = assert(load(data, "="..module))() - _G[module] = nil -end - -preload("component") -preload("computer") -preload("filesystem") - -local component = import("component") -local gpu = component.gpu -local screenAddress = component.list("screen")() ---local screen = component.screen - -gpu.bind(screenAddress) ---local maxWidth, maxHeight = gpu.maxResolution() ---local aspectX, aspectY = screen.getAspectRatio() ---local screenRatio = aspectX * 2 / aspectY - --- Calculate potential dimensions ---local widthLimited = math.floor(maxHeight * screenRatio) ---local heightLimited = math.floor(maxWidth / screenRatio) - ---local targetWidth, targetHeight - ---if widthLimited <= maxWidth then - -- height is the limiting factor --- targetWidth = widthLimited --- targetHeight = maxHeight ---else - -- width is the limiting factor --- targetWidth = maxWidth --- targetHeight = heightLimited ---end - ---targetWidth = math.min(targetWidth, maxWidth) ---targetHeight = math.min(targetHeight, maxHeight) - ---gpu.setResolution(targetWidth, targetHeight) -gpu.setResolution(gpu.maxResolution()) - ---local handle = assert(filesystem.open("/bazinga.txt", "w")) ---assert(handle:write("Bazinga!")) ---handle:close() - -local fs = import("filesystem") -if not fs.exists("/halyde/config/shell.json") then -- Auto-generate configs - fs.copy("/halyde/config/generate/shell.json", "/halyde/config/shell.json") -end -if not fs.exists("/halyde/config/startupapps.json") then - fs.copy("/halyde/config/generate/startupapps.json", "/halyde/config/startupapps.json") -end -fs = nil - -import("/halyde/core/cormgr.lua") +Error: no such file. (``) diff --git a/halyde/core/cormgr.lua b/halyde/core/cormgr.lua index 7049fa3..fddefd5 100644 --- a/halyde/core/cormgr.lua +++ b/halyde/core/cormgr.lua @@ -1,97 +1 @@ -_G.cormgr = {} -_G.cormgr.corList = {} -_G.cormgr.labelList = {} - -local component = import("component") -local filesystem = import("filesystem") -local json = import("json") -local gpu = component.gpu ---local ocelot = component.ocelot - -function _G.cormgr.loadCoroutine(path,...) - local args = {...} - local function corFunction() - local result, errorMessage = xpcall(function(...) - import(...) - end, function(errorMessage) - return errorMessage .. "\n \n" .. debug.traceback() - end, path, table.unpack(args)) - if not result then - if print then - gpu.freeAllBuffers() - print("\n\27[91m" .. errorMessage) - else - error(errorMessage) - end - end - --import(path, table.unpack(args)) - end - cormgr.addCoroutine(corFunction, string.match(tostring(path), "([^/]+)%.lua$")) -end - -function _G.cormgr.addCoroutine(func, name) - local cor = coroutine.create(func) - table.insert(cormgr.corList, cor) - table.insert(cormgr.labelList, name) - return cor -end - -function _G.cormgr.removeCoroutine(name) - local index = table.find(cormgr.labelList, cor) - table.remove(cormgr.corList, index) - table.remove(cormgr.labelList, index) - --coroutine.close(cor) -end - -function handleError(errormsg) - if errormsg == nil then - error("unknown error") - else - error(tostring(errormsg).."\n \n"..debug.traceback()) - end -end - -local function runCoroutines() - for i = 1, #_G.cormgr.corList do - if cormgr.corList[i] then - local result, errorMessage = coroutine.resume(cormgr.corList[i]) - if cormgr.corList[i] then - if not result then - handleError(errorMessage) - end - if coroutine.status(cormgr.corList[i]) == "dead" then - table.remove(cormgr.corList, i) - table.remove(cormgr.labelList, i) - --ocelot.log("Removed coroutine") - i = i - 1 - end - --computer.pullSignal(0) - --coroutine.yield() - end - end - end -end - -local handle, data, tmpdata = filesystem.open("/halyde/config/startupapps.json", "r"), "", nil -repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") -until not tmpdata -handle:close() -for _, line in ipairs(json.decode(data)) do - if line ~= "" then - --[[ if _G.print then - print(line) - end ]] - _G.cormgr.loadCoroutine(line) - runCoroutines() - end -end --- _G.cormgr.loadCoroutine("/halyde/core/shell.lua") - -while true do - runCoroutines() - if #_G.cormgr.corList == 0 then - computer.shutdown() - end -end +Error: no such file. (``) diff --git a/halyde/core/datatools.lua b/halyde/core/datatools.lua index b7b80e5..fddefd5 100644 --- a/halyde/core/datatools.lua +++ b/halyde/core/datatools.lua @@ -1,45 +1 @@ -local conversionTables = { - ["bytes"] = { - ["B"] = 1, - ["KB"] = 1000, - ["MB"] = 1000000, - ["GB"] = 1000000000 - }, ["bibytes"] = { - ["B"] = 1, - ["KiB"] = 1024, - ["MiB"] = 1048576, - ["GiB"] = 1073741824 - } -} - -function table.find(tab, item) - for k, v in pairs(tab) do - if v == item then - return k - end - end -end - -function table.copy(orig) - local orig_type = type(orig) - local copy - if orig_type == 'table' then - copy = {} - for orig_key, orig_value in next, orig, nil do - copy[table.copy(orig_key)] = table.copy(orig_value) - end - setmetatable(copy, table.copy(getmetatable(orig))) - else -- number, string, boolean, etc - copy = orig - end - return copy -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 +Error: no such file. (``) diff --git a/halyde/core/drvload.lua b/halyde/core/drvload.lua index 441b091..fddefd5 100644 --- a/halyde/core/drvload.lua +++ b/halyde/core/drvload.lua @@ -1,46 +1 @@ -local fs = import("filesystem") - -local driverPath = "/halyde/drivers" - -local drivers = fs.list(driverPath) -local driverTypes = {} - -local function loadDriver(drvName) - local driverData = import(fs.concat(driverPath, drvName)) - table.remove(drivers, table.find(drivers, drvName)) - if driverData.dependencies then - for _, dependency in pairs(driverData.dependencies) do - if table.find(drivers, dependency) then - loadDriver(dependency) - elseif table.find(drivers, dependency .. ".lua") then - loadDriver(dependency .. ".lua") - else - for typeLookupDrvName, typeLookupDrvType in pairs(driverTypes) do - if typeLookupDrvType == dependency then - loadDriver(typeLookupDrvName) - -- Don't break, because there can be multiple drivers of the correct type - end - end - end - end - end - --print(drvName) - if driverData.onStartup then -- I have no idea why would this not exist, but it's a failsafe - driverData.onStartup() - end - -- More functions to be implemented in the future -end - -for _, drvName in pairs(drivers) do -- Get all the driver types - local driverData = import(fs.concat(driverPath, drvName)) - if driverData.type then - --print(driverData.type) - driverTypes[drvName] = driverData.type -- Not the other way around because there can be multiple drivers of the same type, but there can't be multiple entries with the same key - end -end - -for _, drvName in pairs(drivers) do -- Load the drivers - if drvName:sub(-1, -1) ~= "/" then -- Check if it's not a directory. Otherwise it might be driver config - loadDriver(drvName) - end -end +Error: no such file. (``) diff --git a/halyde/core/evmgr.lua b/halyde/core/evmgr.lua index 7fb252f..fddefd5 100644 --- a/halyde/core/evmgr.lua +++ b/halyde/core/evmgr.lua @@ -1,55 +1 @@ -_G.evmgr = {} -_G.evmgr.eventQueue = {} -local maxEventQueueLength = 10 -- increase if events start getting dropped - -local computer = import("computer") - -keyboard.ctrlDown = false -keyboard.altDown = false -keyboard.shiftDown = false - ---local ocelot = component.proxy(component.list("ocelot")()) - -while true do - local args - repeat - args = {computer.uptime(), computer.pullSignal(0)} - if args and args[2] then - table.insert(evmgr.eventQueue, args) - if keyboard then - if args[2] == "key_down" then - local keycode = args[5] - local key = keyboard.keys[keycode] - if key == "lcontrol" then - keyboard.ctrlDown = true - elseif key == "lmenu" then - keyboard.altDown = true - elseif key == "lshift" then - keyboard.shiftDown = true - elseif key == "c" and keyboard.ctrlDown and keyboard.altDown then - if print then - print("\n\27[91mCoroutine "..tostring(#cormgr.corList).." killed.") - end - cormgr.corList[#cormgr.corList] = nil - end - elseif args[2] == "key_up" then - local keycode = args[5] - local key = keyboard.keys[keycode] - if key == "lcontrol" then - keyboard.ctrlDown = false - elseif key == "lmenu" then - keyboard.altDown = false - elseif key == "lshift" then - keyboard.shiftDown = true - end - end - end - while #evmgr.eventQueue > maxEventQueueLength do - --ocelot.log("Queue length breach, removing first signal") - table.remove(evmgr.eventQueue, 1) - end - end - until not args or not args[1] - --ocelot.log("done") - coroutine.yield() -end +Error: no such file. (``) diff --git a/halyde/core/fullkb.lua b/halyde/core/fullkb.lua index e9c64de..fddefd5 100644 --- a/halyde/core/fullkb.lua +++ b/halyde/core/fullkb.lua @@ -1,143 +1 @@ -_G.keyboard = {["keys"] = {}} - -keyboard.keys["1"] = 0x02 -keyboard.keys["2"] = 0x03 -keyboard.keys["3"] = 0x04 -keyboard.keys["4"] = 0x05 -keyboard.keys["5"] = 0x06 -keyboard.keys["6"] = 0x07 -keyboard.keys["7"] = 0x08 -keyboard.keys["8"] = 0x09 -keyboard.keys["9"] = 0x0A -keyboard.keys["0"] = 0x0B -keyboard.keys.a = 0x1E -keyboard.keys.b = 0x30 -keyboard.keys.c = 0x2E -keyboard.keys.d = 0x20 -keyboard.keys.e = 0x12 -keyboard.keys.f = 0x21 -keyboard.keys.g = 0x22 -keyboard.keys.h = 0x23 -keyboard.keys.i = 0x17 -keyboard.keys.j = 0x24 -keyboard.keys.k = 0x25 -keyboard.keys.l = 0x26 -keyboard.keys.m = 0x32 -keyboard.keys.n = 0x31 -keyboard.keys.o = 0x18 -keyboard.keys.p = 0x19 -keyboard.keys.q = 0x10 -keyboard.keys.r = 0x13 -keyboard.keys.s = 0x1F -keyboard.keys.t = 0x14 -keyboard.keys.u = 0x16 -keyboard.keys.v = 0x2F -keyboard.keys.w = 0x11 -keyboard.keys.x = 0x2D -keyboard.keys.y = 0x15 -keyboard.keys.z = 0x2C - -keyboard.keys.apostrophe = 0x28 -keyboard.keys.at = 0x91 -keyboard.keys.back = 0x0E -- backspace -keyboard.keys.backslash = 0x2B -keyboard.keys.capital = 0x3A -- capslock -keyboard.keys.colon = 0x92 -keyboard.keys.comma = 0x33 -keyboard.keys.enter = 0x1C -keyboard.keys.equals = 0x0D -keyboard.keys.grave = 0x29 -- accent grave -keyboard.keys.lbracket = 0x1A -keyboard.keys.lcontrol = 0x1D -keyboard.keys.lmenu = 0x38 -- left Alt -keyboard.keys.lshift = 0x2A -keyboard.keys.minus = 0x0C -keyboard.keys.numlock = 0x45 -keyboard.keys.pause = 0xC5 -keyboard.keys.period = 0x34 -keyboard.keys.rbracket = 0x1B -keyboard.keys.rcontrol = 0x9D -keyboard.keys.rmenu = 0xB8 -- right Alt -keyboard.keys.rshift = 0x36 -keyboard.keys.scroll = 0x46 -- Scroll Lock -keyboard.keys.semicolon = 0x27 -keyboard.keys.slash = 0x35 -- / on main keyboard -keyboard.keys.space = 0x39 -keyboard.keys.stop = 0x95 -keyboard.keys.tab = 0x0F -keyboard.keys.underline = 0x93 - --- Keypad (and numpad with numlock off) -keyboard.keys.up = 0xC8 -keyboard.keys.down = 0xD0 -keyboard.keys.left = 0xCB -keyboard.keys.right = 0xCD -keyboard.keys.home = 0xC7 -keyboard.keys["end"] = 0xCF -keyboard.keys.pageUp = 0xC9 -keyboard.keys.pageDown = 0xD1 -keyboard.keys.insert = 0xD2 -keyboard.keys.delete = 0xD3 - --- Function keys -keyboard.keys.f1 = 0x3B -keyboard.keys.f2 = 0x3C -keyboard.keys.f3 = 0x3D -keyboard.keys.f4 = 0x3E -keyboard.keys.f5 = 0x3F -keyboard.keys.f6 = 0x40 -keyboard.keys.f7 = 0x41 -keyboard.keys.f8 = 0x42 -keyboard.keys.f9 = 0x43 -keyboard.keys.f10 = 0x44 -keyboard.keys.f11 = 0x57 -keyboard.keys.f12 = 0x58 -keyboard.keys.f13 = 0x64 -keyboard.keys.f14 = 0x65 -keyboard.keys.f15 = 0x66 -keyboard.keys.f16 = 0x67 -keyboard.keys.f17 = 0x68 -keyboard.keys.f18 = 0x69 -keyboard.keys.f19 = 0x71 - --- Japanese keyboards -keyboard.keys.kana = 0x70 -keyboard.keys.kanji = 0x94 -keyboard.keys.convert = 0x79 -keyboard.keys.noconvert = 0x7B -keyboard.keys.yen = 0x7D -keyboard.keys.circumflex = 0x90 -keyboard.keys.ax = 0x96 - --- Numpad -keyboard.keys.numpad0 = 0x52 -keyboard.keys.numpad1 = 0x4F -keyboard.keys.numpad2 = 0x50 -keyboard.keys.numpad3 = 0x51 -keyboard.keys.numpad4 = 0x4B -keyboard.keys.numpad5 = 0x4C -keyboard.keys.numpad6 = 0x4D -keyboard.keys.numpad7 = 0x47 -keyboard.keys.numpad8 = 0x48 -keyboard.keys.numpad9 = 0x49 -keyboard.keys.numpadmul = 0x37 -keyboard.keys.numpaddiv = 0xB5 -keyboard.keys.numpadsub = 0x4A -keyboard.keys.numpadadd = 0x4E -keyboard.keys.numpaddecimal = 0x53 -keyboard.keys.numpadcomma = 0xB3 -keyboard.keys.numpadenter = 0x9C -keyboard.keys.numpadequals = 0x8D - --- Create inverse mapping for name lookup. -setmetatable(keyboard.keys, -{ - __index = function(tbl, k) - if type(k) ~= "number" then return end - for name,value in pairs(tbl) do - if value == k then - return name - end - end - end -}) +Error: no such file. (``) diff --git a/halyde/core/shell.lua b/halyde/core/shell.lua index f75b189..fddefd5 100644 --- a/halyde/core/shell.lua +++ b/halyde/core/shell.lua @@ -1,106 +1 @@ -local fs = import("filesystem") -local json = import("json") -local handle, data, tmpdata = fs.open("/halyde/config/shell.json", "r"), "", nil -repeat - tmpdata = handle:read(math.huge) - data = data .. (tmpdata or "") -until not tmpdata -handle:close() -local shellcfg = json.decode(data) -import("/halyde/core/termlib.lua") -local event = import("event") -local component = import("component") -local gpu = component.gpu - -_G.shell = {} -_G.shell.workingDirectory = shellcfg["defaultWorkingDirectory"] -_G.shell.aliases = shellcfg["aliases"] - -local function runAsCoroutine(path, ...) - --ocelot.log("running " .. path .. " as coroutine") - cormgr.loadCoroutine(path, ...) - local corIndex = #cormgr.corList - local cor = cormgr.corList[#cormgr.corList] - repeat - coroutine.yield() - until cormgr.corList[corIndex] ~= cor -end - -function _G.shell.run(command) - checkArg(1, command, "string") - if shell.aliases[command:match("[^ ]+")] then - 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 - result = gm() - if not result then - break - end - if result:find('"') then - local location = trimmedCommand:find('"') - local argBefore = result:sub(1, result:find('"') - 1) -- edge case where there is no space before the quote, get the argument there - if argBefore and argBefore ~= "" then - table.insert(args, argBefore) - end - trimmedCommand = trimmedCommand:sub(location + 1) - if trimmedCommand:find('"') then - table.insert(args, trimmedCommand:sub(1, trimmedCommand:find('"') - 1)) - trimmedCommand = trimmedCommand:sub(trimmedCommand:find('"') + 1) - gm = trimmedCommand:gmatch('[^ ]+') - else - print("\27[91mmalformed shell command") - return - end - else - table.insert(args, result) - end - end - -- execute the program - local PATH = table.copy(shellcfg.path) - table.insert(PATH, shell.workingDirectory) - if not args[1] then - return - end - if fs.exists(args[1]) and not fs.isDirectory(args[1]) then - local path = args[1] - table.remove(args, 1) - runAsCoroutine(path, table.unpack(args)) - return - end - for _, item in pairs(PATH) do - if fs.exists(item..args[1]) and not fs.isDirectory(item .. args[1]) then - local path = fs.concat(item, args[1]) - table.remove(args, 1) - runAsCoroutine(path, table.unpack(args)) - return - else -- try to look for it without the file extension - local files = fs.list(item) or {} - for _, file in pairs(files) do - -- previous pattern: (.+)%.[^%.]+$ - if args[1] == file:match("(.+)%.[^%.]+$") and not fs.isDirectory(item .. file) then - table.remove(args, 1) - runAsCoroutine(item .. file, table.unpack(args)) - return - end - end - end - end - print("No such file or command: "..args[1]) -end - -print(shellcfg["startupMessage"]:format(_OSVERSION, shellcfg.splashMessages[math.random(1, #shellcfg.splashMessages)])) -while true do - coroutine.yield() - -- print(shell.workingDirectory .. " >") - --print(shellcfg["prompt"]:format(shell.workingDirectory),false) - -- termlib.cursorPosX = #(shell.workingDirectory .. " > ") - -- termlib.cursorPosY = termlib.cursorPosY - 1 - if shell.workingDirectory:sub(-1, -1) ~= "/" then - shell.workingDirectory = shell.workingDirectory .. "/" - end - local shellCommand = read("shell", shellcfg.prompt:format(shell.workingDirectory)) - shell.run(shellCommand) - gpu.freeAllBuffers() -end +Error: no such file. (``) diff --git a/halyde/core/termlib.lua b/halyde/core/termlib.lua index 1d1e74b..fddefd5 100644 --- a/halyde/core/termlib.lua +++ b/halyde/core/termlib.lua @@ -1,453 +1 @@ -local serialize = import("serialize") -local unicode = import("unicode") -local event = import("event") ---local keyboard = import("keyboard") - ---local ocelot = component.proxy(component.list("ocelot")()) -local component = import("component") -local computer = import("computer") -local gpu = component.gpu -_G.termlib = {} -termlib.cursorPosX = 1 -termlib.cursorPosY = 1 -termlib.readHistory = {} - -local width, height = gpu.getResolution() - -local ANSIColorPalette = { - ["dark"] = { - [0] = 0x000000, - [1] = 0x800000, - [2] = 0x008000, - [3] = 0x808000, - [4] = 0x000080, - [5] = 0x800080, - [6] = 0x008080, - [7] = 0xC0C0C0 - }, - ["bright"] = { - [0] = 0x808080, - [1] = 0xFF0000, - [2] = 0x00FF00, - [3] = 0xFFFF00, - [4] = 0x0000FF, - [5] = 0xFF00FF, - [6] = 0x00FFFF, - [7] = 0xFFFFFF - } -} - -defaultForegroundColor = ANSIColorPalette["bright"][7] -defaultBackgroundColor = ANSIColorPalette["dark"][0] - -gpu.setForeground(defaultForegroundColor) -gpu.setBackground(defaultBackgroundColor) - -local function scrollDown() - local width, height = gpu.getResolution() - if gpu.copy(1,1,width,height,0,-1) then - local prevForeground = gpu.getForeground() - local prevBackground = gpu.getBackground() - gpu.setForeground(defaultForegroundColor) - gpu.setBackground(defaultBackgroundColor) - gpu.fill(1, height, width, 1, " ") - gpu.setForeground(prevForeground) - gpu.setBackground(prevBackground) - termlib.cursorPosY=height - end -end - -local function newLine() - termlib.cursorPosX=1 - termlib.cursorPosY = termlib.cursorPosY + 1 - if termlib.cursorPosY>height then - scrollDown() - end -end - -local function parseCodeNumbers(code) - local o = {} - for num in code:sub(3,-2):gmatch("[^;]+") do - table.insert(o,tonumber(num)) - end - return o -end - -local function from8BitColor(num) - num=math.floor(num)&255 - if num<16 then return 0x444444*((num>>3)&1)+(0xBB0000*((num>>2)&1)|0x00BB00*((num>>1)&1)|0x0000BB*(num&1)) end - if num>=232 then return 0x10101*(8+(num-232)*10) end - num=num-16 - local palette = {0,95,135,175,215,255} - return (palette[(num//36)%6+1]<<16)|(palette[(num//6)%6+1]<<8)|palette[num%6+1] -end - -local function from24BitColor(r,g,b) - r,g,b=math.floor(r)&255,math.floor(g)&255,math.floor(b)&255 - return (r<<16)|(g<<8)|b -end - -local function findCodeEnd(text,i) - local function inRange(v,min,max) - return v>=min and v<=max - end - i=i+2 - while i<=#text and not inRange(text:byte(i),0x40,0x7F) do i=i+1 end - return i -end - -function termlib.write(text, textWrap) - local width, height = gpu.getResolution() - - -- you don't know how tiring this was just for ANSI escape code support - - if textWrap == nil then - textWrap = true - end - - if not text or not tostring(text) then - return - end - if text:find("\a") then - computer.beep() - end - text = tostring(text) - text = "\27[0m" .. text:gsub("\t", " ") - local 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. - -- unfortunately, changing the "i" variable would have unpredictable effects, so to not risk anything, this workaround was done. - local section = "" - - local function printSection() - if #section==0 then - return - end - while true do - gpu.set(termlib.cursorPosX,termlib.cursorPosY,section) - if unicode.wlen(section) > width - termlib.cursorPosX + 1 and textWrap then - section = section:sub(width - termlib.cursorPosX + 2) - newLine() - else - termlib.cursorPosX = termlib.cursorPosX+unicode.wlen(section) - break - end - end - section = "" - end - - for i=1,#text do - if readBreak>0 then - readBreak = readBreak - 1 - goto continue - end - - if string.byte(text,i)==10 then - printSection() - newLine() - elseif string.byte(text,i)==13 then - printSection() - termlib.cursorPosX=1 - elseif string.byte(text,i)==0x1b and i<=#text-2 then - printSection() - --ocelot.log("0x1b char detected") - local codeType = string.sub(text,i+1,i+1) - if codeType=="[" then - -- Control Sequence Introducer - --ocelot.log("Control Sequence Introducer") - local codeEndIdx = findCodeEnd(text,i) - -- codeEndIdx = string.find(text,"m",i) - local code = string.sub(text,i,codeEndIdx) - --ocelot.log("Code: "..code.." ("..i..", "..codeEndIdx..")") - readBreak = readBreak + #code - 1 - local nums = parseCodeNumbers(code) - local codeEnd = code:sub(-1) - --ocelot.log("Code end: "..codeEnd..", "..#codeEnd) - if codeEnd == "m" then - -- Select Graphic Rendition - --ocelot.log("Select Graphic Rendition, ID "..nums[1]) - if nums[1]>=30 and nums[1]<=37 then - gpu.setForeground(ANSIColorPalette["dark"][nums[1]%10]) - end - if nums[1]==38 and nums[2]==5 then - gpu.setForeground(from8BitColor(nums[3])) - end - if nums[1]==38 and nums[2]==2 then - gpu.setForeground(from24BitColor(nums[3],nums[4],nums[5])) - end - if nums[1]==39 or nums[1]==0 then - gpu.setForeground(defaultForegroundColor) - end - if nums[1]>=40 and nums[1]<=47 then - gpu.setBackground(ANSIColorPalette["dark"][nums[1]%10]) - end - if nums[1]==48 and nums[2]==5 then - gpu.setBackground(from8BitColor(nums[3])) - end - if nums[1]==48 and nums[2]==2 then - gpu.setBackground(from24BitColor(nums[3],nums[4],nums[5])) - end - if nums[1]==49 or nums[1]==0 then - gpu.setBackground(defaultBackgroundColor) - end - if nums[1]>=90 and nums[1]<=97 then - gpu.setForeground(ANSIColorPalette["bright"][nums[1]%10]) - end - if nums[1]>=100 and nums[1]<=107 then - gpu.setBackground(ANSIColorPalette["bright"][nums[1]%10]) - end - end - end - else - --gpu.set(termlib.cursorPosX,termlib.cursorPosY,string.sub(text,i,i)) - section = section..string.sub(text,i,i) - end - ::continue:: - end - printSection() -end - -function _G.print(...) - local args = {...} - local stringArgs = {} - for _, arg in pairs(args) do - if type(arg)=="table" then - table.insert(stringArgs, serialize.table(arg,true)) - elseif tostring(arg) then - table.insert(stringArgs, tostring(arg)) - end - end - termlib.write(table.concat(stringArgs, " ") .. "\n") -end - -function _G.clear() - width, height = gpu.getResolution() - gpu.setForeground(defaultForegroundColor) - gpu.setBackground(defaultBackgroundColor) - gpu.fill(1,1,width,height," ") - termlib.cursorPosX, termlib.cursorPosY = 1, 1 -end - -function _G.read(readHistoryType, prefix, defaultText, maxChars) - checkArg(1, readHistoryType, "string", "nil") - checkArg(2, prefix, "string", "nil") - checkArg(3, defaultText, "string", "nil") - checkArg(4, maxChars, "number", "nil") - maxChars = maxChars or math.huge - - local text = defaultText or "" - - local historyIdx - if readHistoryType then - if not termlib.readHistory[readHistoryType] then - termlib.readHistory[readHistoryType] = {text} - elseif termlib.readHistory[readHistoryType][#termlib.readHistory[readHistoryType] ] ~= "" then - table.insert(termlib.readHistory[readHistoryType], text) - end - historyIdx = #termlib.readHistory[readHistoryType] - end - - local function updateHistory() - if not readHistoryType then return end - termlib.readHistory[readHistoryType][historyIdx]=text - end - - local cur = unicode.len(text)+1 - if prefix then termlib.write(prefix) end - local startX, startY = termlib.cursorPosX, termlib.cursorPosY - local fg, bg = gpu.getForeground(), gpu.getBackground() - local cursorBlink = true - local function get(idx) - idx=startX+idx-1 - return gpu.get(idx%width,startY+(idx//width)) - end - local function checkScroll(y) - for i=1,y-height do - scrollDown() - startY=startY-1 - end - return math.min(y,height) - end - local function set(idx,chr,rev) - if chr==nil or chr=="" then return end - if rev then - gpu.setForeground(bg) - gpu.setBackground(fg) - else - gpu.setForeground(fg) - gpu.setBackground(bg) - end - idx=startX+idx-1 - local setX, setY = (idx-1)%width+1, startY+((idx-1)//width+1)-1 - setY = checkScroll(setY) - gpu.set(setX,setY,unicode.sub(chr,1,width-setX+1)) - for i=1,math.ceil((#chr+setX-1)/width)+1 do - gpu.set(1,setY+i,unicode.sub(chr,2-setX+i*width,width+i*width-setX)) - setY = checkScroll(setY) - end - end - local function strDef(a,b) - if #a==0 then return b end - return a - end - local function curPos(cur) - return unicode.wlen(unicode.sub(text,1,cur-1))+1 - end - local function add(chr) - if type(chr)~="string" or #chr==0 then return end - if unicode.len(text)>=maxChars then return end - if maxChars1 then - text=unicode.sub(text,1,cur-2)..unicode.sub(text,cur) - cur=cur-1 - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) - cursorBlink = true - set(curPos(cur)+1,unicode.sub(text,cur+1).." ",false) - updateHistory() - elseif key=="delete" then - text = unicode.sub(text,1,cur-1)..unicode.sub(text,cur+1) - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) - cursorBlink = true - if cur<=unicode.len(text) then - set(curPos(cur+1),unicode.sub(text,cur+1).." ",false) - end - updateHistory() - elseif key=="enter" then - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false) - break - elseif not (args[3]<32 or (args[3]>0x7F and args[3]<=0x9F)) then - add(unicode.char(args[3]) or " ") - updateHistory() - end - elseif args and args[1]=="clipboard" then - local clip = args[3] - if not args[3] then goto continue end - while isLine(unicode.sub(clip,1,1)) do clip=unicode.sub(clip,2) end - while isLine(unicode.sub(clip,-1)) do clip=unicode.sub(clip,1,-2) end - add(clip) - updateHistory() - else - cursorBlink=not cursorBlink - set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),cursorBlink) - end - ::continue:: - end - - if readHistoryType then - if termlib.readHistory[readHistoryType][#termlib.readHistory[readHistoryType]]=="" then - table.remove(termlib.readHistory[readHistoryType],#termlib.readHistory[readHistoryType]) - end - if historyIdx<#termlib.readHistory[readHistoryType] then - table.remove(termlib.readHistory[readHistoryType],historyIdx) - table.insert(termlib.readHistory[readHistoryType],text) - end - while #termlib.readHistory[readHistoryType] > 50 do - table.remove(termlib.readHistory[readHistoryType], 1) - end - end - - termlib.cursorPosX=1 - termlib.cursorPosY=termlib.cursorPosY+math.ceil((unicode.wlen(text)+startX-1)/width) - if termlib.cursorPosY>height then scrollDown() end - - return text -end +Error: no such file. (``) diff --git a/halyde/lib/component.lua b/halyde/lib/component.lua index 078fad4..fddefd5 100644 --- a/halyde/lib/component.lua +++ b/halyde/lib/component.lua @@ -1,97 +1 @@ -local compLib -local LLcomponent -if table.copy then - compLib = table.copy(component) - LLcomponent = table.copy(component) -else - compLib = {} - LLcomponent = component -end - ---local ocelot = LLcomponent.proxy(LLcomponent.list("ocelot")()) ---ocelot.log("loaded") - -_G.componentlib = {["additions"] = {}, ["removals"] = {}} -compLib.virtual = {} - -function compLib.virtual.add(address, componentType, proxy) - checkArg(1, address, "string") - checkArg(2, componentType, "string") - checkArg(3, proxy, "table") - proxy["address"] = address - componentlib.additions[address] = {["componentType"] = componentType, ["proxy"] = proxy} - if componentlib.removals[address] then - componentlib.removals[address] = nil - end -end - -function compLib.virtual.remove(address) - checkArg(1, address, "string") - if componentlib.additions[address] then - componentlib.additions[address] = nil - else - table.insert(componentlib.removals, address) - end -end - -function compLib.list(componentType) - checkArg(1, componentType, "string", "nil") - local componentList = table.copy(LLcomponent.list(componentType)) - for address, dataTable in pairs(componentlib.additions) do - if dataTable.componentType == componentType or not componentType then - componentList[address] = dataTable.componentType - end - end - for _, address in pairs(componentlib.removals) do - componentList[address] = nil - end - local i, value - setmetatable(componentList, {__call = function(self) - i, value = next(self, i) - return i, value - end}) - return componentList -end - -function compLib.proxy(address) - if componentlib.additions[address] then - --ocelot.log("vcomponent") - return componentlib.additions[address].proxy - else - return LLcomponent.proxy(address) - end -end - -function compLib.invoke(address, funcName, ...) - --ocelot.log("Invoking " .. funcName .. " from " .. address) - if componentlib.additions[address] then - --ocelot.log("vcomponent") - return componentlib.additions[address].proxy[funcName](...) - else - return LLcomponent.invoke(address, funcName, ...) - end -end - -function compLib.get(address) - checkArg(1, address, "string") - if #address < 3 then - return nil, "abbreviated address must be at least 3 characters long" - end - for currentAddress, name in compLib.list() do - if currentAddress:find("^" .. address) then - return(currentAddress) - end - end - return nil, "full address not found" -end - --- Add main component proxies to the library -setmetatable(compLib, {["__index"] = function(_, item) - if compLib.list(item)() then - return compLib.proxy(compLib.list(item)()) - else - return compLib[item] - end -end}) - -return compLib +Error: no such file. (``) diff --git a/halyde/lib/computer.lua b/halyde/lib/computer.lua index 14a223f..fddefd5 100644 --- a/halyde/lib/computer.lua +++ b/halyde/lib/computer.lua @@ -1,14 +1 @@ -local computerlib = table.copy(computer) -local LLcomputer = table.copy(computer) - -function computerlib.pullSignal(timeout) - local startTime = LLcomputer.uptime() - local result - repeat - result = {LLcomputer.pullSignal(0)} - coroutine.yield() - until result or timeout and LLcomputer.uptime() >= startTime + timeout - return table.unpack(result) -end - -return computerlib +Error: no such file. (``) diff --git a/halyde/lib/event.lua b/halyde/lib/event.lua index 64547fa..fddefd5 100644 --- a/halyde/lib/event.lua +++ b/halyde/lib/event.lua @@ -1,55 +1 @@ -local computer = import("computer") -local event = {} - -local bufferTime = 0.1 -- A little bit of buffer time so events won't be skipped by accident. - ---local ocelot = component.proxy(component.list("ocelot")()) -function event.pull(...) - local args = {...} - local evtypes, timeout = {}, nil - - for _, arg in pairs(args) do - if type(arg) == "number" and not timeout then -- It's a timeout - timeout = arg - else -- It's an event type - table.insert(evtypes, tostring(arg)) - end - end - - local startTime = computer.uptime() - - while true do - -- Check event queue for matching event - for i = 1, #evmgr.eventQueue do - local foundevent = false - if evtypes[1] then -- event type(s) specified - for _, evtype in pairs(evtypes) do - if evmgr.eventQueue[i][2] == evtype and evmgr.eventQueue[i][1] >= startTime - bufferTime then - foundevent = true - end - end - else - if evmgr.eventQueue[i][1] >= startTime - bufferTime then - foundevent = true - end - end - if foundevent then - -- Found matching event (or any event if no type specified) - local result = table.copy(evmgr.eventQueue[i]) - table.remove(evmgr.eventQueue, i) - table.remove(result, 1) -- remove the time of event argument - return table.unpack(result) - end - end - - -- Check if we've timed out - if timeout and computer.uptime() >= startTime + timeout then - return nil -- Timed out, return nil - end - - -- Yield to allow other processes to run and more events to be added - coroutine.yield() - end -end - -return event +Error: no such file. (``) diff --git a/halyde/lib/filesystem.lua b/halyde/lib/filesystem.lua index ec94613..fddefd5 100644 --- a/halyde/lib/filesystem.lua +++ b/halyde/lib/filesystem.lua @@ -1,506 +1 @@ -local loadfile = ... -- raw loadfile from boot.lua -local component, computer - -if loadfile then - unicode = loadfile("/halyde/lib/unicode.lua")(loadfile) - component = loadfile("/halyde/lib/component.lua")(loadfile) - computer = _G.computer -elseif import then - unicode = import("unicode") - component = import("component") - computer = import("computer") -end - -local filesystem = {} - -function filesystem.canonical(path) - checkArg(1, path, "string") - local segList = {} - if path:sub(1, 1) ~= "/" then - path = "/" .. path - end - path = path:gsub("/+", "/") - for segment in path:gmatch("[^/]+") do - if segment == ".." and segList[1] then - table.remove(segList, #segList) - elseif segment ~= "." then - table.insert(segList, segment) - end - end - return "/" .. table.concat(segList, "/") -end - -function filesystem.concat(...) - local paths = {...} - for i, path in ipairs(paths) do - checkArg(i, path, "string") - end - local currentPath = paths[1]:match("(.+)/?$") - for i = 2, #paths do - currentPath = currentPath .. "/" .. paths[i]:match("^/?(.+)/?$") - end - return currentPath -end - -function filesystem.absolutePath(path) -- returns the address and absolute path of an object - checkArg(1, path, "string") - path = filesystem.canonical(path) - local address = nil - if path:find("^/tmp") then - address = computer.tmpAddress() - path = path:sub(5) - elseif path:find("^/mnt/...") then - address = component.get(path:sub(6,8)) - if not address then - address = computer.getBootAddress() - else - path = path:sub(9) - end - else - address = computer.getBootAddress() - end - if not address then - return nil, "no such component" - end - return address, path -end - -function filesystem.exists(path) -- check if path exists - checkArg(1, path, "string") - local address, absPath = filesystem.absolutePath(path) - if not address then - return false - end - if absPath:find("^/special/drive/...") then - return not not (computer.getBootAddress() and component.get(absPath:sub(16,18))) - end - if absPath:find("^/special/eeprom/") then - return table.find({"init.lua","data.bin","label.txt"},absPath:sub(17)) - end - return component.invoke(address, "exists", absPath) -end - -local function readBytes(self,n) - n = n or 1 - if n==1 then - local byte = self:read(1) - if byte==nil then return nil end - return string.byte(byte) - end - local bytes, res = {string.byte(self:read(n),1,n)}, 0 - if self.littleEndian then - for i=#bytes,1,-1 do - res = (res<<8)&0xFFFFFFFF | bytes[i] - end - else - for i=1,#bytes do - res = (res<<8)&0xFFFFFFFF | bytes[i] - end - end - return res -end - -local function readUnicodeChar(self) - return unicode.readChar(function() - return self:readBytes(1) - end) -end - -local function iterateBytes(self) - return function() - local byte = readBytes(self,1) - if byte==nil then self:close() end - return byte - end -end - -local function iterateUnicodeChars(self) - return unicode.iterate(iterateBytes(self)) -end - -function filesystem.makeReadStream(content) - local properHandle = {} - local readcursor = 1 - function properHandle.read(self, amount) - checkArg(2, amount, "number") - local limit = string.len(content)+1 - local out = nil - if readcursorsectorCount then return nil end - local sector = unmanagedProxy.readSector(sectorIdx) - local data = sector:sub(((readcursor-1)%sectorSize)+1,((readcursor+math.min(amount,sectorSize)-2)%sectorSize)+1) - readcursor=readcursor+#data - if data=="" then return nil end - return data - else - if buffered then - local limit = string.len(content)+1 - local out = nil - if readcursorsectorCount then return nil, "not enough space" end - local startSByte = ((readcursor-1)%sectorSize)+1 - local sect = unmanagedProxy.readSector(startSector) - unmanagedProxy.writeSector(startSector,sect:sub(1,startSByte-1)..data:sub(1,sectorSize-startSByte+1)) - for i=2,(#data+startSByte)//sectorSize do - if startSector+i-1>sectorCount then return nil, "not enough space" end - unmanagedProxy.writeSector(startSector+i-1,data:sub(startSByte+sectorSize*(i-1),startSByte+sectorSize*i-1)) - end - readcursor=readcursor+#data - return true - else - return component.invoke(self.address, "write", self.handle, data) - end - end - function properHandle.close(self) - if buffered then - content = nil - else - return component.invoke(self.address, "close", self.handle) - end - end - if address==computer.getBootAddress() then - local eeprom - pcall(function() - eeprom = component.eeprom - end) - if eeprom then - local getFunc, setFunc - if absPath=="/special/eeprom/init.lua" then - getFunc,setFunc = "get","set" - elseif absPath=="/special/eeprom/data.bin" then - getFunc,setFunc = "getData","setData" - elseif absPath=="/special/eeprom/label.txt" then - getFunc,setFunc = "getLabel","setLabel" - end - if mode:sub(1,1)=="r" and getFunc then - local stream = filesystem.makeReadStream(eeprom[getFunc]() or "") - properHandle.read = stream.read - properHandle.close = stream.close - elseif mode:sub(1,1)=="w" and setFunc then - local content = "" - function properHandle.write(self, data) - checkArg(2, data, "string") - content=content..data - end - function properHandle.close(self) - return eeprom[setFunc](content) - end - end - end - end - return properHandle -end - -function filesystem.list(path) - checkArg(1, path, "string") - path = filesystem.canonical(path) - if path == "/mnt" then - -- list drives - local returnTable = {} - local tmpAddress = computer.tmpAddress() - for address, _ in component.list("filesystem") do - if address~=tmpAddress then - table.insert(returnTable, address:sub(1, 3) .. "/") - end - end - return returnTable - elseif path == "/special/drive" then - local returnTable = {} - local tmpAddress = computer.tmpAddress() - for address, type in component.list("drive") do - if address~=tmpAddress and type=="drive" then - table.insert(returnTable, address:sub(1, 3)) - end - end - return returnTable - elseif path=="/special/eeprom" then - return {"init.lua","data.bin","label.txt"} - else - local address, absPath = filesystem.absolutePath(path) - if not address then - return false - end - return component.invoke(address, "list", absPath) - end -end - -function filesystem.size(path) - checkArg(1, path, "string") - local address, absPath = filesystem.absolutePath(path) - if not address then - return false - end - if address==computer.getBootAddress() then - if absPath:find("^/special/drive") then - local drive = component.get(absPath:sub(16,18)) - if not drive then return false end - return component.invoke(drive,"getCapacity") - elseif absPath:find("^/special/eeprom") then - local eeprom - pcall(function() - eeprom = component.eeprom - end) - if eeprom then - local getFunc - if absPath=="/special/eeprom/init.lua" then - getFunc = "get" - elseif absPath=="/special/eeprom/data.bin" then - getFunc = "getData" - elseif absPath=="/special/eeprom/label.txt" then - getFunc = "getLabel" - end - return #(eeprom[getFunc]()) - end - end - end - return component.invoke(address, "size", absPath) -end - -local function getRecursiveList(address,absPath) - local list = component.invoke(address,"list",absPath) - local dirList = {} - local listChanged = true - while listChanged do - listChanged = false - for i=1,#list do - if component.invoke(address, "isDirectory", absPath.."/"..list[i]) then - listChanged = true - local dir = list[i] - if dir:sub(-1)=="/" then dir=dir:sub(1,-2) end - table.insert(dirList,dir) - table.remove(list,i) - local subDir = component.invoke(address,"list",absPath.."/"..dir) - for j=1,#subDir do table.insert(list,dir.."/"..subDir[j]) end - end - end - end - return list,dirList -end - -local function copyContent(fromHandle,toHandle) - if not (fromHandle and toHandle) then return end - local memory = math.floor(computer.freeMemory()*0.8) - local tmpdata - while true do - tmpdata = fromHandle:read(memory) - if not tmpdata then break end - local status,reason = toHandle:write(tmpdata) - if status~=true then break end - end - fromHandle:close() - toHandle:close() -end - -local function copyRecursive(fromAddress,fromAbsPath,toAddress,toAbsPath) - -- TODO: make this use copyContent - if fromAbsPath:sub(-1)=="/" then fromAbsPath=fromAbsPath:sub(1,-2) end - if toAbsPath:sub(-1)=="/" then toAbsPath=toAbsPath:sub(1,-2) end - component.invoke(toAddress,"makeDirectory",toAbsPath) - local fileList,dirList = getRecursiveList(fromAddress,fromAbsPath) - for i=1,#dirList do - component.invoke(toAddress,"makeDirectory",toAbsPath.."/"..dirList[i]) - end - for i=1,#fileList do - local fromFile, toFile = fromAbsPath.."/"..fileList[i], toAbsPath.."/"..fileList[i] - --[[ local handle = component.invoke(fromAddress, "open", fromFile, "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", toFile, "w") - component.invoke(toAddress, "write", handle, data) - component.invoke(toAddress, "close", handle) ]] - local fromHandle = component.invoke(fromAddress, "open", fromFile, "r") - local toHandle = component.invoke(toAddress, "open", toFile, "w") - copyContent({ - ["read"]=function(...) return component.invoke(fromAddress, "read", handle, ...) end, - ["close"]=function(...) return component.invoke(fromAddress, "close", handle, ...) end - },{ - ["write"]=function(...) return component.invoke(fromAddress, "write", handle, ...) end, - ["close"]=function(...) return component.invoke(fromAddress, "close", handle, ...) end - }) - end -end - -function filesystem.isDirectory(path) - checkArg(1, path, "string") - local address, absPath = filesystem.absolutePath(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.absolutePath(fromPath) - local toAddress, toAbsPath = filesystem.absolutePath(toPath) - if not fromAddress or not toAddress then - return false - end - if fromAddress == toAddress then - return component.invoke(fromAddress, "rename", fromAbsPath, toAbsPath) - elseif filesystem.isDirectory(fromPath) then -- component.invoke(fromAddress, "isDirectory", fromAbsPath) then - copyRecursive(fromAddress,fromAbsPath,toAddress,toAbsPath) - filesystem.remove(fromPath) -- component.invoke(fromAddress,"remove", fromAbsPath) - else - local handle, data, tmpdata = filesystem.open(fromPath), "", nil -- component.invoke(fromAddress, "open", fromAbsPath, "r"), "", nil - repeat - tmpdata = handle:read(math.huge or math.maxinteger) -- component.invoke(fromAddress, "read", handle, math.huge or math.maxinteger) - data = data .. (tmpdata or "") - until not tmpdata - tmpdata = handle:close() -- component.invoke(fromAddress, "close", handle) - local handle = filesystem.open(toPath) -- component.invoke(toAddress, "open", toAbsPath, "w") - handle:write(data) -- component.invoke(toAddress, "write", handle, data) - handle:close() -- component.invoke(toAddress, "close", handle) - filesystem.remove(fromPath) -- component.invoke(fromAddress, "remove", fromAbsPath) - end -end - -function filesystem.copy(fromPath, toPath) - checkArg(1, fromPath, "string") - checkArg(2, toPath, "string") - local fromAddress, fromAbsPath = filesystem.absolutePath(fromPath) - local toAddress, toAbsPath = filesystem.absolutePath(toPath) - if not fromAddress or not toAddress then - return false - end - if filesystem.isDirectory(fromPath) then -- component.invoke(fromAddress, "isDirectory", fromAbsPath) - copyRecursive(fromAddress,fromAbsPath,toAddress,toAbsPath) - else - --[[ local handle = filesystem.open(fromPath,"r") - local data, tmpdata = "", nil - repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") - until not tmpdata - tmpdata = handle:close() - local handle = filesystem.open(toPath,"w") - handle:write(data) - handle:close() ]] - copyContent(filesystem.open(fromPath,"r"),filesystem.open(toPath,"w")) - end -end - -function filesystem.remove(path) - checkArg(1, path, "string") - local address, absPath = filesystem.absolutePath(path) - if not address then - return false - end - if absPath:find("^/special") then return false end - if absPath:find("^/tmp") then return false end - if absPath:find("^/mnt") then return false end - return component.invoke(address, "remove", absPath) -end - -function filesystem.makeDirectory(path) - checkArg(1, path, "string") - local address, absPath = filesystem.absolutePath(path) - if not address then - return false - end - return component.invoke(address, "makeDirectory", absPath) -end - -return(filesystem) +Error: no such file. (``) diff --git a/halyde/lib/json.lua b/halyde/lib/json.lua index 3aa0b76..fddefd5 100644 --- a/halyde/lib/json.lua +++ b/halyde/lib/json.lua @@ -1,4 +1 @@ --- json.lua by rxi --- Minified with luamin --- Original: https://github.com/rxi/json.lua -local a={_version="0.1.2"}local b;local c={["\\"]="\\",["\""]="\"",["\b"]="b",["\f"]="f",["\n"]="n",["\r"]="r",["\t"]="t"}local d={["/"]="/"}for e,f in pairs(c)do d[f]=e end;local function g(h)return"\\"..(c[h]or string.format("u%04x",h:byte()))end;local function i(j)return"null"end;local function k(j,l)local m={}l=l or{}if l[j]then error("circular reference")end;l[j]=true;if rawget(j,1)~=nil or next(j)==nil then local n=0;for e in pairs(j)do if type(e)~="number"then error("invalid table: mixed or invalid key types")end;n=n+1 end;if n~=#j then error("invalid table: sparse array")end;for o,f in ipairs(j)do table.insert(m,b(f,l))end;l[j]=nil;return"["..table.concat(m,",").."]"else for e,f in pairs(j)do if type(e)~="string"then error("invalid table: mixed or invalid key types")end;table.insert(m,b(e,l)..":"..b(f,l))end;l[j]=nil;return"{"..table.concat(m,",").."}"end end;local function p(j)return'"'..j:gsub('[%z\1-\31\\"]',g)..'"'end;local function q(j)if j~=j or j<=-math.huge or j>=math.huge then error("unexpected number value '"..tostring(j).."'")end;return string.format("%.14g",j)end;local r={["nil"]=i,["table"]=k,["string"]=p,["number"]=q,["boolean"]=tostring}b=function(j,l)local s=type(j)local t=r[s]if t then return t(j,l)end;error("unexpected type '"..s.."'")end;function a.encode(j)return b(j)end;local u;local function v(...)local m={}for o=1,select("#",...)do m[select(o,...)]=true end;return m end;local w=v(" ","\t","\r","\n")local x=v(" ","\t","\r","\n","]","}",",")local y=v("\\","/",'"',"b","f","n","r","t","u")local z=v("true","false","null")local A={["true"]=true,["false"]=false,["null"]=nil}local function B(C,D,E,F)for o=D,#C do if E[C:sub(o,o)]~=F then return o end end;return#C+1 end;local function G(C,D,H)local I=1;local J=1;for o=1,D-1 do J=J+1;if C:sub(o,o)=="\n"then I=I+1;J=1 end end;error(string.format("%s at line %d col %d",H,I,J))end;local function K(n)local t=math.floor;if n<=0x7f then return string.char(n)elseif n<=0x7ff then return string.char(t(n/64)+192,n%64+128)elseif n<=0xffff then return string.char(t(n/4096)+224,t(n%4096/64)+128,n%64+128)elseif n<=0x10ffff then return string.char(t(n/262144)+240,t(n%262144/4096)+128,t(n%4096/64)+128,n%64+128)end;error(string.format("invalid unicode codepoint '%x'",n))end;local function L(M)local N=tonumber(M:sub(1,4),16)local O=tonumber(M:sub(7,10),16)if O then return K((N-0xd800)*0x400+O-0xdc00+0x10000)else return K(N)end end;local function P(C,o)local m=""local Q=o+1;local e=Q;while Q<=#C do local R=C:byte(Q)if R<32 then G(C,Q,"control character in string")elseif R==92 then m=m..C:sub(e,Q-1)Q=Q+1;local h=C:sub(Q,Q)if h=="u"then local S=C:match("^[dD][89aAbB]%x%x\\u%x%x%x%x",Q+1)or C:match("^%x%x%x%x",Q+1)or G(C,Q-1,"invalid unicode escape in string")m=m..L(S)Q=Q+#S else if not y[h]then G(C,Q-1,"invalid escape char '"..h.."' in string")end;m=m..d[h]end;e=Q+1 elseif R==34 then m=m..C:sub(e,Q-1)return m,Q+1 end;Q=Q+1 end;G(C,o,"expected closing quote for string")end;local function T(C,o)local R=B(C,o,x)local M=C:sub(o,R-1)local n=tonumber(M)if not n then G(C,o,"invalid number '"..M.."'")end;return n,R end;local function U(C,o)local R=B(C,o,x)local V=C:sub(o,R-1)if not z[V]then G(C,o,"invalid literal '"..V.."'")end;return A[V],R end;local function W(C,o)local m={}local n=1;o=o+1;while 1 do local R;o=B(C,o,w,true)if C:sub(o,o)=="]"then o=o+1;break end;R,o=u(C,o)m[n]=R;n=n+1;o=B(C,o,w,true)local X=C:sub(o,o)o=o+1;if X=="]"then break end;if X~=","then G(C,o,"expected ']' or ','")end end;return m,o end;local function Y(C,o)local m={}o=o+1;while 1 do local Z,j;o=B(C,o,w,true)if C:sub(o,o)=="}"then o=o+1;break end;if C:sub(o,o)~='"'then G(C,o,"expected string for key")end;Z,o=u(C,o)o=B(C,o,w,true)if C:sub(o,o)~=":"then G(C,o,"expected ':' after key")end;o=B(C,o+1,w,true)j,o=u(C,o)m[Z]=j;o=B(C,o,w,true)local X=C:sub(o,o)o=o+1;if X=="}"then break end;if X~=","then G(C,o,"expected '}' or ','")end end;return m,o end;local _={['"']=P,["0"]=T,["1"]=T,["2"]=T,["3"]=T,["4"]=T,["5"]=T,["6"]=T,["7"]=T,["8"]=T,["9"]=T,["-"]=T,["t"]=U,["f"]=U,["n"]=U,["["]=W,["{"]=Y}u=function(C,D)local X=C:sub(D,D)local t=_[X]if t then return t(C,D)end;G(C,D,"unexpected character '"..X.."'")end;function a.decode(C)if type(C)~="string"then error("expected argument of type string, got "..type(C))end;local m,D=u(C,B(C,1,w,true))D=B(C,D,w,true)if D<=#C then G(C,D,"trailing garbage")end;return m end;return a +Error: no such file. (``) diff --git a/halyde/lib/md5.lua b/halyde/lib/md5.lua index 34937ab..fddefd5 100644 --- a/halyde/lib/md5.lua +++ b/halyde/lib/md5.lua @@ -1,27 +1 @@ --- md5.lua by kikito --- Minified with luamin --- Original: https://github.com/kikito/md5.lua -local a={_VERSION="md5.lua 1.1.0",_DESCRIPTION="MD5 computation in Lua (5.1-3, LuaJIT)",_URL="https://github.com/kikito/md5.lua",_LICENSE=[[ - MIT LICENSE - - Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -]]}local b,c,d,e,f=string.char,string.byte,string.format,string.rep,string.sub;local g,h,i,j,k,l;local m,n=pcall(require,'bit')local o,p=pcall(require,'ffi')if m then g,h,i,j,k,l=n.bor,n.band,n.bnot,n.bxor,n.rshift,n.lshift else m,n=pcall(require,'bit32')if m then i=n.bnot;local q=function(r)return r<=0x7fffffff and r or-(i(r)+1)end;local s=function(t)return function(u,v)return q(t(q(u),q(v)))end end;g,h,j=s(n.bor),s(n.band),s(n.bxor)k,l=s(n.rshift),s(n.lshift)else local function w(x)local y=0;local z=1;for A=1,#x do y=y+x[A]*z;z=z*2 end;return y end;local function B(C,D)local E,F=C,D;if#E<#F then E,F=F,E end;for A=#F+1,#E do F[A]=0 end end;local G;i=function(r)local x=G(r)local H=math.max(#x,32)for A=1,H do if x[A]==1 then x[A]=0 else x[A]=1 end end;return w(x)end;G=function(r)if r<0 then return G(i(math.abs(r))+1)end;local x={}local I=1;local J;while r>0 do J=r%2;x[I]=J;r=(r-J)/2;I=I+1 end;return x end;g=function(K,r)local L=G(K)local M=G(r)B(L,M)local x={}for A=1,#L do if L[A]==0 and M[A]==0 then x[A]=0 else x[A]=1 end end;return w(x)end;h=function(K,r)local L=G(K)local M=G(r)B(L,M)local x={}for A=1,#L do if L[A]==0 or M[A]==0 then x[A]=0 else x[A]=1 end end;return w(x)end;j=function(K,r)local L=G(K)local M=G(r)B(L,M)local x={}for A=1,#L do if L[A]~=M[A]then x[A]=1 else x[A]=0 end end;return w(x)end;k=function(r,N)local O=0;if r<0 then r=i(math.abs(r))+1;O=0x80000000 end;local P=math.floor;for A=1,N do r=r/2;r=g(P(r),O)end;return P(r)end;l=function(r,N)if r<0 then r=i(math.abs(r))+1 end;for A=1,N do r=r*2 end;return h(r,0xFFFFFFFF)end end end;local Q;if o then local R=p.typeof("int[1]")Q=function(A)return p.string(R(A),4)end else Q=function(A)local t=function(S)return b(h(k(A,S),255))end;return t(0)..t(8)..t(16)..t(24)end end;local function T(S)local U=0;for A=1,#S do U=U*256+c(S,A)end;return U end;local V;if o then local W=p.typeof("const char*")local X=p.typeof("const int*")V=function(S)local Y=W(S)return p.cast(X,Y)[0]end else V=function(S)local U=0;for A=#S,1,-1 do U=U*256+c(S,A)end;return U end end;local function Z(S)return{V(f(S,1,4)),V(f(S,5,8)),V(f(S,9,12)),V(f(S,13,16)),V(f(S,17,20)),V(f(S,21,24)),V(f(S,25,28)),V(f(S,29,32)),V(f(S,33,36)),V(f(S,37,40)),V(f(S,41,44)),V(f(S,45,48)),V(f(S,49,52)),V(f(S,53,56)),V(f(S,57,60)),V(f(S,61,64))}end;local _={0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391,0x67452301,0xefcdab89,0x98badcfe,0x10325476}local t=function(a0,a1,a2)return g(h(a0,a1),h(-a0-1,a2))end;local a3=function(a0,a1,a2)return g(h(a0,a2),h(a1,-a2-1))end;local a4=function(a0,a1,a2)return j(a0,j(a1,a2))end;local A=function(a0,a1,a2)return j(a1,g(a0,-a2-1))end;local a2=function(a5,u,v,a6,a7,a0,S,a8)u=h(u+a5(v,a6,a7)+a0+a8,0xFFFFFFFF)return g(l(h(u,k(0xFFFFFFFF,S)),S),k(u,32-S))+v end;local function a9(aa,ab,ac,ad,ae)local u,v,a6,a7=aa,ab,ac,ad;local af=_;u=a2(t,u,v,a6,a7,ae[0],7,af[1])a7=a2(t,a7,u,v,a6,ae[1],12,af[2])a6=a2(t,a6,a7,u,v,ae[2],17,af[3])v=a2(t,v,a6,a7,u,ae[3],22,af[4])u=a2(t,u,v,a6,a7,ae[4],7,af[5])a7=a2(t,a7,u,v,a6,ae[5],12,af[6])a6=a2(t,a6,a7,u,v,ae[6],17,af[7])v=a2(t,v,a6,a7,u,ae[7],22,af[8])u=a2(t,u,v,a6,a7,ae[8],7,af[9])a7=a2(t,a7,u,v,a6,ae[9],12,af[10])a6=a2(t,a6,a7,u,v,ae[10],17,af[11])v=a2(t,v,a6,a7,u,ae[11],22,af[12])u=a2(t,u,v,a6,a7,ae[12],7,af[13])a7=a2(t,a7,u,v,a6,ae[13],12,af[14])a6=a2(t,a6,a7,u,v,ae[14],17,af[15])v=a2(t,v,a6,a7,u,ae[15],22,af[16])u=a2(a3,u,v,a6,a7,ae[1],5,af[17])a7=a2(a3,a7,u,v,a6,ae[6],9,af[18])a6=a2(a3,a6,a7,u,v,ae[11],14,af[19])v=a2(a3,v,a6,a7,u,ae[0],20,af[20])u=a2(a3,u,v,a6,a7,ae[5],5,af[21])a7=a2(a3,a7,u,v,a6,ae[10],9,af[22])a6=a2(a3,a6,a7,u,v,ae[15],14,af[23])v=a2(a3,v,a6,a7,u,ae[4],20,af[24])u=a2(a3,u,v,a6,a7,ae[9],5,af[25])a7=a2(a3,a7,u,v,a6,ae[14],9,af[26])a6=a2(a3,a6,a7,u,v,ae[3],14,af[27])v=a2(a3,v,a6,a7,u,ae[8],20,af[28])u=a2(a3,u,v,a6,a7,ae[13],5,af[29])a7=a2(a3,a7,u,v,a6,ae[2],9,af[30])a6=a2(a3,a6,a7,u,v,ae[7],14,af[31])v=a2(a3,v,a6,a7,u,ae[12],20,af[32])u=a2(a4,u,v,a6,a7,ae[5],4,af[33])a7=a2(a4,a7,u,v,a6,ae[8],11,af[34])a6=a2(a4,a6,a7,u,v,ae[11],16,af[35])v=a2(a4,v,a6,a7,u,ae[14],23,af[36])u=a2(a4,u,v,a6,a7,ae[1],4,af[37])a7=a2(a4,a7,u,v,a6,ae[4],11,af[38])a6=a2(a4,a6,a7,u,v,ae[7],16,af[39])v=a2(a4,v,a6,a7,u,ae[10],23,af[40])u=a2(a4,u,v,a6,a7,ae[13],4,af[41])a7=a2(a4,a7,u,v,a6,ae[0],11,af[42])a6=a2(a4,a6,a7,u,v,ae[3],16,af[43])v=a2(a4,v,a6,a7,u,ae[6],23,af[44])u=a2(a4,u,v,a6,a7,ae[9],4,af[45])a7=a2(a4,a7,u,v,a6,ae[12],11,af[46])a6=a2(a4,a6,a7,u,v,ae[15],16,af[47])v=a2(a4,v,a6,a7,u,ae[2],23,af[48])u=a2(A,u,v,a6,a7,ae[0],6,af[49])a7=a2(A,a7,u,v,a6,ae[7],10,af[50])a6=a2(A,a6,a7,u,v,ae[14],15,af[51])v=a2(A,v,a6,a7,u,ae[5],21,af[52])u=a2(A,u,v,a6,a7,ae[12],6,af[53])a7=a2(A,a7,u,v,a6,ae[3],10,af[54])a6=a2(A,a6,a7,u,v,ae[10],15,af[55])v=a2(A,v,a6,a7,u,ae[1],21,af[56])u=a2(A,u,v,a6,a7,ae[8],6,af[57])a7=a2(A,a7,u,v,a6,ae[15],10,af[58])a6=a2(A,a6,a7,u,v,ae[6],15,af[59])v=a2(A,v,a6,a7,u,ae[13],21,af[60])u=a2(A,u,v,a6,a7,ae[4],6,af[61])a7=a2(A,a7,u,v,a6,ae[11],10,af[62])a6=a2(A,a6,a7,u,v,ae[2],15,af[63])v=a2(A,v,a6,a7,u,ae[9],21,af[64])return h(aa+u,0xFFFFFFFF),h(ab+v,0xFFFFFFFF),h(ac+a6,0xFFFFFFFF),h(ad+a7,0xFFFFFFFF)end;local function ag(self,S)self.pos=self.pos+#S;S=self.buf..S;for ah=1,#S-63,64 do local ae=Z(f(S,ah,ah+63))assert(#ae==16)ae[0]=table.remove(ae,1)self.a,self.b,self.c,self.d=a9(self.a,self.b,self.c,self.d,ae)end;self.buf=f(S,math.floor(#S/64)*64+1,#S)return self end;local function ai(self)local aj=self.pos;local ak=56-aj%64;if aj%64>56 then ak=ak+64 end;if ak==0 then ak=64 end;local S=b(128)..e(b(0),ak-1)..Q(h(8*aj,0xFFFFFFFF))..Q(math.floor(aj/0x20000000))ag(self,S)assert(self.pos%64==0)return Q(self.a)..Q(self.b)..Q(self.c)..Q(self.d)end;function a.new()return{a=_[65],b=_[66],c=_[67],d=_[68],pos=0,buf='',update=ag,finish=ai}end;function a.tohex(S)return d("%08x%08x%08x%08x",T(f(S,1,4)),T(f(S,5,8)),T(f(S,9,12)),T(f(S,13,16)))end;function a.sum(S)return a.new():update(S):finish()end;function a.sumhexa(S)return a.tohex(a.sum(S))end;return a +Error: no such file. (``) diff --git a/halyde/lib/raster.lua b/halyde/lib/raster.lua index 2709b75..fddefd5 100644 --- a/halyde/lib/raster.lua +++ b/halyde/lib/raster.lua @@ -1,432 +1 @@ -local raster = { - ["units"]={}, - ["defaultBackgroundColor"]=0x000000, - ["defaultForegroundColor"]=0xFFFFFF, - ["displayWidth"]=0, - ["displayHeight"]=0, - ["charWidth"]=0, - ["charHeight"]=0, - ["backgroundColor"]=0xFFFFFF -} - -local component = import("component") --- local ocelot = component.proxy(component.list("ocelot")()) -local gpu = component.gpu - -local display = {} -local chunksAffected = {} - -local renderBuffer = nil - --- braille rendering - -function raster.units.charToBraille(x,y) - return x*2,y*4 -end - -function raster.units.brailleToChar(x,y) - return math.ceil(x/2),math.ceil(y/4) -end - -function raster.init(width, height, bgcolor) - -- NOTE: Width and height are in characters, not pixels in braille. - -- If the width and height are nil, the entire screen will be used. - if width==nil and height==nil then - width, height = gpu.getResolution() - end - - raster.charWidth = width - raster.charHeight = height - - width, height = raster.units.charToBraille(width, height) - - bgcolor = bgcolor or raster.defaultBackgroundColor - if bgcolor~=0 then - for i=1,width*height do - display[i]=bgcolor - end - end - - raster.displayWidth = width - raster.displayHeight = height - raster.backgroundColor = bgcolor - - pcall(function() - renderBuffer = gpu.allocateBuffer() - end) - - raster.clear() -end - -function raster.set(x, y, color) - if x<1 or x>raster.displayWidth or y<1 or y>raster.displayHeight then - return false - end - - color = color or raster.defaultForegroundColor - local i = x+y*raster.displayWidth - display[i] = color - - local ci = math.floor((x-1)/2)+math.floor((y-1)/4)*raster.charWidth+1 - -- ocelot.log(x..","..y..":"..ci) - chunksAffected[ci] = true - - return true -end - -function raster.get(x, y) - local i = x+y*raster.displayWidth - return display[i] or raster.backgroundColor -end - -local function stats(arr) - local out = {} - for i=1,#arr do - local v = arr[i] - if out[v]==nil then - out[v]=1 - else - out[v] = out[v] + 1 - end - end - return out -end - -local function getKeys(t) - local keys = {} - for k,v in pairs(t) do - table.insert(keys,{k,v}) - end - table.sort(keys,function(a,b) - return a[2]>b[2] - end) - for i=1,#keys do - keys[i] = keys[i][1] - end - return keys -end - -local function colorDifference(a,b) - return ((a>>16)&255)-((b>>16)&255)+((a>>8)&255)-((b>>8)&255)+(a&255)-(b&255) -end - -local function limitTwoColors(arr) - local colors = getKeys(stats(arr)) - for i=1,#arr do - local v=arr[i] - if v==colors[1] then - arr[i]=0 - goto continue - elseif v==colors[2] then - arr[i]=1 - goto continue - else - --error("Pixel is not in the two colors (raster.lua:90)") - -- get closest color so atleast it kinda shows - if colorDifference(v,colors[1]) -dy then - err = err - dy - x1 = x1 + sx - end - - if e2 < dx then - err = err + dx - y1 = y1 + sy - end - end -end - -function raster.drawRect(x1,y1,x2,y2,col) - x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2) - if x1 > x2 then x1, x2 = x2, x1 end - if y1 > y2 then y1, y2 = y2, y1 end - for x=x1,x2 do - raster.set(x,y1,col) - raster.set(x,y2,col) - end - for y=y1+1,y2-1 do - raster.set(x1,y,col) - raster.set(x2,y,col) - end -end - -function raster.fillRect(x1,y1,x2,y2,col) - x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2) - if x1 > x2 then x1, x2 = x2, x1 end - if y1 > y2 then y1, y2 = y2, y1 end - for x=x1,x2 do - for y=y1,y2 do - raster.set(x,y,col) - end - end -end - -function raster.drawCircle(xc, yc, radius, color) - xc=math.floor(xc) - yc=math.floor(yc) - radius=math.floor(radius) - local x = 0 - local y = radius - local d = 3 - 2 * radius - - while y >= x do - -- Draw 8 symmetric points - raster.set(xc + x, yc + y, color) - raster.set(xc - x, yc + y, color) - raster.set(xc + x, yc - y, color) - raster.set(xc - x, yc - y, color) - raster.set(xc + y, yc + x, color) - raster.set(xc - y, yc + x, color) - raster.set(xc + y, yc - x, color) - raster.set(xc - y, yc - x, color) - - if d < 0 then - d = d + 4 * x + 6 - else - d = d + 4 * (x - y) + 10 - y = y - 1 - end - x = x + 1 - end -end - -function raster.drawEllipse(x1, y1, x2, y2, color) - if x1 > x2 then x1, x2 = x2, x1 end - if y1 > y2 then y1, y2 = y2, y1 end - - local xc = math.floor((x1 + x2) / 2) - local yc = math.floor((y1 + y2) / 2) - - local a = math.floor((x2 - x1) / 2) - local b = math.floor((y2 - y1) / 2) - - if a <= 0 or b <= 0 then - return - end - - if a == b then - raster.drawCircle(xc, yc, a, color) - return - end - - if a <= 1 and b <= 1 then - raster.set(xc, yc, color) - return - elseif a <= 1 then - for y = yc - b, yc + b do - raster.set(xc, y, color) - end - return - elseif b <= 1 then - for x = xc - a, xc + a do - raster.set(x, yc, color) - end - return - end - - local x = 0 - local y = b - local a2 = a * a - local b2 = b * b - - local d1 = b2 - (a2 * b) + (0.25 * a2) - local dx = 2 * b2 * x - local dy = 2 * a2 * y - - while dx < dy do - raster.set(xc + x, yc + y, color) - raster.set(xc - x, yc + y, color) - raster.set(xc + x, yc - y, color) - - if d1 < 0 then - x = x + 1 - dx = dx + (2 * b2) - d1 = d1 + dx + b2 - else - x = x + 1 - y = y - 1 - dx = dx + (2 * b2) - dy = dy - (2 * a2) - d1 = d1 + dx - dy + b2 - end - end - - local d2 = b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2 - - while y >= 0 do - raster.set(xc + x, yc + y, color) - raster.set(xc - x, yc + y, color) - raster.set(xc + x, yc - y, color) - raster.set(xc - x, yc - y, color) - - if d2 > 0 then - y = y - 1 - dy = dy - (2 * a2) - d2 = d2 - dy + a2 - else - y = y - 1 - x = x + 1 - dx = dx + (2 * b2) - dy = dy - (2 * a2) - d2 = d2 + dx - dy + a2 - end - end -end - -function raster.fillCircle(x, y, r, color) - x, y = math.floor(x + 0.5), math.floor(y + 0.5) - r = math.floor(r + 0.5) - - if r <= 0 then return end - - local minX, maxX = x - r, x + r - local minY, maxY = y - r, y + r - - for py = minY, maxY do - for px = minX, maxX do - local dx, dy = px - x, py - y - local distSquared = dx*dx + dy*dy - - if distSquared <= r*r then - raster.set(px, py, color) - end - end - end -end - -function raster.fillEllipse(x1, y1, x2, y2, color) - local centerX = (x1 + x2) / 2 - local centerY = (y1 + y2) / 2 - - local a = math.abs(x2 - x1) / 2 - local b = math.abs(y2 - y1) / 2 - - centerX = math.floor(centerX + 0.5) - centerY = math.floor(centerY + 0.5) - a = math.floor(a + 0.5) - b = math.floor(b + 0.5) - - if a <= 0 or b <= 0 then return end - - if a == b then - raster.fillCircle(centerX, centerY, a, color) - return - end - - local minX = centerX - a - local maxX = centerX + a - local minY = centerY - b - local maxY = centerY + b - - for y = minY, maxY do - for x = minX, maxX do - local dx = x - centerX - local dy = y - centerY - local value = (dx*dx)/(a*a) + (dy*dy)/(b*b) - - if value <= 1 then - raster.set(x, y, color) - end - end - end -end - -return raster +Error: no such file. (``) diff --git a/halyde/lib/serialize.lua b/halyde/lib/serialize.lua index eaefccf..fddefd5 100644 --- a/halyde/lib/serialize.lua +++ b/halyde/lib/serialize.lua @@ -1,125 +1 @@ -local serialize = {} - -function serialize.string(str) - return '"'..str:gsub("[%z\1-\31\34\92\127-\159]",function(c) - local byte = c:byte() - if byte== 7 then return "\\a" end - if byte== 8 then return "\\b" end - if byte== 9 then return "\\t" end - if byte==10 then return "\\n" end - if byte==11 then return "\\v" end - if byte==12 then return "\\f" end - if byte==13 then return "\\r" end - if byte==34 then return "\\\"" end - if byte==92 then return "\\\\" end - return string.format("\\x%02x",byte) - end)..'"' -end - -function serialize.table(tbl,colors,stack) - stack = table.copy(stack or {}) - table.insert(stack,tbl) - local keyAmount = 0 - local keyNumber = true - local out = "" - local first = true - - for key,val in pairs(tbl) do - if not first then out=out..",\n" end - first=false - out=out.." " - if type(key)=="string" then - if key:match("^[%a_][%w_]*$") then - out=out..key.."=" - else - out=out..'['..serialize.string(key)..']=' - end - else - out=out.."["..tostring(key).."]=" - end - if type(key)~="number" then - keyNumber=false - end - - local success,reason = pcall(function() - local valStr = "" - if type(val)=="table" then - if #stack>4 or table.find(stack,val) then - valStr="..." - else - valStr=serialize.table(val,colors,stack) - end - elseif type(val)=="string" then - local lines = {} - for line in (val.."\n"):gmatch("([^\n]*)\n") do table.insert(lines,line) end - if #lines[#lines]==0 then - lines[#lines]=nil - lines[#lines]=lines[#lines].."\n" - end - for i=1,#lines do - if i<#lines then - lines[i]=serialize.string(lines[i].."\n") - else - lines[i]=serialize.string(lines[i]) - end - end - valStr=table.concat(lines," ..\n ") - else - valStr=tostring(val) - end - local lines = {} - for line in (valStr.."\n"):gmatch("([^\n]*)\n") do table.insert(lines,line) end - out=out..table.concat(lines,"\n ") - lines = nil - keyAmount=keyAmount+1 - end) - if not success then - if colors then out=out.."\x1b[91m" end - out=out.."["..tostring(reason).."]" - if colors then out=out.."\x1b[39m" end - end - coroutine.yield() - end - - local metatbl = getmetatable(tbl) - local metakeys = {} - if type(metatbl)=="table" then - for i,v in pairs(metatbl) do - keyNumber=false - table.insert(metakeys,i) - end - end - if #metakeys>0 then - out=out.."\n " - if colors then out=out.."\x1b[92m" end - if table.find(metakeys,"__tostring") then - out=out.."tostring: "..serialize.string(tostring(tbl)).."\n " - table.remove(metakeys,table.find(metakeys,"__tostring")) - end - out=out..table.concat(metakeys,", ") - if colors then out=out.."\x1b[39m" end - end - - if keyAmount==0 then return "{}" end - if keyNumber then - -- fix strings not being serialised - local vals = {} - for _,v in pairs(tbl) do - if #vals>=5 and #stack>1 then - table.insert(vals,"...") - break - end - if type(v)=="table" then - table.insert(vals,serialize.table(v,colors,stack)) - elseif type(v)=="string" then - table.insert(vals,serialize.string(v)) - else - table.insert(vals,tostring(v)) - end - end - return "{"..table.concat(vals,", ").."}" - end - return "{\n"..out.."\n}" -end - -return serialize +Error: no such file. (``) diff --git a/halyde/lib/unicode.lua b/halyde/lib/unicode.lua index 5f44fab..fddefd5 100644 --- a/halyde/lib/unicode.lua +++ b/halyde/lib/unicode.lua @@ -1,102 +1 @@ -local unicodeLib -local LLunicode -if table.copy then - unicodeLib = table.copy(unicode) - LLunicode = table.copy(unicode) -else - unicodeLib = {} - LLunicode = unicode -end - -function unicodeLib.readCodePoint(readByte) - checkArg(1,readByte,"function") - - local function inRange(min,max,...) - for _,v in ipairs({...}) do - if not (v and v>=min and v1 then - if not chooseDrive() then - reset() - return - end -end -if not installLocation then - reset() - io.stderr.write("All drives are read-only.\nHalyde cannot be installed.") - return -end - -if width<80 then - gpu.set(1,1,"Are you sure you would like to install Halyde?") -else - gpu.set(1,1,"Are you sure you would like to install Halyde to "..installLocation.."?") -end -gpu.set(1,2,"This will erase all data on this disk.") -gpu.set(1,height-1,"Press Y to accept, or N to cancel.") -gpu.set(3,4,"Capacity: ") -gpu.set(3,5,"Used: ") -gpu.set(3,6,"ID: ") -gpu.set(3,7,"Label: ") -gpu.setForeground(0x00FF00) -if width>=80 then - gpu.set(50,1,installLocation) -end -gpu.set(13,4,math.floor(component.invoke(installAddress,"spaceTotal")/1024).." KiB") -gpu.set(9,5,math.floor(component.invoke(installAddress,"spaceUsed")/1024).." KiB") -gpu.set(7,6,installAddress) -gpu.set(10,7,component.invoke(installAddress,"getLabel") or "No label") - -if keyboard.keys[({event.pull("key_down")})[4]]=="n" then - return reset() -end - --- installation - -local computer = require("computer") - -local function getFile(url) - local request, data, tmpdata = nil, "", nil - local status, errorMessage = pcall(function() - request = internet.request(url) - request:finishConnect() - end) - if not status then - return false, errorMessage - end - local responseCode = request:response() - if responseCode and responseCode ~= 200 then - return false, responseCode - end - repeat - tmpdata = request.read(math.huge) - data = data .. (tmpdata or "") - until not tmpdata - return data -end - --- installation graphics -local webInstallConfig -local installationOrder = {"halyde", "edit", "argentum", "webinstall-extras"} - -gpu.setBackground(0x000000) -gpu.setForeground(0xFFFFFF) -gpu.fill(1,1,width,height," ") - -local function lpad(str, len, char) - str=tostring(str) - if char == nil then char = ' ' end - return string.rep(char, len - #str) .. str -end - -local function progress(package,progress) - local total = 0 - if webInstallConfig and type(webInstallConfig)=="table" then - for i,pck in ipairs(installationOrder) do - local packConfig = webInstallConfig[pck] - -- print(pck,packConfig) - total=total+#(packConfig.directories or {})+#(packConfig.files or {}) - end - else - total=1 - end - - local info = "" - local realProgress = 1 - if type(package)=="string" then - realProgress = progress - info = string.format("%s %s%%",package,lpad(math.floor(progress*100),2)) - else - realProgress = 0 - for i=1,package do - local packConfig = webInstallConfig[installationOrder[i]] - if i==package then - realProgress=realProgress+progress - else - local value = #(packConfig.directories or {})+#packConfig.files - realProgress=realProgress+value - end - end - realProgress=realProgress/total - local packConfig = webInstallConfig[installationOrder[package]] - progress=progress/(#(packConfig.directories or {})+#packConfig.files) - -- realProgress = (progress+package-1)/#installationOrder - local packInfo = installationOrder[package].." "..lpad(math.floor(progress*100),2).."%" - info = string.format("%s%% [%s]",lpad(math.floor(realProgress*100),2),packInfo) - end - - info=info..string.rep(" ",width-#info) - local progX = math.floor(realProgress*width) - gpu.setBackground(0x00FF00) - gpu.setForeground(0x000000) - gpu.set(1,height,info:sub(1,progX)) - gpu.setBackground(0x000000) - gpu.setForeground(0xFFFFFF) - gpu.set(progX+1,height,info:sub(progX+1)) -end -local logY = 1 -local function log(txt) - if logY>=height then - gpu.copy(1,2,width,height-2,0,-1) - gpu.fill(1,height-1,width,1," ") - logY=logY-1 - end - gpu.set(1,logY,txt) - logY=logY+1 -end ----------------------------- - -log("Fetching Argentum configuration for Halyde") -progress("Preparing",0) -webInstallConfig = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/argentum.cfg") -log("Loading Argentum configuration") -progress("Preparing",0.5) -webInstallConfig = load(webInstallConfig) -webInstallConfig = webInstallConfig() -log("Looking for outdated files in the drive") -progress("Preparing",1) -local oldFiles = {} -for oldFile in fs.list(installLocation) do - local usedFlag = false - for i = 1, 3 do - for _, file in pairs(webInstallConfig[installationOrder[i]].files) do - if oldFile == file then - usedFlag = true - end - end - if webInstallConfig[installationOrder[i]].directories then - for _, dir in pairs(webInstallConfig[installationOrder[i]].directories) do - if oldFile == dir .. "/" then - usedFlag = true - end - end - end - end - if oldFile=="halyde/" then usedFlag = true end - if not usedFlag then - table.insert(oldFiles, oldFile) - end -end -log("Found "..#oldFiles) -progress(1,0) - -for i = 1, 4 do - local webInstallConfig = webInstallConfig[installationOrder[i]] - local dirCount = 0 - if webInstallConfig.directories then - dirCount=#webInstallConfig.directories - for dirIdx, directory in ipairs(webInstallConfig.directories) do - log("Creating " .. directory .. "...") - progress(i,dirIdx-1) - fs.makeDirectory(installLocation .. directory) - end - end - for fileIdx, file in ipairs(webInstallConfig.files) do - log("Downloading " .. file .. "...") - progress(i,fileIdx-1+dirCount) - local handle = fs.open(installLocation .. file, "w") - handle:write(getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/" .. file)) - handle:close() - end -end -for i, oldFile in ipairs(oldFiles) do - log("Removing "..oldFile) - progress("Finishing up",(i-1)/#oldFiles*1) - fs.remove(installLocation .. oldFile) -end - -log("Setting boot address") -progress("Finishing up",1) -computer.setBootAddress(component.get(installLocation:sub(6, -2))) - -log("Setting label to Halyde") -component.invoke(component.get(installLocation:sub(6, -2)), "setLabel", "Halyde") - -gpu.fill(1,1,width,height," ") -computer.shutdown(true) +Error: no such file. (``)