Compare commits
37 Commits
cutting-edge
...
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
|
||||||
+5
-95
@@ -1,100 +1,10 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/LuaLS/lua-language-server/master/locale/en-us/setting.lua",
|
"diagnostics.globals": [
|
||||||
"runtime": {
|
|
||||||
"version": "Lua 5.3",
|
|
||||||
"special": {},
|
|
||||||
"unicodeName": false,
|
|
||||||
"nonstandardSymbol": []
|
|
||||||
},
|
|
||||||
"workspace": {
|
|
||||||
"checkThirdParty": false,
|
|
||||||
"maxPreload": 5000,
|
|
||||||
"preloadFileSize": 500
|
|
||||||
},
|
|
||||||
"diagnostics": {
|
|
||||||
"disable": [
|
|
||||||
"undefined-global",
|
|
||||||
"lowercase-global"
|
|
||||||
],
|
|
||||||
"globals": [
|
|
||||||
"_G",
|
|
||||||
"_VERSION",
|
|
||||||
"assert",
|
|
||||||
"error",
|
|
||||||
"getmetatable",
|
|
||||||
"ipairs",
|
|
||||||
"load",
|
|
||||||
"next",
|
|
||||||
"pairs",
|
|
||||||
"pcall",
|
|
||||||
"rawequal",
|
|
||||||
"rawget",
|
|
||||||
"rawlen",
|
|
||||||
"rawset",
|
|
||||||
"select",
|
|
||||||
"setmetatable",
|
|
||||||
"tonumber",
|
|
||||||
"tostring",
|
|
||||||
"type",
|
|
||||||
"xpcall",
|
|
||||||
"checkArg",
|
"checkArg",
|
||||||
"bit32",
|
|
||||||
"coroutine",
|
|
||||||
"debug",
|
|
||||||
"math",
|
|
||||||
"os",
|
|
||||||
"string",
|
|
||||||
"table",
|
|
||||||
"component",
|
|
||||||
"computer",
|
"computer",
|
||||||
"unicode",
|
"component"
|
||||||
"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,4 +1,6 @@
|
|||||||
# Halyde
|
# 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.
|
A universal, customizable and feature-packed operating system for OpenComputers.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -6,8 +8,8 @@ A universal, customizable and feature-packed operating system for OpenComputers.
|
|||||||
<img src="https://img.shields.io/badge/Written_in-Lua-blue?style=plastic&logo=lua" /></a>
|
<img src="https://img.shields.io/badge/Written_in-Lua-blue?style=plastic&logo=lua" /></a>
|
||||||
<a href="https://ocdoc.cil.li/">
|
<a href="https://ocdoc.cil.li/">
|
||||||
<img src="https://img.shields.io/badge/Made_for-OpenComputers-yellow?style=plastic" /></a>
|
<img src="https://img.shields.io/badge/Made_for-OpenComputers-yellow?style=plastic" /></a>
|
||||||
<a href="https://cerulean-blue.gitbook.io/halyde-docs">
|
<a href="https://wiki.sting.lt/">
|
||||||
<img src="https://img.shields.io/badge/Documented_on-GitBook-green?style=plastic&logo=gitbook" /></a>
|
<img src="https://img.shields.io/badge/Documented_on-DokuWiki-green?style=plastic" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -20,4 +22,4 @@ 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`
|
`wget -f https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/webinstall.lua /tmp/webinstall.lua && /tmp/webinstall.lua`
|
||||||
|
|
||||||
## Docs
|
## Docs
|
||||||
Halyde is [documented on GitBook](https://cerulean-blue.gitbook.io/halyde-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"] = {
|
["argentum"] = {
|
||||||
["maindir"] = "",
|
["maindir"] = "",
|
||||||
["version"] = "1.3.1",
|
["version"] = "1.3.3",
|
||||||
["description"] = "The default package manager for Halyde.",
|
["description"] = "The default package manager for Halyde.",
|
||||||
["directories"] = {
|
["directories"] = {
|
||||||
"argentum",
|
"argentum",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
local agregistry = {
|
local agregistry = {
|
||||||
["halyde"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
|
["halyde"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
|
||||||
["edit"] = "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/",
|
["hextra"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
|
||||||
["utape"] = "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/",
|
["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
|
return agregistry
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Aargentum/store/
|
Aargentum/store/
|
||||||
Aargentum/
|
Aargentum/
|
||||||
V1.2.0
|
V1.3.3
|
||||||
Aargentum/registry.cfg
|
Aargentum/registry.cfg
|
||||||
Ahalyde/apps/argentum.lua
|
Ahalyde/apps/argentum.lua
|
||||||
Ahalyde/apps/helpdb/argentum.txt
|
Ahalyde/apps/helpdb/argentum.txt
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
local packages = {...}
|
local packages = {...}
|
||||||
local command = packages[1]
|
local command = packages[1]
|
||||||
table.remove(packages, 1)
|
table.remove(packages, 1)
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
local component = require("component")
|
local component = import("component")
|
||||||
local agReg = require("/argentum/registry.cfg")
|
local agReg = import("/argentum/registry.cfg")
|
||||||
if not command then
|
if not command then
|
||||||
shell.run("help argentum")
|
shell.run("help argentum")
|
||||||
return
|
return
|
||||||
@@ -346,7 +346,7 @@ if command == "install" then
|
|||||||
else
|
else
|
||||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||||
end
|
end
|
||||||
agReg = require("/argentum/registry.cfg")
|
agReg = import("/argentum/registry.cfg")
|
||||||
while true do
|
while true do
|
||||||
if not doChecks(packages[i]) then
|
if not doChecks(packages[i]) then
|
||||||
table.insert(fails, packages[i])
|
table.insert(fails, packages[i])
|
||||||
@@ -497,7 +497,7 @@ elseif command == "update" then
|
|||||||
else
|
else
|
||||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||||
end
|
end
|
||||||
agReg = require("/argentum/registry.cfg")
|
agReg = import("/argentum/registry.cfg")
|
||||||
if not packages[1] then
|
if not packages[1] then
|
||||||
local packagesInstalled = fs.list("/argentum/store/")
|
local packagesInstalled = fs.list("/argentum/store/")
|
||||||
for _, currentPackage in pairs(packagesInstalled) do
|
for _, currentPackage in pairs(packagesInstalled) do
|
||||||
@@ -632,7 +632,7 @@ elseif command == "info" then
|
|||||||
else
|
else
|
||||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||||
end
|
end
|
||||||
agReg = require("/argentum/registry.cfg")
|
agReg = import("/argentum/registry.cfg")
|
||||||
if not agReg[packages[1]] and not source then
|
if not agReg[packages[1]] and not source then
|
||||||
print("\27[91mPackage " .. packages[1] .. " does not exist.")
|
print("\27[91mPackage " .. packages[1] .. " does not exist.")
|
||||||
return
|
return
|
||||||
@@ -656,7 +656,7 @@ elseif command == "search" then
|
|||||||
else
|
else
|
||||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||||
end
|
end
|
||||||
agReg = require("/argentum/registry.cfg")
|
agReg = import("/argentum/registry.cfg")
|
||||||
local searchResults = {}
|
local searchResults = {}
|
||||||
for packageName, _ in pairs(agReg) do
|
for packageName, _ in pairs(agReg) do
|
||||||
if packageName:find(packages[1], 1, true) then
|
if packageName:find(packages[1], 1, true) then
|
||||||
@@ -679,7 +679,7 @@ elseif command == "list" then
|
|||||||
else
|
else
|
||||||
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil"))
|
||||||
end
|
end
|
||||||
agReg = require("/argentum/registry.cfg")
|
agReg = import("/argentum/registry.cfg")
|
||||||
local sortedPackages = {}
|
local sortedPackages = {}
|
||||||
for packageName, _ in pairs(agReg) do
|
for packageName, _ in pairs(agReg) do
|
||||||
table.insert(sortedPackages, packageName)
|
table.insert(sortedPackages, packageName)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local component = require("component")
|
local component = import("component")
|
||||||
local computer = require("computer")
|
local computer = import("computer")
|
||||||
local args = {...}
|
local args = {...}
|
||||||
|
|
||||||
local force = false
|
local force = false
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
local files = {...}
|
local files = {...}
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
if not files or not files[1] then
|
if not files or not files[1] then
|
||||||
shell.run("help cat")
|
shell.run("help cat")
|
||||||
return
|
return
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
local directory = ...
|
local directory = ...
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
|
|
||||||
if not directory then
|
if not directory then
|
||||||
return
|
return
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
local fromFile, toFile = ...
|
local fromFile, toFile = ...
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
|
|
||||||
if not fromFile or not toFile then
|
if not fromFile or not toFile then
|
||||||
shell.run("help cp")
|
shell.run("help cp")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local url = ...
|
local url = ...
|
||||||
|
|
||||||
local component = require("component")
|
local component = import("component")
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
|
|
||||||
if not component.list("internet")() then
|
if not component.list("internet")() then
|
||||||
print("\27[91mThis program requires an internet card to run.")
|
print("\27[91mThis program requires an internet card to run.")
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
local file = ...
|
local file = ...
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
local event = require("event")
|
local event = import("event")
|
||||||
local component = require("component")
|
local component = import("component")
|
||||||
local unicode = require("unicode")
|
local unicode = import("unicode")
|
||||||
local gpu = component.gpu
|
local gpu = component.gpu
|
||||||
local width, height = gpu.getResolution()
|
local width, height = gpu.getResolution()
|
||||||
local scrollPosX, scrollPosY = 1, 1
|
local scrollPosX, scrollPosY = 1, 1
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
local component = require("component")
|
local component = import("component")
|
||||||
local computer = require("computer")
|
local computer = import("computer")
|
||||||
|
|
||||||
local function printstat(text)
|
local function printstat(text)
|
||||||
terminal.cursorPosX = 35
|
termlib.cursorPosX = 35
|
||||||
terminal.write(text .. "\n", false)
|
termlib.write(text .. "\n", false)
|
||||||
end
|
end
|
||||||
|
|
||||||
terminal.write(_OSLOGO, false)
|
termlib.write(_OSLOGO, false)
|
||||||
terminal.cursorPosY = terminal.cursorPosY - 17
|
termlib.cursorPosY = termlib.cursorPosY - 17
|
||||||
printstat("\27[92mOS\27[0m: ".._OSVERSION)
|
printstat("\27[92mOS\27[0m: ".._OSVERSION)
|
||||||
printstat("\27[92mArchitecture\27[0m: ".._VERSION)
|
printstat("\27[92mArchitecture\27[0m: ".._VERSION)
|
||||||
local componentCounter = 0
|
local componentCounter = 0
|
||||||
@@ -15,7 +15,7 @@ for _, _ in component.list() do
|
|||||||
componentCounter = componentCounter + 1
|
componentCounter = componentCounter + 1
|
||||||
end
|
end
|
||||||
printstat("\27[92mComponents\27[0m: "..tostring(componentCounter))
|
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).."%")
|
printstat("\27[92mBattery\27[0m: "..tostring(math.floor(computer.energy() / computer.maxEnergy() * 1000 + 0.5) / 10).."%")
|
||||||
local totalMemory = computer.totalMemory()
|
local totalMemory = computer.totalMemory()
|
||||||
local usedMemory = computer.totalMemory() - computer.freeMemory()
|
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[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[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 ")
|
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 args = {...}
|
||||||
local command = args[1]
|
local command = args[1]
|
||||||
args = nil
|
args = nil
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local component = require("component")
|
local component = import("component")
|
||||||
local computer = require("computer")
|
local computer = import("computer")
|
||||||
local args = {...}
|
local args = {...}
|
||||||
if not args then return print("\x1b[91mCannot get arguments.") end
|
if not args then return print("\x1b[91mCannot get arguments.") end
|
||||||
if not args[1] then
|
if not args[1] then
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
local args = {...}
|
local args = {...}
|
||||||
local target = args[1]
|
local target = args[1]
|
||||||
args = nil
|
args = nil
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
local unicode = require("unicode")
|
local unicode = import("unicode")
|
||||||
local maxLength = 0
|
local maxLength = 0
|
||||||
local margin = 2 -- minimum space between filename and size
|
local margin = 2 -- minimum space between filename and size
|
||||||
local dirTable = {}
|
local dirTable = {}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local serialize = require("serialize")
|
local serialize = import("serialize")
|
||||||
local component = require("component")
|
local component = import("component")
|
||||||
local computer = require("computer")
|
local computer = import("computer")
|
||||||
local unicode = require("unicode")
|
local unicode = import("unicode")
|
||||||
|
|
||||||
local width,height = component.gpu.getResolution()
|
local width,height = component.gpu.getResolution()
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,13 +1,13 @@
|
|||||||
print("\27[44m".._VERSION.."\27[0m shell")
|
print("\27[44m".._VERSION.."\27[0m shell")
|
||||||
print('Type "exit" to exit.')
|
print('Type "exit" to exit.')
|
||||||
termlib.readHistory["lua"] = {""}
|
termlib.readHistory["lua"] = {""}
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
|
|
||||||
local loadedLibraries = ""
|
local loadedLibraries = ""
|
||||||
local libList = fs.list("halyde/lib")
|
local libList = fs.list("halyde/lib")
|
||||||
for _, lib in pairs(libList) do
|
for _, lib in pairs(libList) do
|
||||||
if lib:match("(.+)%.lua") then
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
local computer = require("computer")
|
local computer = import("computer")
|
||||||
|
|
||||||
if type(computer)~="table" then
|
if type(computer)~="table" then
|
||||||
return print("\x1b[91mComputer library returned '"..type(computer).."' type\x1b[39m")
|
return print("\x1b[91mComputer library returned '"..type(computer).."' type\x1b[39m")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local directory = ...
|
local directory = ...
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
|
|
||||||
if not directory then
|
if not directory then
|
||||||
shell.run("help mkdir")
|
shell.run("help mkdir")
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
local fromFile, toFile = ...
|
local fromFile, toFile = ...
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
|
|
||||||
if not fromFile or not toFile then
|
if not fromFile or not toFile then
|
||||||
shell.run("help mv")
|
shell.run("help mv")
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
require("computer").shutdown(true)
|
import("computer").shutdown(true)
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
local file = ...
|
local file = ...
|
||||||
local fs = require("filesystem")
|
local fs = import("filesystem")
|
||||||
|
|
||||||
if not file then
|
if not file then
|
||||||
shell.run("help rm")
|
shell.run("help rm")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
local raster = require("raster")
|
local raster = import("raster")
|
||||||
|
|
||||||
raster.init()
|
raster.init()
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ end]]
|
|||||||
end
|
end
|
||||||
end ]]
|
end ]]
|
||||||
|
|
||||||
local event = require("event")
|
local event = import("event")
|
||||||
local x=0
|
local x=0
|
||||||
local y=0
|
local y=0
|
||||||
local vx=1
|
local vx=1
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local component = require("component")
|
local component = import("component")
|
||||||
local computer = require("computer")
|
local computer = import("computer")
|
||||||
local raster = require("raster")
|
local raster = import("raster")
|
||||||
local event = require("event")
|
local event = import("event")
|
||||||
|
|
||||||
-- Initialize the 3D renderer for a spinning cube
|
-- Initialize the 3D renderer for a spinning cube
|
||||||
-- Using the raster library for drawing
|
-- 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 = {}
|
_G.evmgr.eventQueue = {}
|
||||||
local maxEventQueueLength = 10 -- increase if events start getting dropped
|
local maxEventQueueLength = 10 -- increase if events start getting dropped
|
||||||
|
|
||||||
local computer = require("computer")
|
local computer = import("computer")
|
||||||
|
|
||||||
_G._PUBLIC.keyboard.ctrlDown = false
|
keyboard.ctrlDown = false
|
||||||
_G._PUBLIC.keyboard.altDown = false
|
keyboard.altDown = false
|
||||||
_G._PUBLIC.keyboard.shiftDown = false
|
keyboard.shiftDown = false
|
||||||
|
|
||||||
--local ocelot = component.proxy(component.list("ocelot")())
|
--local ocelot = component.proxy(component.list("ocelot")())
|
||||||
|
|
||||||
@@ -16,31 +16,31 @@ while true do
|
|||||||
args = {computer.uptime(), computer.pullSignal(0)}
|
args = {computer.uptime(), computer.pullSignal(0)}
|
||||||
if args and args[2] then
|
if args and args[2] then
|
||||||
table.insert(evmgr.eventQueue, args)
|
table.insert(evmgr.eventQueue, args)
|
||||||
if _PUBLIC.keyboard then
|
if keyboard then
|
||||||
if args[2] == "key_down" then
|
if args[2] == "key_down" then
|
||||||
local keycode = args[5]
|
local keycode = args[5]
|
||||||
local key = _PUBLIC.keyboard.keys[keycode]
|
local key = keyboard.keys[keycode]
|
||||||
if key == "lcontrol" then
|
if key == "lcontrol" then
|
||||||
_PUBLIC.keyboard.ctrlDown = true
|
keyboard.ctrlDown = true
|
||||||
elseif key == "lmenu" then
|
elseif key == "lmenu" then
|
||||||
_PUBLIC.keyboard.altDown = true
|
keyboard.altDown = true
|
||||||
elseif key == "lshift" then
|
elseif key == "lshift" then
|
||||||
_PUBLIC.keyboard.shiftDown = true
|
keyboard.shiftDown = true
|
||||||
elseif key == "c" and _PUBLIC.keyboard.ctrlDown and _PUBLIC.keyboard.altDown then
|
elseif key == "c" and keyboard.ctrlDown and keyboard.altDown then
|
||||||
if print then
|
if print then
|
||||||
print("\n\27[91mCoroutine "..tostring(#tsched.tasks).." killed.")
|
print("\n\27[91mCoroutine "..tostring(#cormgr.corList).." killed.")
|
||||||
end
|
end
|
||||||
tsched.tasks[#tsched.tasks] = nil
|
cormgr.corList[#cormgr.corList] = nil
|
||||||
end
|
end
|
||||||
elseif args[2] == "key_up" then
|
elseif args[2] == "key_up" then
|
||||||
local keycode = args[5]
|
local keycode = args[5]
|
||||||
local key = _PUBLIC.keyboard.keys[keycode]
|
local key = keyboard.keys[keycode]
|
||||||
if key == "lcontrol" then
|
if key == "lcontrol" then
|
||||||
_PUBLIC.keyboard.ctrlDown = false
|
keyboard.ctrlDown = false
|
||||||
elseif key == "lmenu" then
|
elseif key == "lmenu" then
|
||||||
_PUBLIC.keyboard.altDown = false
|
keyboard.altDown = false
|
||||||
elseif key == "lshift" then
|
elseif key == "lshift" then
|
||||||
_PUBLIC.keyboard.shiftDown = true
|
keyboard.shiftDown = true
|
||||||
end
|
end
|
||||||
end
|
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 fs = import("filesystem")
|
||||||
local json = require("json")
|
local json = import("json")
|
||||||
local handle, data, tmpdata = fs.open("/halyde/config/shell.json", "r"), "", nil
|
local handle, data, tmpdata = fs.open("/halyde/config/shell.json", "r"), "", nil
|
||||||
repeat
|
repeat
|
||||||
tmpdata = handle:read(math.huge)
|
tmpdata = handle:read(math.huge)
|
||||||
@@ -7,21 +7,23 @@ repeat
|
|||||||
until not tmpdata
|
until not tmpdata
|
||||||
handle:close()
|
handle:close()
|
||||||
local shellcfg = json.decode(data)
|
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
|
local gpu = component.gpu
|
||||||
|
|
||||||
_G.shell = {}
|
_G.shell = {}
|
||||||
_G.shell.workingDirectory = shellcfg["defaultWorkingDirectory"]
|
_G.shell.workingDirectory = shellcfg["defaultWorkingDirectory"]
|
||||||
_G.shell.aliases = shellcfg["aliases"]
|
_G.shell.aliases = shellcfg["aliases"]
|
||||||
|
|
||||||
local function runAsTask(path, ...)
|
local function runAsCoroutine(path, ...)
|
||||||
--ocelot.log("running " .. path .. " as coroutine")
|
--ocelot.log("running " .. path .. " as coroutine")
|
||||||
tsched.runAsTask(path, ...)
|
cormgr.loadCoroutine(path, ...)
|
||||||
local corIndex = #tsched.getTasks()
|
local corIndex = #cormgr.corList
|
||||||
local task = tsched.getTasks()[#tsched.getTasks()]
|
local cor = cormgr.corList[#cormgr.corList]
|
||||||
repeat
|
repeat
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
until tsched.getTasks()[corIndex] ~= task
|
until cormgr.corList[corIndex] ~= cor
|
||||||
end
|
end
|
||||||
|
|
||||||
function _G.shell.run(command)
|
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
|
if fs.exists(args[1]) and not fs.isDirectory(args[1]) then
|
||||||
local path = args[1]
|
local path = args[1]
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
runAsTask(path, table.unpack(args))
|
runAsCoroutine(path, table.unpack(args))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
for _, item in pairs(PATH) do
|
for _, item in pairs(PATH) do
|
||||||
if fs.exists(item..args[1]) and not fs.isDirectory(item .. args[1]) then
|
if fs.exists(item..args[1]) and not fs.isDirectory(item .. args[1]) then
|
||||||
local path = fs.concat(item, args[1])
|
local path = fs.concat(item, args[1])
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
runAsTask(path, table.unpack(args))
|
runAsCoroutine(path, table.unpack(args))
|
||||||
return
|
return
|
||||||
else -- try to look for it without the file extension
|
else -- try to look for it without the file extension
|
||||||
local files = fs.list(item) or {}
|
local files = fs.list(item) or {}
|
||||||
@@ -79,7 +81,7 @@ function _G.shell.run(command)
|
|||||||
-- previous pattern: (.+)%.[^%.]+$
|
-- previous pattern: (.+)%.[^%.]+$
|
||||||
if args[1] == file:match("(.+)%.[^%.]+$") and not fs.isDirectory(item .. file) then
|
if args[1] == file:match("(.+)%.[^%.]+$") and not fs.isDirectory(item .. file) then
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
runAsTask(item .. file, table.unpack(args))
|
runAsCoroutine(item .. file, table.unpack(args))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -98,7 +100,7 @@ while true do
|
|||||||
if shell.workingDirectory:sub(-1, -1) ~= "/" then
|
if shell.workingDirectory:sub(-1, -1) ~= "/" then
|
||||||
shell.workingDirectory = shell.workingDirectory .. "/"
|
shell.workingDirectory = shell.workingDirectory .. "/"
|
||||||
end
|
end
|
||||||
local shellCommand = terminal.read("shell", shellcfg.prompt:format(shell.workingDirectory))
|
local shellCommand = read("shell", shellcfg.prompt:format(shell.workingDirectory))
|
||||||
shell.run(shellCommand)
|
shell.run(shellCommand)
|
||||||
gpu.freeAllBuffers()
|
gpu.freeAllBuffers()
|
||||||
end
|
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 event = {}
|
||||||
|
|
||||||
local bufferTime = 0.1 -- A little bit of buffer time so events won't be skipped by accident.
|
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 loadfile = ... -- raw loadfile from boot.lua
|
||||||
local unicode, component, computer
|
local component, computer
|
||||||
|
|
||||||
if loadfile then
|
if loadfile then
|
||||||
unicode = loadfile("/lib/unicode.lua")(loadfile)
|
unicode = loadfile("/halyde/lib/unicode.lua")(loadfile)
|
||||||
component = loadfile("/lib/component.lua")(loadfile)
|
component = loadfile("/halyde/lib/component.lua")(loadfile)
|
||||||
computer = _G.computer
|
computer = _G.computer
|
||||||
elseif require then
|
elseif import then
|
||||||
unicode = require("unicode")
|
unicode = import("unicode")
|
||||||
component = require("component")
|
component = import("component")
|
||||||
computer = require("computer")
|
computer = import("computer")
|
||||||
end
|
end
|
||||||
|
|
||||||
local filesystem = {}
|
local filesystem = {}
|
||||||
@@ -30,16 +30,16 @@ function filesystem.canonical(path)
|
|||||||
return "/" .. table.concat(segList, "/")
|
return "/" .. table.concat(segList, "/")
|
||||||
end
|
end
|
||||||
|
|
||||||
function filesystem.concat(path1, path2)
|
function filesystem.concat(...)
|
||||||
checkArg(1, path1, "string")
|
local paths = {...}
|
||||||
checkArg(2, path2, "string")
|
for i, path in ipairs(paths) do
|
||||||
if path1:sub(-1, -1) == "/" then
|
checkArg(i, path, "string")
|
||||||
path1 = path1:sub(1, -2)
|
|
||||||
end
|
end
|
||||||
if path2:sub(1, 1) ~= "/" then
|
local currentPath = paths[1]:match("(.+)/?$")
|
||||||
path2 = "/" .. path2
|
for i = 2, #paths do
|
||||||
|
currentPath = currentPath .. "/" .. paths[i]:match("^/?(.+)/?$")
|
||||||
end
|
end
|
||||||
return path1 .. path2
|
return currentPath
|
||||||
end
|
end
|
||||||
|
|
||||||
function filesystem.absolutePath(path) -- returns the address and absolute path of an object
|
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
|
["backgroundColor"]=0xFFFFFF
|
||||||
}
|
}
|
||||||
|
|
||||||
local component = require("component")
|
local component = import("component")
|
||||||
-- local ocelot = component.proxy(component.list("ocelot")())
|
-- local ocelot = component.proxy(component.list("ocelot")())
|
||||||
local gpu = component.gpu
|
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 gpu = component.proxy(component.list("gpu")())
|
||||||
local resX, resY = gpu.getResolution()
|
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 function loadfile(file)
|
local function loadfile(file)
|
||||||
checkArg(1, file, "string")
|
checkArg(1, file, "string")
|
||||||
@@ -36,36 +17,36 @@ local function handleError(errorMessage)
|
|||||||
return(errorMessage.."\n \n"..debug.traceback())
|
return(errorMessage.."\n \n"..debug.traceback())
|
||||||
end
|
end
|
||||||
|
|
||||||
function loadBoot()
|
function loadthething()
|
||||||
loadfile("/halyde/kernel/boot.lua")(loadfile)
|
loadfile("/halyde/core/boot.lua")(loadfile)
|
||||||
end
|
end
|
||||||
|
|
||||||
gpu.setBackground(0x000000)
|
gpu.setBackground(0x000000)
|
||||||
gpu.fill(1, 1, resX, resY, " ")
|
gpu.fill(1, 1, resx, resy, " ")
|
||||||
|
local result, reason = xpcall(loadthething, handleError)
|
||||||
-- Copying low-level functions in case of post-preload failure
|
|
||||||
local pullSignal = computer.pullSignal
|
|
||||||
local shutdown = computer.shutdown
|
|
||||||
|
|
||||||
local result, reason = xpcall(loadBoot, handleError)
|
|
||||||
if not result then
|
if not result then
|
||||||
|
if import then
|
||||||
|
local computer = import("computer")
|
||||||
|
end
|
||||||
gpu.setBackground(0x000000)
|
gpu.setBackground(0x000000)
|
||||||
gpu.fill(1, 1, resX, resY, " ")
|
gpu.fill(1, 1, resx, resy, " ")
|
||||||
gpu.setBackground(0x800000)
|
gpu.setBackground(0x800000)
|
||||||
gpu.setForeground(0xFFFFFF)
|
gpu.setForeground(0xFFFFFF)
|
||||||
gpu.set(2,2,"A critical error has occurred.")
|
gpu.set(2,2,"A critical error has occurred.")
|
||||||
local i = 4
|
local i = 4
|
||||||
reason = tostring(reason):gsub("\t", " ")
|
reason = reason:gsub("\t", " ")
|
||||||
for line in string.gmatch(reason or "unknown error", "([^\n]*)\n?") do
|
for line in string.gmatch((reason ~= nil and tostring(reason)) or "unknown error", "([^\n]*)\n?") do
|
||||||
gpu.set(2,i,line)
|
gpu.set(2,i,line)
|
||||||
i = i + 1
|
i = i + 1
|
||||||
end
|
end
|
||||||
|
if computer~=nil then
|
||||||
gpu.set(2,i+1, "Press any key to restart.")
|
gpu.set(2,i+1, "Press any key to restart.")
|
||||||
local evname
|
local evname
|
||||||
repeat
|
repeat
|
||||||
evname = pullSignal()
|
evname = computer.pullSignal()
|
||||||
until evname == "key_down"
|
until evname == "key_down"
|
||||||
shutdown(true)
|
computer.shutdown(true)
|
||||||
|
end
|
||||||
while true do
|
while true do
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
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