Compare commits
37 Commits
8aa08814a1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b6a29b5cf | |||
| a3b70d0d23 | |||
| a45c02b93a | |||
| 1d05b2e26d | |||
| 00b4ffe174 | |||
| 0e70c533c3 | |||
| 61a584c9f5 | |||
| 5f66a5d7d5 | |||
| 2c754288e8 | |||
| 1df95d386d | |||
| 060ef9113c | |||
| 4cc5f8b743 | |||
| 129f5f6d34 | |||
| 420421ca9d | |||
| 6e0d4a7bf1 | |||
| c1901f2098 | |||
| e0e26e12c9 | |||
| e6436a8373 | |||
| 895636a22e | |||
| b6b4a4cb23 | |||
| 9eebc6da2c | |||
| 8468ec31ec | |||
| f89474af9b | |||
| ed6862cf41 | |||
| c9b23c2371 | |||
| 236bf8487e | |||
| 21127b18ff | |||
| 2864ff60de | |||
| 184f15bbab | |||
| ac867ddff7 | |||
| ae7083d23b | |||
| f76bef395a | |||
| 6bf6f119b2 | |||
| 6e51cddc81 | |||
| 2a2b27a827 | |||
| 9581d5ce52 | |||
| 2dee5eaba7 |
@@ -0,0 +1,14 @@
|
||||
const fs = require("fs")
|
||||
const luamin = require('lua-format')
|
||||
|
||||
const Code = fs.readFileSync(process.argv[2],"utf-8")
|
||||
const Settings = {
|
||||
RenameVariables: true,
|
||||
RenameGlobals: false,
|
||||
SolveMath: false,
|
||||
Indentation: '\t'
|
||||
}
|
||||
|
||||
const Beautified = luamin.Beautify(Code, Settings)
|
||||
const Minified = luamin.Minify(Code, Settings)
|
||||
fs.writeFileSync(process.argv[2],Minified)
|
||||
@@ -0,0 +1,57 @@
|
||||
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: 25.6.1
|
||||
|
||||
- name: Switch to minified branch
|
||||
run: git checkout minified
|
||||
|
||||
- name: Copy files from main
|
||||
run: |
|
||||
git checkout main -- .
|
||||
git reset HEAD
|
||||
|
||||
- name: Just do the whole damn thing
|
||||
run: |
|
||||
cd .github/workflows
|
||||
npm install github:Ponali/luamin.js
|
||||
for file in $(find ../.. -name "*.lua" -not -path "../../.git/*" -not -path "../../.github/*"); do
|
||||
echo $file
|
||||
node minify.js $file
|
||||
done
|
||||
cd ../..
|
||||
|
||||
- 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 $(find . -name "*.lua" -not -path "./.git/*" -not -path "./.github/*")
|
||||
git commit -m "${{ steps.commit.outputs.message }} (minified)"
|
||||
git push origin minified
|
||||
+7
-97
@@ -1,100 +1,10 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/LuaLS/lua-language-server/master/locale/en-us/setting.lua",
|
||||
"runtime": {
|
||||
"version": "Lua 5.3",
|
||||
"special": {},
|
||||
"unicodeName": false,
|
||||
"nonstandardSymbol": []
|
||||
},
|
||||
"workspace": {
|
||||
"checkThirdParty": false,
|
||||
"maxPreload": 5000,
|
||||
"preloadFileSize": 500
|
||||
},
|
||||
"diagnostics": {
|
||||
"disable": [
|
||||
"undefined-global",
|
||||
"lowercase-global"
|
||||
"diagnostics.globals": [
|
||||
"checkArg",
|
||||
"computer",
|
||||
"component"
|
||||
],
|
||||
"globals": [
|
||||
"_G",
|
||||
"_VERSION",
|
||||
"assert",
|
||||
"error",
|
||||
"getmetatable",
|
||||
"ipairs",
|
||||
"load",
|
||||
"next",
|
||||
"pairs",
|
||||
"pcall",
|
||||
"rawequal",
|
||||
"rawget",
|
||||
"rawlen",
|
||||
"rawset",
|
||||
"select",
|
||||
"setmetatable",
|
||||
"tonumber",
|
||||
"tostring",
|
||||
"type",
|
||||
"xpcall",
|
||||
"checkArg",
|
||||
"bit32",
|
||||
"coroutine",
|
||||
"debug",
|
||||
"math",
|
||||
"os",
|
||||
"string",
|
||||
"table",
|
||||
"component",
|
||||
"computer",
|
||||
"unicode",
|
||||
"utf8"
|
||||
"diagnostics.disable": [
|
||||
"lowercase-global"
|
||||
]
|
||||
},
|
||||
"completion": {
|
||||
"enable": true,
|
||||
"callSnippet": "Both",
|
||||
"keywordSnippet": "Both",
|
||||
"displayContext": 6
|
||||
},
|
||||
"hover": {
|
||||
"enable": true,
|
||||
"viewString": true,
|
||||
"viewStringMax": 1000,
|
||||
"viewNumber": true,
|
||||
"fieldInfer": 3000,
|
||||
"previewFields": 50,
|
||||
"enumsLimit": 5
|
||||
},
|
||||
"semantic": {
|
||||
"enable": true,
|
||||
"variable": true,
|
||||
"annotation": true,
|
||||
"keyword": false
|
||||
},
|
||||
"format": {
|
||||
"enable": true,
|
||||
"defaultConfig": {
|
||||
"indent_style": "space",
|
||||
"indent_size": "2",
|
||||
"tab_width": "2"
|
||||
}
|
||||
},
|
||||
"spell": {
|
||||
"dict": []
|
||||
},
|
||||
"telemetry": {
|
||||
"enable": false
|
||||
},
|
||||
"IntelliSense": {
|
||||
"traceLocalSet": false,
|
||||
"traceReturn": false,
|
||||
"traceBeSetted": false,
|
||||
"traceFieldInject": false
|
||||
},
|
||||
"type": {
|
||||
"castNumberToInteger": false,
|
||||
"weakUnionCheck": false,
|
||||
"weakNilCheck": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,25 @@
|
||||
# Halyde
|
||||
A universal, customizable and feature-packed operating system for OpenComputers.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://lua.org/">
|
||||
<img src="https://img.shields.io/badge/Written_in-Lua-blue?style=plastic&logo=lua" /></a>
|
||||
<a href="https://ocdoc.cil.li/">
|
||||
<img src="https://img.shields.io/badge/Made_for-OpenComputers-yellow?style=plastic" /></a>
|
||||
<a href="https://cerulean-blue.gitbook.io/halyde-docs">
|
||||
<img src="https://img.shields.io/badge/Documented_on-GitBook-green?style=plastic&logo=gitbook" /></a>
|
||||
</p>
|
||||
|
||||
## Installation
|
||||
To install Halyde from OpenOS, simply run:
|
||||
|
||||
`pastebin run MB21BTMv`
|
||||
|
||||
If for some reason that doesn't work, try:
|
||||
|
||||
`wget -f https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/webinstall.lua /tmp/webinstall.lua && /tmp/webinstall.lua`
|
||||
|
||||
## Docs
|
||||
Halyde is [documented on GitBook](https://cerulean-blue.gitbook.io/halyde-docs).
|
||||
# Halyde
|
||||
### If you are viewing on GitHub: Halyde has moved to [Gitea](https://git.sting.lt/Cerulean-Blue/Halyde). This repository is now a read-only mirror. Contributions, issues and pull requests will not be processed here. Please go to [the Gitea instance](https://git.sting.lt/Cerulean-Blue/Halyde) for that.
|
||||
|
||||
A universal, customizable and feature-packed operating system for OpenComputers.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://lua.org/">
|
||||
<img src="https://img.shields.io/badge/Written_in-Lua-blue?style=plastic&logo=lua" /></a>
|
||||
<a href="https://ocdoc.cil.li/">
|
||||
<img src="https://img.shields.io/badge/Made_for-OpenComputers-yellow?style=plastic" /></a>
|
||||
<a href="https://wiki.sting.lt/">
|
||||
<img src="https://img.shields.io/badge/Documented_on-DokuWiki-green?style=plastic" /></a>
|
||||
</p>
|
||||
|
||||
## Installation
|
||||
To install Halyde from OpenOS, simply run:
|
||||
|
||||
`pastebin run MB21BTMv`
|
||||
|
||||
If for some reason that doesn't work, try:
|
||||
|
||||
`wget -f https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/webinstall.lua /tmp/webinstall.lua && /tmp/webinstall.lua`
|
||||
|
||||
## Docs
|
||||
Halyde is [documented on DokuWiki](https://wiki.sting.lt/), however there is an alternative documentation on [GitBook](https://cerulean-blue.gitbook.io/halyde-docs/).
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ local agcfg = {
|
||||
},
|
||||
["argentum"] = {
|
||||
["maindir"] = "",
|
||||
["version"] = "1.3.1",
|
||||
["version"] = "1.3.3",
|
||||
["description"] = "The default package manager for Halyde.",
|
||||
["directories"] = {
|
||||
"argentum",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
local agregistry = {
|
||||
["halyde"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
|
||||
["edit"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
|
||||
@@ -8,7 +9,11 @@ local agregistry = {
|
||||
["hextra"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
|
||||
["utape"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
|
||||
["libctif"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
|
||||
["ctif-viewer"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/"
|
||||
["ctif-viewer"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
|
||||
["libsha256"] = "https://raw.githubusercontent.com/tema5002/ag-packages/refs/heads/main/",
|
||||
["sha256sum"] = "https://raw.githubusercontent.com/tema5002/ag-packages/refs/heads/main/",
|
||||
["base64"] = "https://raw.githubusercontent.com/mcplayer3/AgPackages/refs/heads/main/",
|
||||
["gitget"] = "https://raw.githubusercontent.com/mcplayer3/AgPackages/refs/heads/main/"
|
||||
}
|
||||
|
||||
return agregistry
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Aargentum/store/
|
||||
Aargentum/
|
||||
V1.2.0
|
||||
V1.3.3
|
||||
Aargentum/registry.cfg
|
||||
Ahalyde/apps/argentum.lua
|
||||
Ahalyde/apps/helpdb/argentum.txt
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
local packages = {...}
|
||||
local command = packages[1]
|
||||
table.remove(packages, 1)
|
||||
local fs = require("filesystem")
|
||||
local component = require("component")
|
||||
local agReg = require("/argentum/registry.cfg")
|
||||
local fs = import("filesystem")
|
||||
local component = import("component")
|
||||
local agReg = import("/argentum/registry.cfg")
|
||||
if not command then
|
||||
shell.run("help argentum")
|
||||
return
|
||||
@@ -346,7 +346,7 @@ if command == "install" then
|
||||
else
|
||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||
end
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
agReg = import("/argentum/registry.cfg")
|
||||
while true do
|
||||
if not doChecks(packages[i]) then
|
||||
table.insert(fails, packages[i])
|
||||
@@ -497,7 +497,7 @@ elseif command == "update" then
|
||||
else
|
||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||
end
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
agReg = import("/argentum/registry.cfg")
|
||||
if not packages[1] then
|
||||
local packagesInstalled = fs.list("/argentum/store/")
|
||||
for _, currentPackage in pairs(packagesInstalled) do
|
||||
@@ -632,7 +632,7 @@ elseif command == "info" then
|
||||
else
|
||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||
end
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
agReg = import("/argentum/registry.cfg")
|
||||
if not agReg[packages[1]] and not source then
|
||||
print("\27[91mPackage " .. packages[1] .. " does not exist.")
|
||||
return
|
||||
@@ -656,7 +656,7 @@ elseif command == "search" then
|
||||
else
|
||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||
end
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
agReg = import("/argentum/registry.cfg")
|
||||
local searchResults = {}
|
||||
for packageName, _ in pairs(agReg) do
|
||||
if packageName:find(packages[1], 1, true) then
|
||||
@@ -679,7 +679,7 @@ elseif command == "list" then
|
||||
else
|
||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||
end
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
agReg = import("/argentum/registry.cfg")
|
||||
local sortedPackages = {}
|
||||
for packageName, _ in pairs(agReg) do
|
||||
table.insert(sortedPackages, packageName)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
local component = import("component")
|
||||
local computer = import("computer")
|
||||
local args = {...}
|
||||
|
||||
local force = false
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
local files = {...}
|
||||
local fs = require("filesystem")
|
||||
local fs = import("filesystem")
|
||||
if not files or not files[1] then
|
||||
shell.run("help cat")
|
||||
return
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
local directory = ...
|
||||
local fs = require("filesystem")
|
||||
local fs = import("filesystem")
|
||||
|
||||
if not directory then
|
||||
return
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
local fromFile, toFile = ...
|
||||
local fs = require("filesystem")
|
||||
local fs = import("filesystem")
|
||||
|
||||
if not fromFile or not toFile then
|
||||
shell.run("help cp")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
local url = ...
|
||||
|
||||
local component = require("component")
|
||||
local fs = require("filesystem")
|
||||
local component = import("component")
|
||||
local fs = import("filesystem")
|
||||
|
||||
if not component.list("internet")() then
|
||||
print("\27[91mThis program requires an internet card to run.")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
local file = ...
|
||||
local fs = require("filesystem")
|
||||
local event = require("event")
|
||||
local component = require("component")
|
||||
local unicode = require("unicode")
|
||||
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
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
local component = import("component")
|
||||
local computer = import("computer")
|
||||
|
||||
local function printstat(text)
|
||||
terminal.cursorPosX = 35
|
||||
terminal.write(text .. "\n", false)
|
||||
termlib.cursorPosX = 35
|
||||
termlib.write(text .. "\n", false)
|
||||
end
|
||||
|
||||
terminal.write(_OSLOGO, false)
|
||||
terminal.cursorPosY = terminal.cursorPosY - 17
|
||||
termlib.write(_OSLOGO, false)
|
||||
termlib.cursorPosY = termlib.cursorPosY - 17
|
||||
printstat("\27[92mOS\27[0m: ".._OSVERSION)
|
||||
printstat("\27[92mArchitecture\27[0m: ".._VERSION)
|
||||
local componentCounter = 0
|
||||
@@ -15,7 +15,7 @@ for _, _ in component.list() do
|
||||
componentCounter = componentCounter + 1
|
||||
end
|
||||
printstat("\27[92mComponents\27[0m: "..tostring(componentCounter))
|
||||
printstat("\27[92mCoroutines\27[0m: "..tostring(#tsched.getTasks()))
|
||||
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()
|
||||
@@ -67,4 +67,4 @@ 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 ")
|
||||
terminal.cursorPosY = terminal.cursorPosY + 5
|
||||
termlib.cursorPosY = termlib.cursorPosY + 5
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
local fs = require("filesystem")
|
||||
local fs = import("filesystem")
|
||||
local args = {...}
|
||||
local command = args[1]
|
||||
args = nil
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
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
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
local args = {...}
|
||||
local target = args[1]
|
||||
args = nil
|
||||
local fs = require("filesystem")
|
||||
local unicode = require("unicode")
|
||||
local fs = import("filesystem")
|
||||
local unicode = import("unicode")
|
||||
local maxLength = 0
|
||||
local margin = 2 -- minimum space between filename and size
|
||||
local dirTable = {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
local serialize = require("serialize")
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
local unicode = require("unicode")
|
||||
local serialize = import("serialize")
|
||||
local component = import("component")
|
||||
local computer = import("computer")
|
||||
local unicode = import("unicode")
|
||||
|
||||
local width,height = component.gpu.getResolution()
|
||||
|
||||
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
print("\27[44m".._VERSION.."\27[0m shell")
|
||||
print('Type "exit" to exit.')
|
||||
termlib.readHistory["lua"] = {""}
|
||||
local fs = require("filesystem")
|
||||
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") .. ' = require("' .. lib:match("(.+)%.lua") .. '")\n'
|
||||
loadedLibraries = loadedLibraries .. "local " .. lib:match("(.+)%.lua") .. ' = import("' .. lib:match("(.+)%.lua") .. '")\n'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
local computer = require("computer")
|
||||
local computer = import("computer")
|
||||
|
||||
if type(computer)~="table" then
|
||||
return print("\x1b[91mComputer library returned '"..type(computer).."' type\x1b[39m")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local directory = ...
|
||||
local fs = require("filesystem")
|
||||
local fs = import("filesystem")
|
||||
|
||||
if not directory then
|
||||
shell.run("help mkdir")
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
local fromFile, toFile = ...
|
||||
local fs = require("filesystem")
|
||||
local fs = import("filesystem")
|
||||
|
||||
if not fromFile or not toFile then
|
||||
shell.run("help mv")
|
||||
|
||||
@@ -1 +1 @@
|
||||
require("computer").shutdown(true)
|
||||
import("computer").shutdown(true)
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
local file = ...
|
||||
local fs = require("filesystem")
|
||||
local fs = import("filesystem")
|
||||
|
||||
if not file then
|
||||
shell.run("help rm")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
local raster = require("raster")
|
||||
local raster = import("raster")
|
||||
|
||||
raster.init()
|
||||
|
||||
@@ -15,7 +15,7 @@ end]]
|
||||
end
|
||||
end ]]
|
||||
|
||||
local event = require("event")
|
||||
local event = import("event")
|
||||
local x=0
|
||||
local y=0
|
||||
local vx=1
|
||||
@@ -88,4 +88,4 @@ end
|
||||
end ]]
|
||||
|
||||
raster.free()
|
||||
termlib.cursorPosY=1
|
||||
termlib.cursorPosY=1
|
||||
@@ -1,7 +1,7 @@
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
local raster = require("raster")
|
||||
local event = require("event")
|
||||
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
|
||||
|
||||
@@ -1 +1 @@
|
||||
require("computer").shutdown()
|
||||
import("computer").shutdown()
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"prompt":"\u001b[92m%s > \u001b[0m","aliases":{"move":"mv","copy":"cp","ag":"argentum","rename":"mv","..":"cd ..","man":"help","del":"rm","delete":"rm","ren":"mv","remove":"rm","list":"ls","wget":"download","dir":"ls","ps":"lscor","poweroff":"shutdown","restart":"reboot","lsblk":"lsdrv"},"splashMessages":["Made by John Haly- I mean Cerulean Blue.","Welcome! Type \"help\" to get started.","Also try KOCOS!","Welcome back, Commander. We have no idea what we're doing.","99.9% bug-free. The remaining 0.1% are features.","0 days since last error.","Everything is fine. The fire is decorative.","Please don't feed the background processes.","Also has fetch!","Anything red is no man's land. Trust me.","Machine...","Abort, Retry, Fail?","What's the deal with /argentum/store?","So cutting-edge you can't hold it in your hand.","Americans are the reason you see colors on-screen. I'm talking about ANSI escape codes, not politics.","Shoutout to Ponali!","Now i% more secure!"],"path":["/halyde/apps/"],"startupMessage":"\n │\n │ %s\n │ %s\n │\n ","defaultWorkingDirectory":"/home/"}
|
||||
{"prompt":"\u001b[92m%s > \u001b[0m","aliases":{"move":"mv","copy":"cp","ag":"argentum","rename":"mv","..":"cd ..","man":"help","del":"rm","delete":"rm","ren":"mv","remove":"rm","list":"ls","wget":"download","dir":"ls","ps":"lscor","poweroff":"shutdown","restart":"reboot","lsblk":"lsdrv"},"splashMessages":["Made by John Haly- I mean Cerulean Blue.","Welcome! Type \"help\" to get started.","Also try KOCOS!","Welcome back, Commander. We have no idea what we're doing.","99.9% bug-free. The remaining 0.1% are features.","0 days since last error.","Everything is fine. The fire is decorative.","Please don't feed the background processes.","Also has fetch!","Anything red is no man's land. Trust me.","Machine...","Abort, Retry, Fail?","What's the deal with /argentum/store?","So cutting-edge you can't hold it in your hand.","Americans are the reason you see colors on-screen. I'm talking about ANSI escape codes, not politics.","Shoutout to Ponali!"],"path":["/halyde/apps/"],"startupMessage":"\n │\n │ %s\n │ %s\n │\n ","defaultWorkingDirectory":"/home/"}
|
||||
|
||||
@@ -1 +1 @@
|
||||
["/halyde/shell/shell.lua"]
|
||||
["/halyde/core/fullkb.lua","/halyde/core/evmgr.lua","/halyde/core/drvload.lua","/halyde/core/shell.lua"]
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
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")
|
||||
@@ -0,0 +1,97 @@
|
||||
_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
|
||||
@@ -0,0 +1,46 @@
|
||||
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
|
||||
@@ -2,11 +2,11 @@ _G.evmgr = {}
|
||||
_G.evmgr.eventQueue = {}
|
||||
local maxEventQueueLength = 10 -- increase if events start getting dropped
|
||||
|
||||
local computer = require("computer")
|
||||
local computer = import("computer")
|
||||
|
||||
_G._PUBLIC.keyboard.ctrlDown = false
|
||||
_G._PUBLIC.keyboard.altDown = false
|
||||
_G._PUBLIC.keyboard.shiftDown = false
|
||||
keyboard.ctrlDown = false
|
||||
keyboard.altDown = false
|
||||
keyboard.shiftDown = false
|
||||
|
||||
--local ocelot = component.proxy(component.list("ocelot")())
|
||||
|
||||
@@ -16,31 +16,31 @@ while true do
|
||||
args = {computer.uptime(), computer.pullSignal(0)}
|
||||
if args and args[2] then
|
||||
table.insert(evmgr.eventQueue, args)
|
||||
if _PUBLIC.keyboard then
|
||||
if keyboard then
|
||||
if args[2] == "key_down" then
|
||||
local keycode = args[5]
|
||||
local key = _PUBLIC.keyboard.keys[keycode]
|
||||
local key = keyboard.keys[keycode]
|
||||
if key == "lcontrol" then
|
||||
_PUBLIC.keyboard.ctrlDown = true
|
||||
keyboard.ctrlDown = true
|
||||
elseif key == "lmenu" then
|
||||
_PUBLIC.keyboard.altDown = true
|
||||
keyboard.altDown = true
|
||||
elseif key == "lshift" then
|
||||
_PUBLIC.keyboard.shiftDown = true
|
||||
elseif key == "c" and _PUBLIC.keyboard.ctrlDown and _PUBLIC.keyboard.altDown then
|
||||
keyboard.shiftDown = true
|
||||
elseif key == "c" and keyboard.ctrlDown and keyboard.altDown then
|
||||
if print then
|
||||
print("\n\27[91mCoroutine "..tostring(#tsched.tasks).." killed.")
|
||||
print("\n\27[91mCoroutine "..tostring(#cormgr.corList).." killed.")
|
||||
end
|
||||
tsched.tasks[#tsched.tasks] = nil
|
||||
cormgr.corList[#cormgr.corList] = nil
|
||||
end
|
||||
elseif args[2] == "key_up" then
|
||||
local keycode = args[5]
|
||||
local key = _PUBLIC.keyboard.keys[keycode]
|
||||
local key = keyboard.keys[keycode]
|
||||
if key == "lcontrol" then
|
||||
_PUBLIC.keyboard.ctrlDown = false
|
||||
keyboard.ctrlDown = false
|
||||
elseif key == "lmenu" then
|
||||
_PUBLIC.keyboard.altDown = false
|
||||
keyboard.altDown = false
|
||||
elseif key == "lshift" then
|
||||
_PUBLIC.keyboard.shiftDown = true
|
||||
keyboard.shiftDown = true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,143 @@
|
||||
_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
|
||||
})
|
||||
@@ -1,5 +1,5 @@
|
||||
local fs = require("filesystem")
|
||||
local json = require("json")
|
||||
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)
|
||||
@@ -7,21 +7,23 @@ repeat
|
||||
until not tmpdata
|
||||
handle:close()
|
||||
local shellcfg = json.decode(data)
|
||||
local component = require("component")
|
||||
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 runAsTask(path, ...)
|
||||
local function runAsCoroutine(path, ...)
|
||||
--ocelot.log("running " .. path .. " as coroutine")
|
||||
tsched.runAsTask(path, ...)
|
||||
local corIndex = #tsched.getTasks()
|
||||
local task = tsched.getTasks()[#tsched.getTasks()]
|
||||
cormgr.loadCoroutine(path, ...)
|
||||
local corIndex = #cormgr.corList
|
||||
local cor = cormgr.corList[#cormgr.corList]
|
||||
repeat
|
||||
coroutine.yield()
|
||||
until tsched.getTasks()[corIndex] ~= task
|
||||
until cormgr.corList[corIndex] ~= cor
|
||||
end
|
||||
|
||||
function _G.shell.run(command)
|
||||
@@ -64,14 +66,14 @@ function _G.shell.run(command)
|
||||
if fs.exists(args[1]) and not fs.isDirectory(args[1]) then
|
||||
local path = args[1]
|
||||
table.remove(args, 1)
|
||||
runAsTask(path, table.unpack(args))
|
||||
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)
|
||||
runAsTask(path, table.unpack(args))
|
||||
runAsCoroutine(path, table.unpack(args))
|
||||
return
|
||||
else -- try to look for it without the file extension
|
||||
local files = fs.list(item) or {}
|
||||
@@ -79,7 +81,7 @@ function _G.shell.run(command)
|
||||
-- previous pattern: (.+)%.[^%.]+$
|
||||
if args[1] == file:match("(.+)%.[^%.]+$") and not fs.isDirectory(item .. file) then
|
||||
table.remove(args, 1)
|
||||
runAsTask(item .. file, table.unpack(args))
|
||||
runAsCoroutine(item .. file, table.unpack(args))
|
||||
return
|
||||
end
|
||||
end
|
||||
@@ -98,7 +100,7 @@ while true do
|
||||
if shell.workingDirectory:sub(-1, -1) ~= "/" then
|
||||
shell.workingDirectory = shell.workingDirectory .. "/"
|
||||
end
|
||||
local shellCommand = terminal.read("shell", shellcfg.prompt:format(shell.workingDirectory))
|
||||
local shellCommand = read("shell", shellcfg.prompt:format(shell.workingDirectory))
|
||||
shell.run(shellCommand)
|
||||
gpu.freeAllBuffers()
|
||||
end
|
||||
@@ -0,0 +1,453 @@
|
||||
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 maxChars<math.huge then
|
||||
chr=unicode.sub(chr,1,maxChars-unicode.len(text))
|
||||
end
|
||||
text=unicode.sub(text,1,cur-1)..chr..unicode.sub(text,cur)
|
||||
set(curPos(cur),chr,false)
|
||||
cur=math.min(cur+unicode.len(chr),maxChars+1)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
cursorBlink = true
|
||||
set(curPos(cur+1),unicode.sub(text,cur+1),false)
|
||||
end
|
||||
local function moveCur(dir)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false)
|
||||
cur=math.max(math.min(cur+dir,unicode.len(text)+1),1)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
cursorBlink = true
|
||||
end
|
||||
local function isLetter(chr)
|
||||
return not string.find("\x09 :@-./_~?&=%+#",chr,1,true)
|
||||
end
|
||||
local function nextCur(dir,chr,icur)
|
||||
if icur==nil then icur=cur end
|
||||
local next = math.max(math.min(icur+dir,unicode.len(text)+1),1)
|
||||
if chr then return unicode.sub(text,next,next) end
|
||||
return next
|
||||
end
|
||||
local function curAfterWord(dir)
|
||||
local ncur = cur
|
||||
while nextCur(dir,false,ncur)~=ncur and isLetter(nextCur(dir,true,ncur))==(dir==1) do
|
||||
ncur=nextCur(dir,false,ncur)
|
||||
end
|
||||
while nextCur(dir,false,ncur)~=ncur and isLetter(nextCur(dir,true,ncur))==(dir==-1) do
|
||||
ncur=nextCur(dir,false,ncur)
|
||||
end
|
||||
return ncur
|
||||
end
|
||||
local function moveWord(dir)
|
||||
if nextCur(dir)==cur then return end
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false)
|
||||
cur=curAfterWord(dir)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
cursorBlink = true
|
||||
end
|
||||
local function deleteWord(dir)
|
||||
local after = curAfterWord(dir)
|
||||
local lenb = unicode.wlen(text)
|
||||
if dir==1 then
|
||||
text=unicode.sub(text,1,cur-1)..unicode.sub(text,after)
|
||||
set(curPos(cur+1),unicode.sub(text,cur+1)..string.rep(" ",lenb-unicode.wlen(text)+1),false)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
else
|
||||
text = unicode.sub(text,1,after-1)..unicode.sub(text,cur)
|
||||
cur=after
|
||||
set(curPos(cur+1),unicode.sub(text,cur+1)..string.rep(" ",lenb-unicode.wlen(text)+1),false)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
end
|
||||
updateHistory()
|
||||
cursorBlink = true
|
||||
end
|
||||
local function isLine(chr)
|
||||
return chr=="\n" or chr=="\r"
|
||||
end
|
||||
--[[ gpu.set(startX,startY,unicode.sub(text,1,width-startX))
|
||||
for i=1,(#text+startX)//width-1 do
|
||||
gpu.set(startX,startY+i,unicode.sub(text,1+i*width,width-startX+i*width))
|
||||
end ]]
|
||||
set(1,text,false)
|
||||
set(curPos(cur)," ",true)
|
||||
|
||||
local function reprint(new)
|
||||
set(1,new..string.rep(" ",unicode.wlen(text)-unicode.wlen(new)+1),false)
|
||||
cur=unicode.len(new)+1
|
||||
text=new
|
||||
set(curPos(cur)," ",true)
|
||||
end
|
||||
|
||||
while true do
|
||||
local args = {event.pull("key_down", "clipboard", 0.5)}
|
||||
if args and args[1] == "key_down" and args[4] then
|
||||
local key = keyboard.keys[args[4]]
|
||||
if key=="up" and readHistoryType then
|
||||
historyIdx=math.max(historyIdx-1,1)
|
||||
reprint(termlib.readHistory[readHistoryType][historyIdx])
|
||||
elseif key=="down" and readHistoryType then
|
||||
historyIdx=math.min(historyIdx+1,#termlib.readHistory[readHistoryType])
|
||||
reprint(termlib.readHistory[readHistoryType][historyIdx])
|
||||
elseif key=="left" and keyboard.ctrlDown then
|
||||
moveWord(-1)
|
||||
elseif key=="right" and keyboard.ctrlDown then
|
||||
moveWord(1)
|
||||
elseif key=="left" then
|
||||
moveCur(-1)
|
||||
elseif key=="right" then
|
||||
moveCur(1)
|
||||
elseif key=="home" then
|
||||
moveCur(-math.huge)
|
||||
elseif key=="end" then
|
||||
moveCur(math.huge)
|
||||
elseif key=="back" and keyboard.ctrlDown then
|
||||
deleteWord(-1)
|
||||
elseif key=="delete" and keyboard.ctrlDown then
|
||||
deleteWord(1)
|
||||
elseif key=="back" and cur>1 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
|
||||
@@ -1,73 +0,0 @@
|
||||
local loadfile = ...
|
||||
local filesystem = assert(loadfile("/lib/filesystem.lua")(loadfile))
|
||||
_G._OSVERSION = "HALYDE VERSION" -- TODO: Put this in a separate config file
|
||||
_G._OSLOGO = ""
|
||||
_G._PUBLIC = {}
|
||||
local ocelot = component.proxy(component.list("ocelot")())
|
||||
|
||||
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/kernel/modules/datatools.lua")()
|
||||
|
||||
function _G.require(module, ...)
|
||||
ocelot.log("Requiring " .. 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("/lib/" .. module .. ".lua") then
|
||||
modulepath = "/lib/" .. module .. ".lua"
|
||||
elseif shell and shell.workingDirectory and filesystem.exists(filesystem.concat(shell.workingDirectory, module .. ".lua")) then
|
||||
modulepath = shell.workingDirectory .. module .. ".lua"
|
||||
end
|
||||
assert(modulepath, "Module not found\nPossible locations:\n/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
|
||||
|
||||
function _G.package.preload(module)
|
||||
local handle, data, tmpdata = assert(filesystem.open("/lib/" .. module .. ".lua", "r")), "", nil
|
||||
repeat
|
||||
tmpdata = handle:read(math.huge or math.maxinteger)
|
||||
data = data .. (tmpdata or "")
|
||||
until not tmpdata
|
||||
handle:close()
|
||||
package.preloaded[module] = assert(load(data, "="..module))()
|
||||
_G[module] = nil
|
||||
end
|
||||
|
||||
require("/halyde/kernel/datatools.lua") -- If this is not imported BEFORE modload gets run, modload requires filesystem which requires computer which requires datatools.
|
||||
require("/halyde/kernel/modload.lua")
|
||||
|
||||
package.preload("component")
|
||||
package.preload("computer")
|
||||
|
||||
local component = require("component")
|
||||
local gpu = component.gpu
|
||||
local screenAddress = component.list("screen")()
|
||||
|
||||
gpu.bind(screenAddress)
|
||||
gpu.setResolution(gpu.maxResolution())
|
||||
|
||||
if not filesystem.exists("/halyde/config/shell.json") then -- Auto-generate configs
|
||||
filesystem.copy("/halyde/config/generate/shell.json", "/halyde/config/shell.json")
|
||||
end
|
||||
if not filesystem.exists("/halyde/config/startupapps.json") then
|
||||
filesystem.copy("/halyde/config/generate/startupapps.json", "/halyde/config/startupapps.json")
|
||||
end
|
||||
|
||||
require("/halyde/kernel/tsched.lua")
|
||||
@@ -1,53 +0,0 @@
|
||||
local fs = require("filesystem")
|
||||
local ocelot = require("component").ocelot
|
||||
|
||||
local modulePath = "/halyde/kernel/modules"
|
||||
|
||||
local modules = fs.list(modulePath)
|
||||
local moduleTypes = {}
|
||||
|
||||
local function loadModule(modName)
|
||||
ocelot.log("Checking module " .. modName)
|
||||
local moduleData = require(fs.concat(modulePath, modName))
|
||||
table.remove(modules, table.find(modules, modName))
|
||||
if not moduleData.check() then
|
||||
return
|
||||
end
|
||||
ocelot.log("Loading module " .. modName)
|
||||
if moduleData.dependencies then
|
||||
for _, dependency in pairs(moduleData.dependencies) do
|
||||
if table.find(modules, dependency) then
|
||||
loadModule(dependency)
|
||||
elseif table.find(modules, dependency .. ".lua") then
|
||||
loadModule(dependency .. ".lua")
|
||||
else
|
||||
for typeLookupDrvName, typeLookupDrvType in pairs(moduleTypes) do
|
||||
if typeLookupDrvType == dependency then
|
||||
loadModule(typeLookupDrvName)
|
||||
-- Don't break, because there can be multiple modules of the correct type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--print(modName)
|
||||
if moduleData.init then -- I have no idea why this would not exist, but it's a failsafe
|
||||
moduleData.init()
|
||||
end
|
||||
end
|
||||
|
||||
for _, modName in pairs(modules) do -- Get all the module types
|
||||
local moduleData = require(fs.concat(modulePath, modName))
|
||||
if moduleData.type then
|
||||
--print(moduleData.type)
|
||||
moduleTypes[modName] = moduleData.type -- Not the other way around because there can be multiple modules of the same type, but there can't be multiple entries with the same key
|
||||
end
|
||||
end
|
||||
|
||||
while modules[1] do
|
||||
if modules[1]:sub(-1, -1) ~= "/" then -- Check if it's not a directory. If it is, it might be module config
|
||||
loadModule(modules[1])
|
||||
end
|
||||
end
|
||||
|
||||
ocelot.log("Finished loading modules!")
|
||||
@@ -1,53 +0,0 @@
|
||||
local module = {}
|
||||
|
||||
module.dependencies = {"terminal"}
|
||||
|
||||
function module.check()
|
||||
return true -- This module should always be loaded
|
||||
end
|
||||
|
||||
function module.init()
|
||||
local publicTable = {
|
||||
"print",
|
||||
"require",
|
||||
"_VERSION",
|
||||
"_OSVERSION",
|
||||
"assert",
|
||||
"error",
|
||||
"getmetatable",
|
||||
"ipairs",
|
||||
"load",
|
||||
"next",
|
||||
"pairs",
|
||||
"pcall",
|
||||
"rawequal",
|
||||
"rawget",
|
||||
"rawlen",
|
||||
"rawset",
|
||||
"select",
|
||||
"setmetatable",
|
||||
"tonumber",
|
||||
"tostring",
|
||||
"type",
|
||||
"xpcall",
|
||||
"bit32",
|
||||
"coroutine",
|
||||
"debug",
|
||||
"math",
|
||||
"os",
|
||||
"string",
|
||||
"table",
|
||||
"checkArg",
|
||||
"utf8",
|
||||
"convert"
|
||||
}
|
||||
for _, value in ipairs(publicTable) do
|
||||
_G._PUBLIC[value] = table.copy(_G[value])
|
||||
end
|
||||
end
|
||||
|
||||
function module.exit()
|
||||
_G._PUBLIC = nil
|
||||
end
|
||||
|
||||
return module
|
||||
@@ -1,15 +0,0 @@
|
||||
local module = {}
|
||||
|
||||
function module.check()
|
||||
return true -- This module should always be loaded
|
||||
end
|
||||
|
||||
function module.init()
|
||||
|
||||
end
|
||||
|
||||
function module.exit()
|
||||
|
||||
end
|
||||
|
||||
return module
|
||||
@@ -1,157 +0,0 @@
|
||||
local module = {}
|
||||
|
||||
function module.check()
|
||||
return true -- This module should always be loaded
|
||||
end
|
||||
|
||||
function module.init()
|
||||
_G._PUBLIC.keyboard = {["keys"] = {}}
|
||||
|
||||
_PUBLIC.keyboard.keys["1"] = 0x02
|
||||
_PUBLIC.keyboard.keys["2"] = 0x03
|
||||
_PUBLIC.keyboard.keys["3"] = 0x04
|
||||
_PUBLIC.keyboard.keys["4"] = 0x05
|
||||
_PUBLIC.keyboard.keys["5"] = 0x06
|
||||
_PUBLIC.keyboard.keys["6"] = 0x07
|
||||
_PUBLIC.keyboard.keys["7"] = 0x08
|
||||
_PUBLIC.keyboard.keys["8"] = 0x09
|
||||
_PUBLIC.keyboard.keys["9"] = 0x0A
|
||||
_PUBLIC.keyboard.keys["0"] = 0x0B
|
||||
_PUBLIC.keyboard.keys.a = 0x1E
|
||||
_PUBLIC.keyboard.keys.b = 0x30
|
||||
_PUBLIC.keyboard.keys.c = 0x2E
|
||||
_PUBLIC.keyboard.keys.d = 0x20
|
||||
_PUBLIC.keyboard.keys.e = 0x12
|
||||
_PUBLIC.keyboard.keys.f = 0x21
|
||||
_PUBLIC.keyboard.keys.g = 0x22
|
||||
_PUBLIC.keyboard.keys.h = 0x23
|
||||
_PUBLIC.keyboard.keys.i = 0x17
|
||||
_PUBLIC.keyboard.keys.j = 0x24
|
||||
_PUBLIC.keyboard.keys.k = 0x25
|
||||
_PUBLIC.keyboard.keys.l = 0x26
|
||||
_PUBLIC.keyboard.keys.m = 0x32
|
||||
_PUBLIC.keyboard.keys.n = 0x31
|
||||
_PUBLIC.keyboard.keys.o = 0x18
|
||||
_PUBLIC.keyboard.keys.p = 0x19
|
||||
_PUBLIC.keyboard.keys.q = 0x10
|
||||
_PUBLIC.keyboard.keys.r = 0x13
|
||||
_PUBLIC.keyboard.keys.s = 0x1F
|
||||
_PUBLIC.keyboard.keys.t = 0x14
|
||||
_PUBLIC.keyboard.keys.u = 0x16
|
||||
_PUBLIC.keyboard.keys.v = 0x2F
|
||||
_PUBLIC.keyboard.keys.w = 0x11
|
||||
_PUBLIC.keyboard.keys.x = 0x2D
|
||||
_PUBLIC.keyboard.keys.y = 0x15
|
||||
_PUBLIC.keyboard.keys.z = 0x2C
|
||||
|
||||
_PUBLIC.keyboard.keys.apostrophe = 0x28
|
||||
_PUBLIC.keyboard.keys.at = 0x91
|
||||
_PUBLIC.keyboard.keys.back = 0x0E -- backspace
|
||||
_PUBLIC.keyboard.keys.backslash = 0x2B
|
||||
_PUBLIC.keyboard.keys.capital = 0x3A -- capslock
|
||||
_PUBLIC.keyboard.keys.colon = 0x92
|
||||
_PUBLIC.keyboard.keys.comma = 0x33
|
||||
_PUBLIC.keyboard.keys.enter = 0x1C
|
||||
_PUBLIC.keyboard.keys.equals = 0x0D
|
||||
_PUBLIC.keyboard.keys.grave = 0x29 -- accent grave
|
||||
_PUBLIC.keyboard.keys.lbracket = 0x1A
|
||||
_PUBLIC.keyboard.keys.lcontrol = 0x1D
|
||||
_PUBLIC.keyboard.keys.lmenu = 0x38 -- left Alt
|
||||
_PUBLIC.keyboard.keys.lshift = 0x2A
|
||||
_PUBLIC.keyboard.keys.minus = 0x0C
|
||||
_PUBLIC.keyboard.keys.numlock = 0x45
|
||||
_PUBLIC.keyboard.keys.pause = 0xC5
|
||||
_PUBLIC.keyboard.keys.period = 0x34
|
||||
_PUBLIC.keyboard.keys.rbracket = 0x1B
|
||||
_PUBLIC.keyboard.keys.rcontrol = 0x9D
|
||||
_PUBLIC.keyboard.keys.rmenu = 0xB8 -- right Alt
|
||||
_PUBLIC.keyboard.keys.rshift = 0x36
|
||||
_PUBLIC.keyboard.keys.scroll = 0x46 -- Scroll Lock
|
||||
_PUBLIC.keyboard.keys.semicolon = 0x27
|
||||
_PUBLIC.keyboard.keys.slash = 0x35 -- / on main _PUBLIC.keyboard
|
||||
_PUBLIC.keyboard.keys.space = 0x39
|
||||
_PUBLIC.keyboard.keys.stop = 0x95
|
||||
_PUBLIC.keyboard.keys.tab = 0x0F
|
||||
_PUBLIC.keyboard.keys.underline = 0x93
|
||||
|
||||
-- Keypad (and numpad with numlock off)
|
||||
_PUBLIC.keyboard.keys.up = 0xC8
|
||||
_PUBLIC.keyboard.keys.down = 0xD0
|
||||
_PUBLIC.keyboard.keys.left = 0xCB
|
||||
_PUBLIC.keyboard.keys.right = 0xCD
|
||||
_PUBLIC.keyboard.keys.home = 0xC7
|
||||
_PUBLIC.keyboard.keys["end"] = 0xCF
|
||||
_PUBLIC.keyboard.keys.pageUp = 0xC9
|
||||
_PUBLIC.keyboard.keys.pageDown = 0xD1
|
||||
_PUBLIC.keyboard.keys.insert = 0xD2
|
||||
_PUBLIC.keyboard.keys.delete = 0xD3
|
||||
|
||||
-- Function keys
|
||||
_PUBLIC.keyboard.keys.f1 = 0x3B
|
||||
_PUBLIC.keyboard.keys.f2 = 0x3C
|
||||
_PUBLIC.keyboard.keys.f3 = 0x3D
|
||||
_PUBLIC.keyboard.keys.f4 = 0x3E
|
||||
_PUBLIC.keyboard.keys.f5 = 0x3F
|
||||
_PUBLIC.keyboard.keys.f6 = 0x40
|
||||
_PUBLIC.keyboard.keys.f7 = 0x41
|
||||
_PUBLIC.keyboard.keys.f8 = 0x42
|
||||
_PUBLIC.keyboard.keys.f9 = 0x43
|
||||
_PUBLIC.keyboard.keys.f10 = 0x44
|
||||
_PUBLIC.keyboard.keys.f11 = 0x57
|
||||
_PUBLIC.keyboard.keys.f12 = 0x58
|
||||
_PUBLIC.keyboard.keys.f13 = 0x64
|
||||
_PUBLIC.keyboard.keys.f14 = 0x65
|
||||
_PUBLIC.keyboard.keys.f15 = 0x66
|
||||
_PUBLIC.keyboard.keys.f16 = 0x67
|
||||
_PUBLIC.keyboard.keys.f17 = 0x68
|
||||
_PUBLIC.keyboard.keys.f18 = 0x69
|
||||
_PUBLIC.keyboard.keys.f19 = 0x71
|
||||
|
||||
-- Japanese keyboards
|
||||
_PUBLIC.keyboard.keys.kana = 0x70
|
||||
_PUBLIC.keyboard.keys.kanji = 0x94
|
||||
_PUBLIC.keyboard.keys.convert = 0x79
|
||||
_PUBLIC.keyboard.keys.noconvert = 0x7B
|
||||
_PUBLIC.keyboard.keys.yen = 0x7D
|
||||
_PUBLIC.keyboard.keys.circumflex = 0x90
|
||||
_PUBLIC.keyboard.keys.ax = 0x96
|
||||
|
||||
-- Numpad
|
||||
_PUBLIC.keyboard.keys.numpad0 = 0x52
|
||||
_PUBLIC.keyboard.keys.numpad1 = 0x4F
|
||||
_PUBLIC.keyboard.keys.numpad2 = 0x50
|
||||
_PUBLIC.keyboard.keys.numpad3 = 0x51
|
||||
_PUBLIC.keyboard.keys.numpad4 = 0x4B
|
||||
_PUBLIC.keyboard.keys.numpad5 = 0x4C
|
||||
_PUBLIC.keyboard.keys.numpad6 = 0x4D
|
||||
_PUBLIC.keyboard.keys.numpad7 = 0x47
|
||||
_PUBLIC.keyboard.keys.numpad8 = 0x48
|
||||
_PUBLIC.keyboard.keys.numpad9 = 0x49
|
||||
_PUBLIC.keyboard.keys.numpadmul = 0x37
|
||||
_PUBLIC.keyboard.keys.numpaddiv = 0xB5
|
||||
_PUBLIC.keyboard.keys.numpadsub = 0x4A
|
||||
_PUBLIC.keyboard.keys.numpadadd = 0x4E
|
||||
_PUBLIC.keyboard.keys.numpaddecimal = 0x53
|
||||
_PUBLIC.keyboard.keys.numpadcomma = 0xB3
|
||||
_PUBLIC.keyboard.keys.numpadenter = 0x9C
|
||||
_PUBLIC.keyboard.keys.numpadequals = 0x8D
|
||||
|
||||
-- Create inverse mapping for name lookup.
|
||||
setmetatable(_PUBLIC.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
|
||||
})
|
||||
end
|
||||
|
||||
function module.exit()
|
||||
_G._PUBLIC.keyboard = nil
|
||||
end
|
||||
|
||||
return module
|
||||
@@ -1,466 +0,0 @@
|
||||
local module = {}
|
||||
|
||||
function module.check()
|
||||
return true -- Usually always loaded, but maybe it would be worth it to check if the computer has a GPU or not? I'm not sure.
|
||||
end
|
||||
|
||||
function module.init()
|
||||
local serialize = require("serialize")
|
||||
local unicode = require("unicode")
|
||||
local event = require("event")
|
||||
|
||||
--local ocelot = component.proxy(component.list("ocelot")())
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
local gpu = component.gpu
|
||||
_G._PUBLIC.terminal = {}
|
||||
_PUBLIC.terminal.cursorPosX = 1
|
||||
_PUBLIC.terminal.cursorPosY = 1
|
||||
_PUBLIC.terminal.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)
|
||||
_PUBLIC.terminal.cursorPosY=height
|
||||
end
|
||||
end
|
||||
|
||||
local function newLine()
|
||||
_PUBLIC.terminal.cursorPosX=1
|
||||
_PUBLIC.terminal.cursorPosY = _PUBLIC.terminal.cursorPosY + 1
|
||||
if _PUBLIC.terminal.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 _PUBLIC.terminal.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(_PUBLIC.terminal.cursorPosX,_PUBLIC.terminal.cursorPosY,section)
|
||||
if unicode.wlen(section) > width - _PUBLIC.terminal.cursorPosX + 1 and textWrap then
|
||||
section = section:sub(width - _PUBLIC.terminal.cursorPosX + 2)
|
||||
newLine()
|
||||
else
|
||||
_PUBLIC.terminal.cursorPosX = _PUBLIC.terminal.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()
|
||||
_PUBLIC.terminal.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(_PUBLIC.terminal.cursorPosX,_PUBLIC.terminal.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
|
||||
_PUBLIC.terminal.write(table.concat(stringArgs, " ") .. "\n")
|
||||
end
|
||||
|
||||
function _G._PUBLIC.terminal.clear()
|
||||
width, height = gpu.getResolution()
|
||||
gpu.setForeground(defaultForegroundColor)
|
||||
gpu.setBackground(defaultBackgroundColor)
|
||||
gpu.fill(1,1,width,height," ")
|
||||
_PUBLIC.terminal.cursorPosX, _PUBLIC.terminal.cursorPosY = 1, 1
|
||||
end
|
||||
|
||||
function _G._PUBLIC.terminal.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 _PUBLIC.terminal.readHistory[readHistoryType] then
|
||||
_PUBLIC.terminal.readHistory[readHistoryType] = {text}
|
||||
elseif _PUBLIC.terminal.readHistory[readHistoryType][#_PUBLIC.terminal.readHistory[readHistoryType] ] ~= "" then
|
||||
table.insert(_PUBLIC.terminal.readHistory[readHistoryType], text)
|
||||
end
|
||||
historyIdx = #_PUBLIC.terminal.readHistory[readHistoryType]
|
||||
end
|
||||
|
||||
local function updateHistory()
|
||||
if not readHistoryType then return end
|
||||
_PUBLIC.terminal.readHistory[readHistoryType][historyIdx]=text
|
||||
end
|
||||
|
||||
local cur = unicode.len(text)+1
|
||||
if prefix then _PUBLIC.terminal.write(prefix) end
|
||||
local startX, startY = _PUBLIC.terminal.cursorPosX, _PUBLIC.terminal.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 maxChars<math.huge then
|
||||
chr=unicode.sub(chr,1,maxChars-unicode.len(text))
|
||||
end
|
||||
text=unicode.sub(text,1,cur-1)..chr..unicode.sub(text,cur)
|
||||
set(curPos(cur),chr,false)
|
||||
cur=math.min(cur+unicode.len(chr),maxChars+1)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
cursorBlink = true
|
||||
set(curPos(cur+1),unicode.sub(text,cur+1),false)
|
||||
end
|
||||
local function moveCur(dir)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false)
|
||||
cur=math.max(math.min(cur+dir,unicode.len(text)+1),1)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
cursorBlink = true
|
||||
end
|
||||
local function isLetter(chr)
|
||||
return not string.find("\x09 :@-./_~?&=%+#",chr,1,true)
|
||||
end
|
||||
local function nextCur(dir,chr,icur)
|
||||
if icur==nil then icur=cur end
|
||||
local next = math.max(math.min(icur+dir,unicode.len(text)+1),1)
|
||||
if chr then return unicode.sub(text,next,next) end
|
||||
return next
|
||||
end
|
||||
local function curAfterWord(dir)
|
||||
local ncur = cur
|
||||
while nextCur(dir,false,ncur)~=ncur and isLetter(nextCur(dir,true,ncur))==(dir==1) do
|
||||
ncur=nextCur(dir,false,ncur)
|
||||
end
|
||||
while nextCur(dir,false,ncur)~=ncur and isLetter(nextCur(dir,true,ncur))==(dir==-1) do
|
||||
ncur=nextCur(dir,false,ncur)
|
||||
end
|
||||
return ncur
|
||||
end
|
||||
local function moveWord(dir)
|
||||
if nextCur(dir)==cur then return end
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false)
|
||||
cur=curAfterWord(dir)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
cursorBlink = true
|
||||
end
|
||||
local function deleteWord(dir)
|
||||
local after = curAfterWord(dir)
|
||||
local lenb = unicode.wlen(text)
|
||||
if dir==1 then
|
||||
text=unicode.sub(text,1,cur-1)..unicode.sub(text,after)
|
||||
set(curPos(cur+1),unicode.sub(text,cur+1)..string.rep(" ",lenb-unicode.wlen(text)+1),false)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
else
|
||||
text = unicode.sub(text,1,after-1)..unicode.sub(text,cur)
|
||||
cur=after
|
||||
set(curPos(cur+1),unicode.sub(text,cur+1)..string.rep(" ",lenb-unicode.wlen(text)+1),false)
|
||||
set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true)
|
||||
end
|
||||
updateHistory()
|
||||
cursorBlink = true
|
||||
end
|
||||
local function isLine(chr)
|
||||
return chr=="\n" or chr=="\r"
|
||||
end
|
||||
--[[ gpu.set(startX,startY,unicode.sub(text,1,width-startX))
|
||||
for i=1,(#text+startX)//width-1 do
|
||||
gpu.set(startX,startY+i,unicode.sub(text,1+i*width,width-startX+i*width))
|
||||
end ]]
|
||||
set(1,text,false)
|
||||
set(curPos(cur)," ",true)
|
||||
|
||||
local function reprint(new)
|
||||
set(1,new..string.rep(" ",unicode.wlen(text)-unicode.wlen(new)+1),false)
|
||||
cur=unicode.len(new)+1
|
||||
text=new
|
||||
set(curPos(cur)," ",true)
|
||||
end
|
||||
|
||||
while true do
|
||||
local args = {event.pull("key_down", "clipboard", 0.5)}
|
||||
if args and args[1] == "key_down" and args[4] then
|
||||
local key = _PUBLIC.keyboard.keys[args[4]]
|
||||
if key=="up" and readHistoryType then
|
||||
historyIdx=math.max(historyIdx-1,1)
|
||||
reprint(_PUBLIC.terminal.readHistory[readHistoryType][historyIdx])
|
||||
elseif key=="down" and readHistoryType then
|
||||
historyIdx=math.min(historyIdx+1,#_PUBLIC.terminal.readHistory[readHistoryType])
|
||||
reprint(_PUBLIC.terminal.readHistory[readHistoryType][historyIdx])
|
||||
elseif key=="left" and _PUBLIC.keyboard.ctrlDown then
|
||||
moveWord(-1)
|
||||
elseif key=="right" and _PUBLIC.keyboard.ctrlDown then
|
||||
moveWord(1)
|
||||
elseif key=="left" then
|
||||
moveCur(-1)
|
||||
elseif key=="right" then
|
||||
moveCur(1)
|
||||
elseif key=="home" then
|
||||
moveCur(-math.huge)
|
||||
elseif key=="end" then
|
||||
moveCur(math.huge)
|
||||
elseif key=="back" and _PUBLIC.keyboard.ctrlDown then
|
||||
deleteWord(-1)
|
||||
elseif key=="delete" and _PUBLIC.keyboard.ctrlDown then
|
||||
deleteWord(1)
|
||||
elseif key=="back" and cur>1 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 _PUBLIC.terminal.readHistory[readHistoryType][#_PUBLIC.terminal.readHistory[readHistoryType]]=="" then
|
||||
table.remove(_PUBLIC.terminal.readHistory[readHistoryType],#_PUBLIC.terminal.readHistory[readHistoryType])
|
||||
end
|
||||
if historyIdx<#_PUBLIC.terminal.readHistory[readHistoryType] then
|
||||
table.remove(_PUBLIC.terminal.readHistory[readHistoryType],historyIdx)
|
||||
table.insert(_PUBLIC.terminal.readHistory[readHistoryType],text)
|
||||
end
|
||||
while #_PUBLIC.terminal.readHistory[readHistoryType] > 50 do
|
||||
table.remove(_PUBLIC.terminal.readHistory[readHistoryType], 1)
|
||||
end
|
||||
end
|
||||
|
||||
_PUBLIC.terminal.cursorPosX=1
|
||||
_PUBLIC.terminal.cursorPosY=_PUBLIC.terminal.cursorPosY+math.ceil((unicode.wlen(text)+startX-1)/width)
|
||||
if _PUBLIC.terminal.cursorPosY>height then scrollDown() end
|
||||
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
function module.exit()
|
||||
_G._PUBLIC.terminal = nil
|
||||
end
|
||||
|
||||
return module
|
||||
@@ -1,149 +0,0 @@
|
||||
_G._PUBLIC.tsched = {}
|
||||
_G.tsched = {}
|
||||
_G.tsched.tasks = {}
|
||||
|
||||
local currentTask
|
||||
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
local filesystem = require("filesystem")
|
||||
local json = require("json")
|
||||
local gpu = component.gpu
|
||||
local ocelot = component.ocelot
|
||||
|
||||
function _G._PUBLIC.tsched.runAsTask(path,...)
|
||||
local args = {...}
|
||||
local function taskFunction()
|
||||
local result, errorMessage = xpcall(function(...)
|
||||
local args = table.pack(...)
|
||||
if not filesystem.exists(path) then
|
||||
error("No such file: " .. path)
|
||||
end
|
||||
local handle, data, tmpdata = filesystem.open(path), "", nil
|
||||
repeat
|
||||
tmpdata = handle:read(math.huge or math.maxinteger)
|
||||
data = data .. (tmpdata or "")
|
||||
until not tmpdata
|
||||
handle:close()
|
||||
|
||||
-- Userland environment definition
|
||||
local userland = table.copy(_PUBLIC)
|
||||
userland._G = userland
|
||||
|
||||
assert(load(data, "="..path, "t", userland))(table.unpack(args))
|
||||
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
|
||||
--require(path, table.unpack(args))
|
||||
end
|
||||
_PUBLIC.tsched.addTask(taskFunction, string.match(tostring(path), "([^/]+)%.lua$"))
|
||||
end
|
||||
|
||||
function _G._PUBLIC.tsched.addTask(func, name)
|
||||
ocelot.log("Added task " .. name)
|
||||
local task = coroutine.create(func)
|
||||
table.insert(tsched.tasks, {["task"] = task, ["name"] = name})
|
||||
return task
|
||||
end
|
||||
|
||||
function _G._PUBLIC.tsched.removeTask(id)
|
||||
-- TODO: Check for user permissions before running
|
||||
table.remove(_G.tsched.tasks, id)
|
||||
end
|
||||
|
||||
function handleError(errormsg)
|
||||
if errormsg == nil then -- TODO: Replace with proper error handling (if this isn't considered proper..?)
|
||||
print("\27[91munknown error" .. "\n \n" .. debug.traceback())
|
||||
else
|
||||
print("\27[91m" .. tostring(errormsg) .. "\n \n" .. debug.traceback())
|
||||
end
|
||||
end
|
||||
|
||||
local function runTasks()
|
||||
for i = 1, #_G.tsched.tasks do
|
||||
if tsched.tasks[i] then
|
||||
currentTask = tsched.tasks[i]
|
||||
local result, errorMessage = coroutine.resume(tsched.tasks[i].task)
|
||||
if not result then
|
||||
handleError(errorMessage)
|
||||
end
|
||||
if coroutine.status(tsched.tasks[i].task) == "dead" then
|
||||
_PUBLIC.tsched.removeTask(i)
|
||||
--ocelot.log("Removed coroutine")
|
||||
i = i - 1
|
||||
end
|
||||
--computer.pullSignal(0)
|
||||
--coroutine.yield()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _G._PUBLIC.tsched.getCurrentTask()
|
||||
return table.copy(currentTask)
|
||||
end
|
||||
|
||||
function _G._PUBLIC.tsched.getTasks()
|
||||
return table.copy(tsched.tasks)
|
||||
end
|
||||
|
||||
local function taskFunction()
|
||||
local result, errorMessage = xpcall(function()
|
||||
if not filesystem.exists("/halyde/kernel/evmgr.lua") then
|
||||
error("No such file: /halyde/kernel/evmgr.lua")
|
||||
end
|
||||
local handle, data, tmpdata = filesystem.open("/halyde/kernel/evmgr.lua"), "", nil
|
||||
repeat
|
||||
tmpdata = handle:read(math.huge or math.maxinteger)
|
||||
data = data .. (tmpdata or "")
|
||||
until not tmpdata
|
||||
handle:close()
|
||||
assert(load(data, "=/halyde/kernel/evmgr.lua"))()
|
||||
end, function(errorMessage)
|
||||
return errorMessage .. "\n \n" .. debug.traceback()
|
||||
end, "/halyde/kernel/evmgr.lua")
|
||||
if not result then
|
||||
if print then
|
||||
gpu.freeAllBuffers()
|
||||
print("\n\27[91m" .. errorMessage)
|
||||
else
|
||||
error(errorMessage)
|
||||
end
|
||||
end
|
||||
end
|
||||
_PUBLIC.tsched.addTask(taskFunction, "evmgr")
|
||||
package.preload("event")
|
||||
|
||||
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._PUBLIC.tsched.runAsTask(line)
|
||||
runTasks()
|
||||
end
|
||||
end
|
||||
-- _G.cormgr.loadCoroutine("/halyde/core/shell.lua")
|
||||
|
||||
while true do
|
||||
runTasks()
|
||||
if #_G.tsched.tasks == 0 then
|
||||
computer.beep(1000, 0.5)
|
||||
while true do
|
||||
computer.pullSignal()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
local computer = require("computer")
|
||||
local computer = import("computer")
|
||||
local event = {}
|
||||
|
||||
local bufferTime = 0.1 -- A little bit of buffer time so events won't be skipped by accident.
|
||||
@@ -1,14 +1,14 @@
|
||||
local loadfile = ... -- raw loadfile from boot.lua
|
||||
local unicode, component, computer
|
||||
local component, computer
|
||||
|
||||
if loadfile then
|
||||
unicode = loadfile("/lib/unicode.lua")(loadfile)
|
||||
component = loadfile("/lib/component.lua")(loadfile)
|
||||
unicode = loadfile("/halyde/lib/unicode.lua")(loadfile)
|
||||
component = loadfile("/halyde/lib/component.lua")(loadfile)
|
||||
computer = _G.computer
|
||||
elseif require then
|
||||
unicode = require("unicode")
|
||||
component = require("component")
|
||||
computer = require("computer")
|
||||
elseif import then
|
||||
unicode = import("unicode")
|
||||
component = import("component")
|
||||
computer = import("computer")
|
||||
end
|
||||
|
||||
local filesystem = {}
|
||||
@@ -30,16 +30,16 @@ function filesystem.canonical(path)
|
||||
return "/" .. table.concat(segList, "/")
|
||||
end
|
||||
|
||||
function filesystem.concat(path1, path2)
|
||||
checkArg(1, path1, "string")
|
||||
checkArg(2, path2, "string")
|
||||
if path1:sub(-1, -1) == "/" then
|
||||
path1 = path1:sub(1, -2)
|
||||
function filesystem.concat(...)
|
||||
local paths = {...}
|
||||
for i, path in ipairs(paths) do
|
||||
checkArg(i, path, "string")
|
||||
end
|
||||
if path2:sub(1, 1) ~= "/" then
|
||||
path2 = "/" .. path2
|
||||
local currentPath = paths[1]:match("(.+)/?$")
|
||||
for i = 2, #paths do
|
||||
currentPath = currentPath .. "/" .. paths[i]:match("^/?(.+)/?$")
|
||||
end
|
||||
return path1 .. path2
|
||||
return currentPath
|
||||
end
|
||||
|
||||
function filesystem.absolutePath(path) -- returns the address and absolute path of an object
|
||||
File diff suppressed because one or more lines are too long
@@ -9,7 +9,7 @@ local raster = {
|
||||
["backgroundColor"]=0xFFFFFF
|
||||
}
|
||||
|
||||
local component = require("component")
|
||||
local component = import("component")
|
||||
-- local ocelot = component.proxy(component.list("ocelot")())
|
||||
local gpu = component.gpu
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[37m[00:00:04:12] Debug!
|
||||
[97m[00:00:04:19] Info!
|
||||
[93m[00:00:04:25] Warning!
|
||||
[91m[00:00:04:32] Error!
|
||||
@@ -1,7 +0,0 @@
|
||||
local cor = coroutine.create(function()
|
||||
print("Hello World!")
|
||||
end)
|
||||
|
||||
print(coroutine.status(cor))
|
||||
coroutine.resume(cor)
|
||||
print(coroutine.status(cor))
|
||||
@@ -1,24 +1,5 @@
|
||||
local gpu = component.proxy(component.list("gpu")())
|
||||
local resX, resY = gpu.getResolution()
|
||||
|
||||
-- Architecture check
|
||||
local foundArchitecture = false
|
||||
for _, arch in pairs(computer.getArchitectures()) do
|
||||
if arch == "Lua 5.3" then
|
||||
foundArchitecture = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if foundArchitecture then
|
||||
computer.setArchitecture("Lua 5.3")
|
||||
else
|
||||
gpu.set(1, 1, "Required architecture (Lua 5.3) is not supported.")
|
||||
gpu.set(1, 2, "Halting.")
|
||||
while true do
|
||||
computer.pullSignal()
|
||||
end
|
||||
end
|
||||
local resx, resy = gpu.getResolution()
|
||||
|
||||
local function loadfile(file)
|
||||
checkArg(1, file, "string")
|
||||
@@ -36,36 +17,36 @@ local function handleError(errorMessage)
|
||||
return(errorMessage.."\n \n"..debug.traceback())
|
||||
end
|
||||
|
||||
function loadBoot()
|
||||
loadfile("/halyde/kernel/boot.lua")(loadfile)
|
||||
function loadthething()
|
||||
loadfile("/halyde/core/boot.lua")(loadfile)
|
||||
end
|
||||
|
||||
gpu.setBackground(0x000000)
|
||||
gpu.fill(1, 1, resX, resY, " ")
|
||||
|
||||
-- Copying low-level functions in case of post-preload failure
|
||||
local pullSignal = computer.pullSignal
|
||||
local shutdown = computer.shutdown
|
||||
|
||||
local result, reason = xpcall(loadBoot, handleError)
|
||||
gpu.fill(1, 1, resx, resy, " ")
|
||||
local result, reason = xpcall(loadthething, handleError)
|
||||
if not result then
|
||||
if import then
|
||||
local computer = import("computer")
|
||||
end
|
||||
gpu.setBackground(0x000000)
|
||||
gpu.fill(1, 1, resX, resY, " ")
|
||||
gpu.fill(1, 1, resx, resy, " ")
|
||||
gpu.setBackground(0x800000)
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.set(2,2,"A critical error has occurred.")
|
||||
local i = 4
|
||||
reason = tostring(reason):gsub("\t", " ")
|
||||
for line in string.gmatch(reason or "unknown error", "([^\n]*)\n?") do
|
||||
reason = reason:gsub("\t", " ")
|
||||
for line in string.gmatch((reason ~= nil and tostring(reason)) or "unknown error", "([^\n]*)\n?") do
|
||||
gpu.set(2,i,line)
|
||||
i = i + 1
|
||||
end
|
||||
gpu.set(2,i+1, "Press any key to restart.")
|
||||
local evname
|
||||
repeat
|
||||
evname = pullSignal()
|
||||
until evname == "key_down"
|
||||
shutdown(true)
|
||||
if computer~=nil then
|
||||
gpu.set(2,i+1, "Press any key to restart.")
|
||||
local evname
|
||||
repeat
|
||||
evname = computer.pullSignal()
|
||||
until evname == "key_down"
|
||||
computer.shutdown(true)
|
||||
end
|
||||
while true do
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
local fs = require("filesystem")
|
||||
local computer = require("computer")
|
||||
|
||||
local log = {}
|
||||
|
||||
function log.add(text, logType)
|
||||
checkArg(1, text, "string")
|
||||
checkArg(2, logType, "string", "nil")
|
||||
if logType ~= "debug" and logType ~= "info" and logType ~= "warning" and logType ~= "error" and logType then
|
||||
error("Log type must either be debug, info, warning or error.")
|
||||
end
|
||||
if not logType then
|
||||
logType = "debug"
|
||||
end
|
||||
local handle = fs.open("/halyde/system.log", "a")
|
||||
local time = computer.uptime()
|
||||
local logText = string.format("[%02d:%02d:%02d:%02d] " .. text, math.floor(time / 86400), math.floor(time / 3600 % 24), math.floor(time / 60 % 60), math.floor(time % 60)) .. "\n"
|
||||
if logType == "debug" then
|
||||
handle:write("\27[37m" .. logText)
|
||||
elseif logType == "info" then
|
||||
handle:write("\27[97m" .. logText)
|
||||
elseif logType == "warning" then
|
||||
handle:write("\27[93m" .. logText)
|
||||
else
|
||||
handle:write("\27[91m" .. logText)
|
||||
end
|
||||
handle:close()
|
||||
end
|
||||
|
||||
return log
|
||||
Reference in New Issue
Block a user