mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-01-18 10:36:44 +00:00
Update CapyOS
This commit is contained in:
parent
27bfd6d363
commit
bc87363f7c
28 changed files with 786 additions and 656 deletions
|
@ -1 +1 @@
|
|||
shell.exit()
|
||||
shell.exit()
|
||||
|
|
94
Capy64/Assets/Lua/bin/fun/mandelbrot.lua
Normal file
94
Capy64/Assets/Lua/bin/fun/mandelbrot.lua
Normal file
|
@ -0,0 +1,94 @@
|
|||
-- Mandelbrot in Capy64
|
||||
|
||||
local gpu = require("gpu")
|
||||
local timer = require("timer")
|
||||
local event = require("event")
|
||||
local term = require("term")
|
||||
|
||||
-- lower = closer = slower
|
||||
local scale = 4
|
||||
|
||||
-- higher = more detailed = slower
|
||||
local iterations = 100
|
||||
|
||||
local pscale = scale
|
||||
local w, h = gpu.getSize()
|
||||
local px = pscale / w
|
||||
local colorUnit = math.floor(0xffffff / iterations)
|
||||
-- todo: make it interactive
|
||||
local dx, dy = 0, 0
|
||||
local cx, cy = math.floor(w / 2), math.floor(h / 2)
|
||||
|
||||
-- z = z^2 + c
|
||||
local function mandelbrot(zr, zi, cr, ci)
|
||||
return zr ^ 2 - zi ^ 2 + cr,
|
||||
2 * zr * zi + ci
|
||||
end
|
||||
|
||||
local function iter(cr, ci)
|
||||
local zr, zi = 0, 0
|
||||
for i = 1, iterations do
|
||||
zr, zi = mandelbrot(zr, zi, cr, ci)
|
||||
if math.abs(zr) >= (pscale >= 2 and pscale or 2) or math.abs(zi) >= (pscale >= 2 and pscale or 2) then
|
||||
return false, colorUnit, i
|
||||
end
|
||||
end
|
||||
|
||||
return true, 0, iterations
|
||||
end
|
||||
|
||||
local function draw()
|
||||
local buffer <close> = gpu.newBuffer()
|
||||
|
||||
for y = 0, h - 1 do
|
||||
for x = 0, w - 1 do
|
||||
local _, _, i = iter((x - cx + dx * pscale) * px, (y - cy + dy * pscale) * px)
|
||||
buffer[y * w + x] = colorUnit * (iterations - i)
|
||||
end
|
||||
end
|
||||
|
||||
gpu.setBuffer(buffer)
|
||||
end
|
||||
|
||||
-- no idea why it's needed
|
||||
timer.sleep(1)
|
||||
|
||||
draw()
|
||||
|
||||
local tw, th = term.getSize()
|
||||
|
||||
while true do
|
||||
term.setPos(1, th)
|
||||
term.setBackground(0)
|
||||
term.setForeground(0xffffff)
|
||||
term.write("X: " .. dx .. "; Y: " .. dy .. "; S: " .. pscale .. "; " .. px .. "!")
|
||||
local ev = { event.pull("key_down") }
|
||||
if ev[1] == "key_down" then
|
||||
local key = ev[3]
|
||||
if key == "up" then
|
||||
dy = dy - 10 / pscale
|
||||
elseif key == "down" then
|
||||
dy = dy + 10 / pscale
|
||||
elseif key == "right" then
|
||||
dx = dx + 10 / pscale
|
||||
elseif key == "left" then
|
||||
dx = dx - 10 / pscale
|
||||
elseif key == "enter" then
|
||||
draw()
|
||||
elseif key == "page_down" then
|
||||
pscale = pscale * 1.25
|
||||
dx = dx * pscale
|
||||
dy = dy * pscale
|
||||
elseif key == "page_up" then
|
||||
pscale = pscale / 1.25
|
||||
dx = dx / pscale
|
||||
dy = dy / pscale
|
||||
elseif key == "r" then
|
||||
pscale = scale
|
||||
dx = 0
|
||||
dy = 0
|
||||
end
|
||||
end
|
||||
|
||||
px = pscale / w
|
||||
end
|
73
Capy64/Assets/Lua/bin/fun/melt.lua
Normal file
73
Capy64/Assets/Lua/bin/fun/melt.lua
Normal file
|
@ -0,0 +1,73 @@
|
|||
local gpu = require("gpu")
|
||||
local timer = require("timer")
|
||||
local event = require("event")
|
||||
local colors = require("colors")
|
||||
local parallel = require("parallel")
|
||||
|
||||
local melts = 2 ^ 12
|
||||
|
||||
local function contains(arr, val)
|
||||
for k, v in ipairs(arr) do
|
||||
if v == val then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function melt()
|
||||
local w, h = gpu.getSize()
|
||||
local x, y = 0, 0
|
||||
|
||||
while true do
|
||||
local buffer <close> = gpu.getBuffer()
|
||||
for i = 1, melts do
|
||||
local nx = math.random(x, w)
|
||||
local ny = math.random(y, h)
|
||||
|
||||
local c = buffer[ny * w + nx]
|
||||
buffer[(ny + 1) * w + nx] = c
|
||||
end
|
||||
gpu.setBuffer(buffer)
|
||||
|
||||
timer.sleep(10)
|
||||
end
|
||||
end
|
||||
|
||||
local function draw()
|
||||
local ox, oy
|
||||
while true do
|
||||
local ev, b, x, y = event.pull("mouse_move", "mouse_down")
|
||||
|
||||
if ev == "mouse_down" then
|
||||
if b == 1 then
|
||||
ox = x
|
||||
oy = y
|
||||
end
|
||||
elseif ev == "mouse_move" then
|
||||
if contains(b, 1) then
|
||||
gpu.plot(x, y, colors.red)
|
||||
gpu.drawLine(x, y, ox, oy, colors.red)
|
||||
ox, oy = x, y
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function random()
|
||||
local w, h = gpu.getSize()
|
||||
while true do
|
||||
for i = 1, 24 do
|
||||
gpu.drawString(
|
||||
math.random(-7, w),
|
||||
math.random(-13, h),
|
||||
math.random(0, 0xffffff),
|
||||
string.char(math.random(32, 127))
|
||||
)
|
||||
end
|
||||
|
||||
timer.sleep(100)
|
||||
end
|
||||
end
|
||||
|
||||
parallel.waitForAny(draw, melt, random)
|
|
@ -5,7 +5,7 @@ local term = require("term")
|
|||
local function slowPrint(text, delay)
|
||||
for i = 1, #text do
|
||||
local ch = text:sub(i, i)
|
||||
write(ch)
|
||||
io.write(ch)
|
||||
timer.sleep(delay)
|
||||
end
|
||||
print()
|
||||
|
@ -14,4 +14,4 @@ end
|
|||
local color = colors[math.random(1, #colors)]
|
||||
|
||||
term.setForeground(color)
|
||||
slowPrint("Hello, World!", 50)
|
||||
slowPrint("Hello, World!", 50)
|
||||
|
|
|
@ -14,7 +14,7 @@ if not fs.isDir(dir) then
|
|||
end
|
||||
|
||||
local files = fs.list(dir)
|
||||
for k,v in ipairs(files) do
|
||||
for k, v in ipairs(files) do
|
||||
if fs.isDir(fs.combine(dir, v)) then
|
||||
term.setForeground(colors.lightBlue)
|
||||
print(v .. "/")
|
||||
|
@ -22,4 +22,4 @@ for k,v in ipairs(files) do
|
|||
term.setForeground(colors.white)
|
||||
print(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,9 +19,6 @@ local tEnv = {
|
|||
__tostring = function() return "Call exit() to exit." end,
|
||||
__call = function() bRunning = false end,
|
||||
}),
|
||||
["_echo"] = function(...)
|
||||
return ...
|
||||
end,
|
||||
}
|
||||
setmetatable(tEnv, { __index = _ENV })
|
||||
|
||||
|
@ -35,9 +32,9 @@ print("Call exit() to exit.")
|
|||
term.setForeground(colours.white)
|
||||
|
||||
while bRunning do
|
||||
term.setForeground( colours.yellow )
|
||||
write("> ")
|
||||
term.setForeground( colours.white )
|
||||
term.setForeground(colours.yellow)
|
||||
io.write("> ")
|
||||
term.setForeground(colours.white)
|
||||
|
||||
local s = io.read(nil, tCommandHistory)
|
||||
if s:match("%S") and tCommandHistory[#tCommandHistory] ~= s then
|
||||
|
@ -46,7 +43,7 @@ while bRunning do
|
|||
|
||||
local nForcePrint = 0
|
||||
local func, e = load(s, "=lua", "t", tEnv)
|
||||
local func2 = load("return _echo(" .. s .. ");", "=lua", "t", tEnv)
|
||||
local func2 = load("return " .. s, "=lua", "t", tEnv)
|
||||
if not func then
|
||||
if func2 then
|
||||
func = func2
|
||||
|
@ -69,10 +66,10 @@ while bRunning do
|
|||
n = n + 1
|
||||
end
|
||||
else
|
||||
print(tResults[2])
|
||||
io.stderr.print(tResults[2])
|
||||
end
|
||||
else
|
||||
print(e)
|
||||
io.stderr.print(e)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
local fs = require("fs")
|
||||
local args = {...}
|
||||
local args = { ... }
|
||||
|
||||
if #args == 0 then
|
||||
print("Usage: mkdir <directory>")
|
||||
|
@ -11,4 +11,4 @@ if fs.exists(dir) then
|
|||
error("Path already exists", 0)
|
||||
end
|
||||
|
||||
fs.makeDir(dir)
|
||||
fs.makeDir(dir)
|
||||
|
|
|
@ -1 +1 @@
|
|||
print(shell.getDir())
|
||||
print(shell.getDir())
|
||||
|
|
|
@ -4,4 +4,4 @@ print("Goodbye!")
|
|||
|
||||
timer.sleep(1000)
|
||||
|
||||
os.shutdown(true)
|
||||
os.shutdown(true)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
local fs = require("fs")
|
||||
|
||||
local args = {...}
|
||||
local args = { ... }
|
||||
if #args == 0 then
|
||||
print("Usage: rm <file>")
|
||||
return
|
||||
end
|
||||
|
||||
local file = shell.resolve(args[1])
|
||||
fs.delete(file, true)
|
||||
fs.delete(file, true)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
local term = require("term")
|
||||
local colors = require("colors")
|
||||
local io = require("io")
|
||||
local fs = require("fs")
|
||||
|
||||
local exit = false
|
||||
|
@ -17,17 +16,6 @@ local function buildEnvironment()
|
|||
}, { __index = _G })
|
||||
end
|
||||
|
||||
local function printError(...)
|
||||
local cfg = {term.getForeground()}
|
||||
local cbg = {term.getBackground()}
|
||||
|
||||
term.setForeground(colors.red)
|
||||
term.setBackground(colors.black)
|
||||
print(...)
|
||||
term.setForeground(table.unpack(cfg))
|
||||
term.setBackground(table.unpack(cbg))
|
||||
end
|
||||
|
||||
local function tokenise(...)
|
||||
local sLine = table.concat({ ... }, " ")
|
||||
local tWords = {}
|
||||
|
@ -58,6 +46,10 @@ function shell.resolve(path)
|
|||
return fs.combine("", path)
|
||||
end
|
||||
|
||||
if path:sub(1, 1) == "~" then
|
||||
return fs.combine(shell.homePath, path)
|
||||
end
|
||||
|
||||
return fs.combine(currentDir, path)
|
||||
end
|
||||
|
||||
|
@ -67,7 +59,7 @@ function shell.resolveProgram(path)
|
|||
end
|
||||
|
||||
for seg in shell.path:gmatch("[^;]+") do
|
||||
local resolved = seg:gsub("%?", path)
|
||||
local resolved = shell.resolve(seg:gsub("%?", path))
|
||||
if fs.exists(resolved) and not fs.isDir(resolved) then
|
||||
return resolved
|
||||
end
|
||||
|
@ -80,7 +72,7 @@ function shell.run(...)
|
|||
local path = shell.resolveProgram(command)
|
||||
|
||||
if not path then
|
||||
printError("Command not found: " .. command)
|
||||
io.stderr.print("Command not found: " .. command)
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -89,13 +81,13 @@ function shell.run(...)
|
|||
local func, err = loadfile(path, "t", env)
|
||||
|
||||
if not func then
|
||||
printError(err)
|
||||
io.stderr.print(err)
|
||||
return false
|
||||
end
|
||||
|
||||
local ok, err = pcall(func, table.unpack(args, 2))
|
||||
if not ok then
|
||||
printError(err)
|
||||
io.stderr.print(err)
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -106,25 +98,29 @@ function shell.exit()
|
|||
exit = true
|
||||
end
|
||||
|
||||
if not fs.exists(shell.homePath) then
|
||||
fs.makeDir(shell.homePath)
|
||||
end
|
||||
|
||||
local history = {}
|
||||
local lastExecSuccess = true
|
||||
while not exit do
|
||||
term.setBackground(colors.black)
|
||||
term.setForeground(colors.white)
|
||||
write(":")
|
||||
io.write(":")
|
||||
term.setForeground(colors.lightBlue)
|
||||
local currentDir = shell.getDir()
|
||||
if currentDir == shell.homePath then
|
||||
write("~")
|
||||
io.write("~")
|
||||
else
|
||||
write(currentDir)
|
||||
io.write(currentDir)
|
||||
end
|
||||
|
||||
|
||||
if lastExecSuccess then
|
||||
term.setForeground(colors.yellow)
|
||||
else
|
||||
term.setForeground(colors.red)
|
||||
end
|
||||
write("$ ")
|
||||
io.write("$ ")
|
||||
|
||||
term.setForeground(colors.white)
|
||||
local line = io.read(nil, history)
|
||||
|
|
|
@ -4,4 +4,4 @@ print("Goodbye!")
|
|||
|
||||
timer.sleep(1000)
|
||||
|
||||
os.shutdown(false)
|
||||
os.shutdown(false)
|
||||
|
|
1
Capy64/Assets/Lua/bin/version.lua
Normal file
1
Capy64/Assets/Lua/bin/version.lua
Normal file
|
@ -0,0 +1 @@
|
|||
print(string.format("%s @ %s - %s", os.version(), _HOST, _VERSION))
|
|
@ -1,7 +1,7 @@
|
|||
local http = require("http")
|
||||
local fs = require("fs")
|
||||
|
||||
local args = {...}
|
||||
local args = { ... }
|
||||
|
||||
if not http then
|
||||
error("HTTP is not enabled", 0)
|
||||
|
@ -12,21 +12,23 @@ if #args == 0 then
|
|||
return false
|
||||
end
|
||||
|
||||
local outputName = args[2] or fs.getName(args[1])
|
||||
local outputName = args[2] or fs.getName(args[1])
|
||||
local outputPath = shell.resolve(outputName)
|
||||
|
||||
if not http.checkURL(args[1]) then
|
||||
error("Invalid URL", 0)
|
||||
end
|
||||
|
||||
local response, err = http.get(args[1])
|
||||
local response <close>, err = http.get(args[1], nil, {
|
||||
binary = true,
|
||||
})
|
||||
if not response then
|
||||
error(err, 0)
|
||||
end
|
||||
|
||||
local file = fs.open(outputPath, "w")
|
||||
local file <close> = fs.open(outputPath, "w")
|
||||
file:write(response:readAll())
|
||||
file:close()
|
||||
response:close()
|
||||
|
||||
print("File written to " .. outputPath)
|
||||
print("File written to " .. outputPath)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
os.print = print
|
3
Capy64/Assets/Lua/boot/00_package.lua
Normal file
3
Capy64/Assets/Lua/boot/00_package.lua
Normal file
|
@ -0,0 +1,3 @@
|
|||
package.path = "/lib/?.lua;/lib/?/init.lua;" .. package.path
|
||||
|
||||
_G.io = require("io")
|
|
@ -1 +0,0 @@
|
|||
package.path = "/lib/?.lua;/lib/?/init.lua;" .. package.path
|
15
Capy64/Assets/Lua/boot/01_stdio.lua
Normal file
15
Capy64/Assets/Lua/boot/01_stdio.lua
Normal file
|
@ -0,0 +1,15 @@
|
|||
function _G.print(...)
|
||||
local args = { ... }
|
||||
local size = #args
|
||||
local lines = 0
|
||||
for n, v in ipairs(args) do
|
||||
local s = tostring(v)
|
||||
if n < size then
|
||||
s = s .. "\t"
|
||||
end
|
||||
lines = lines + io.write(s)
|
||||
end
|
||||
lines = lines + io.write("\n")
|
||||
|
||||
return lines
|
||||
end
|
|
@ -31,16 +31,16 @@ function http.request(url, body, headers, options)
|
|||
end
|
||||
|
||||
local requestId = http.requestAsync(url, body, headers, options)
|
||||
local ev, id, par
|
||||
local ev, id, data, info
|
||||
repeat
|
||||
ev, id, par = event.pull("http_response", "http_failure")
|
||||
ev, id, data, info = event.pull("http_response", "http_failure")
|
||||
until id == requestId
|
||||
|
||||
if ev == "http_failure" then
|
||||
return nil, par
|
||||
return nil, data
|
||||
end
|
||||
|
||||
return par
|
||||
return data, info
|
||||
end
|
||||
|
||||
function http.get(url, headers, options)
|
|
@ -1,79 +0,0 @@
|
|||
local term = require("term")
|
||||
local expect = require("expect").expect
|
||||
|
||||
function write(sText)
|
||||
expect(1, sText, "string", "number")
|
||||
|
||||
local w, h = term.getSize()
|
||||
local x, y = term.getPos()
|
||||
|
||||
local nLinesPrinted = 0
|
||||
local function newLine()
|
||||
if y + 1 <= h then
|
||||
term.setPos(1, y + 1)
|
||||
else
|
||||
term.setPos(1, h)
|
||||
term.scroll(1)
|
||||
end
|
||||
x, y = term.getPos()
|
||||
nLinesPrinted = nLinesPrinted + 1
|
||||
end
|
||||
|
||||
-- Print the line with proper word wrapping
|
||||
sText = tostring(sText)
|
||||
while #sText > 0 do
|
||||
local whitespace = string.match(sText, "^[ \t]+")
|
||||
if whitespace then
|
||||
-- Print whitespace
|
||||
term.write(whitespace)
|
||||
x, y = term.getPos()
|
||||
sText = string.sub(sText, #whitespace + 1)
|
||||
end
|
||||
|
||||
local newline = string.match(sText, "^\n")
|
||||
if newline then
|
||||
-- Print newlines
|
||||
newLine()
|
||||
sText = string.sub(sText, 2)
|
||||
end
|
||||
|
||||
local text = string.match(sText, "^[^ \t\n]+")
|
||||
if text then
|
||||
sText = string.sub(sText, #text + 1)
|
||||
if #text > w then
|
||||
-- Print a multiline word
|
||||
while #text > 0 do
|
||||
if x > w then
|
||||
newLine()
|
||||
end
|
||||
term.write(text)
|
||||
text = string.sub(text, w - x + 2)
|
||||
x, y = term.getPos()
|
||||
end
|
||||
else
|
||||
-- Print a word normally
|
||||
if x + #text - 1 > w then
|
||||
newLine()
|
||||
end
|
||||
term.write(text)
|
||||
x, y = term.getPos()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nLinesPrinted
|
||||
end
|
||||
|
||||
function print(...)
|
||||
local nLinesPrinted = 0
|
||||
local nLimit = select("#", ...)
|
||||
for n = 1, nLimit do
|
||||
local s = tostring(select(n, ...))
|
||||
if n < nLimit then
|
||||
s = s .. "\t"
|
||||
end
|
||||
nLinesPrinted = nLinesPrinted + write(s)
|
||||
end
|
||||
nLinesPrinted = nLinesPrinted + write("\n")
|
||||
return nLinesPrinted
|
||||
end
|
|
@ -11,4 +11,4 @@ function timer.sleep(n)
|
|||
repeat
|
||||
local _, par = event.pull("timer")
|
||||
until par == timerId
|
||||
end
|
||||
end
|
|
@ -1,29 +1,14 @@
|
|||
local term = require("term")
|
||||
local colors = require("colors")
|
||||
|
||||
term.setSize(51, 19)
|
||||
|
||||
term.setForeground(0x59c9ff)
|
||||
term.setBackground(colors.black)
|
||||
term.clear()
|
||||
term.setPos(1, 1)
|
||||
|
||||
print(os.version())
|
||||
term.write(os.version())
|
||||
term.setPos(1, 2)
|
||||
|
||||
local func, err = loadfile("/bin/shell.lua")
|
||||
if func then
|
||||
while true do
|
||||
local ok, err = pcall(func)
|
||||
if not ok then
|
||||
print(err)
|
||||
end
|
||||
end
|
||||
else
|
||||
print(err)
|
||||
end
|
||||
dofile("/bin/shell.lua")
|
||||
|
||||
|
||||
|
||||
print("Press any key to continue...")
|
||||
coroutine.yield("key_down")
|
||||
os.shutdown(false)
|
||||
os.shutdown(false)
|
||||
|
|
|
@ -1,6 +1,47 @@
|
|||
local fs = require("fs")
|
||||
print("Starting CapyOS")
|
||||
|
||||
local term = require("term")
|
||||
local fs = require("fs")
|
||||
local gpu = require("gpu")
|
||||
|
||||
local nPrint = print
|
||||
local function showError(err)
|
||||
nPrint(err)
|
||||
local x, y = term.getPos()
|
||||
term.setForeground(0xff0000)
|
||||
term.setPos(1, y)
|
||||
term.write(err)
|
||||
|
||||
term.setPos(1, y + 1)
|
||||
term.setForeground(0xffffff)
|
||||
term.write("Press any key to continue")
|
||||
|
||||
coroutine.yield("key_down")
|
||||
end
|
||||
|
||||
function os.version()
|
||||
return "CapyOS 0.0.1"
|
||||
end
|
||||
|
||||
term.setSize(51, 19)
|
||||
gpu.setScale(2)
|
||||
|
||||
term.setPos(1, 1)
|
||||
term.write(_HOST)
|
||||
|
||||
local files = fs.list("/boot")
|
||||
for k, v in ipairs(files) do
|
||||
dofile("/boot/" .. v)
|
||||
end
|
||||
local func, err = loadfile("/boot/" .. v)
|
||||
if not func then
|
||||
showError(err)
|
||||
break
|
||||
end
|
||||
|
||||
local ok, err = pcall(func)
|
||||
|
||||
if not ok then
|
||||
showError(debug.traceback(err))
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
local expect = require("expect")
|
||||
|
||||
local palette = {
|
||||
{
|
||||
"white",
|
||||
|
@ -65,29 +67,28 @@ local palette = {
|
|||
}
|
||||
}
|
||||
|
||||
--[[local colors = {
|
||||
white = 0xf0f0f0,
|
||||
orange = 0xf2b233,
|
||||
magenta = 0xe57fd8,
|
||||
lightBlue = 0x99b2f2,
|
||||
yellow = 0xdede6c,
|
||||
lime = 0x7fcc19,
|
||||
pink = 0xf2b2cc,
|
||||
gray = 0x4c4c4c,
|
||||
lightGray = 0x999999,
|
||||
cyan = 0x4c99b2,
|
||||
purple = 0xb266e5,
|
||||
blue = 0x3366cc,
|
||||
brown = 0x7f664c,
|
||||
green = 0x57a64e,
|
||||
red = 0xcc4c4c,
|
||||
black = 0x111111,
|
||||
}]]
|
||||
|
||||
local colors = {}
|
||||
for k, v in ipairs(palette) do
|
||||
colors[v[1]] = v[2]
|
||||
colors[k] = v[2]
|
||||
end
|
||||
|
||||
return colors;
|
||||
function colors.packRGB(r, g, b)
|
||||
expect(1, r, "number")
|
||||
expect(2, g, "number")
|
||||
expect(3, b, "number")
|
||||
|
||||
return (r << 16) +
|
||||
(g << 8) +
|
||||
b
|
||||
end
|
||||
|
||||
function colors.unpackRGB(rgb)
|
||||
expect(1, rgb, "number")
|
||||
|
||||
return (rgb >> 16) & 0xff,
|
||||
(rgb >> 8) & 0xff,
|
||||
rgb & 0xff
|
||||
end
|
||||
|
||||
return colors;
|
||||
|
|
|
@ -1,123 +1,52 @@
|
|||
--[[- The @{cc.expect} library provides helper functions for verifying that
|
||||
function arguments are well-formed and of the correct type.
|
||||
-- Credits: https://github.com/Ocawesome101/recrafted
|
||||
|
||||
@module cc.expect
|
||||
@since 1.84.0
|
||||
@changed 1.96.0 The module can now be called directly as a function, which wraps around `expect.expect`.
|
||||
@usage Define a basic function and check it has the correct arguments.
|
||||
-- cc.expect
|
||||
|
||||
local expect = require "cc.expect"
|
||||
local expect, field = expect.expect, expect.field
|
||||
local _expect = {}
|
||||
|
||||
local function add_person(name, info)
|
||||
expect(1, name, "string")
|
||||
expect(2, info, "table", "nil")
|
||||
local function checkType(index, valueType, value, ...)
|
||||
local expected = table.pack(...)
|
||||
local isType = false
|
||||
|
||||
if info then
|
||||
print("Got age=", field(info, "age", "number"))
|
||||
print("Got gender=", field(info, "gender", "string", "nil"))
|
||||
for i = 1, expected.n, 1 do
|
||||
if type(value) == expected[i] then
|
||||
isType = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
add_person("Anastazja") -- `info' is optional
|
||||
add_person("Kion", { age = 23 }) -- `gender' is optional
|
||||
add_person("Caoimhin", { age = 23, gender = true }) -- error!
|
||||
]]
|
||||
|
||||
local native_select, native_type = select, type
|
||||
|
||||
local function get_type_names(...)
|
||||
local types = table.pack(...)
|
||||
for i = types.n, 1, -1 do
|
||||
if types[i] == "nil" then table.remove(types, i) end
|
||||
if not isType then
|
||||
error(string.format("bad %s %s (%s expected, got %s)", valueType,
|
||||
index, table.concat(expected, " or "), type(value)), 3)
|
||||
end
|
||||
|
||||
if #types <= 1 then
|
||||
return tostring(...)
|
||||
else
|
||||
return table.concat(types, ", ", 1, #types - 1) .. " or " .. types[#types]
|
||||
return value
|
||||
end
|
||||
|
||||
function _expect.expect(index, value, ...)
|
||||
return checkType(("#%d"):format(index), "argument", value, ...)
|
||||
end
|
||||
|
||||
function _expect.field(tbl, index, ...)
|
||||
_expect.expect(1, tbl, "table")
|
||||
_expect.expect(2, index, "string")
|
||||
return checkType(("%q"):format(index), "field", tbl[index], ...)
|
||||
end
|
||||
|
||||
function _expect.range(num, min, max)
|
||||
_expect.expect(1, num, "number")
|
||||
_expect.expect(2, min, "number", "nil")
|
||||
_expect.expect(3, max, "number", "nil")
|
||||
min = min or -math.huge
|
||||
max = max or math.huge
|
||||
if num < min or num > max then
|
||||
error(("number outside of range (expected %d to be within %d and %d")
|
||||
:format(num, min, max), 2)
|
||||
end
|
||||
end
|
||||
|
||||
--- Expect an argument to have a specific type.
|
||||
--
|
||||
-- @tparam number index The 1-based argument index.
|
||||
-- @param value The argument's value.
|
||||
-- @tparam string ... The allowed types of the argument.
|
||||
-- @return The given `value`.
|
||||
-- @throws If the value is not one of the allowed types.
|
||||
local function expect(index, value, ...)
|
||||
local t = native_type(value)
|
||||
for i = 1, native_select("#", ...) do
|
||||
if t == native_select(i, ...) then return value end
|
||||
end
|
||||
setmetatable(_expect, { __call = function(_, ...)
|
||||
return _expect.expect(...)
|
||||
end })
|
||||
|
||||
-- If we can determine the function name with a high level of confidence, try to include it.
|
||||
local name
|
||||
local ok, info = pcall(debug.getinfo, 3, "nS")
|
||||
if ok and info.name and info.name ~= "" and info.what ~= "C" then name = info.name end
|
||||
|
||||
local type_names = get_type_names(...)
|
||||
if name then
|
||||
error(("bad argument #%d to '%s' (expected %s, got %s)"):format(index, name, type_names, t), 3)
|
||||
else
|
||||
error(("bad argument #%d (expected %s, got %s)"):format(index, type_names, t), 3)
|
||||
end
|
||||
end
|
||||
|
||||
--- Expect an field to have a specific type.
|
||||
--
|
||||
-- @tparam table tbl The table to index.
|
||||
-- @tparam string index The field name to check.
|
||||
-- @tparam string ... The allowed types of the argument.
|
||||
-- @return The contents of the given field.
|
||||
-- @throws If the field is not one of the allowed types.
|
||||
local function field(tbl, index, ...)
|
||||
expect(1, tbl, "table")
|
||||
expect(2, index, "string")
|
||||
|
||||
local value = tbl[index]
|
||||
local t = native_type(value)
|
||||
for i = 1, native_select("#", ...) do
|
||||
if t == native_select(i, ...) then return value end
|
||||
end
|
||||
|
||||
if value == nil then
|
||||
error(("field '%s' missing from table"):format(index), 3)
|
||||
else
|
||||
error(("bad field '%s' (expected %s, got %s)"):format(index, get_type_names(...), t), 3)
|
||||
end
|
||||
end
|
||||
|
||||
local function is_nan(num)
|
||||
return num ~= num
|
||||
end
|
||||
|
||||
--- Expect a number to be within a specific range.
|
||||
--
|
||||
-- @tparam number num The value to check.
|
||||
-- @tparam number min The minimum value, if nil then `-math.huge` is used.
|
||||
-- @tparam number max The maximum value, if nil then `math.huge` is used.
|
||||
-- @return The given `value`.
|
||||
-- @throws If the value is outside of the allowed range.
|
||||
-- @since 1.96.0
|
||||
local function range(num, min, max)
|
||||
expect(1, num, "number")
|
||||
min = expect(2, min, "number", "nil") or -math.huge
|
||||
max = expect(3, max, "number", "nil") or math.huge
|
||||
if min > max then
|
||||
error("min must be less than or equal to max)", 2)
|
||||
end
|
||||
|
||||
if is_nan(num) or num < min or num > max then
|
||||
error(("number outside of range (expected %s to be within %s and %s)"):format(num, min, max), 3)
|
||||
end
|
||||
|
||||
return num
|
||||
end
|
||||
|
||||
return setmetatable({
|
||||
expect = expect,
|
||||
field = field,
|
||||
range = range,
|
||||
}, { __call = function(_, ...) return expect(...) end })
|
||||
return _expect
|
||||
|
|
|
@ -4,280 +4,279 @@ local term = require("term")
|
|||
|
||||
local io = {}
|
||||
|
||||
function io.read(_sReplaceChar, _tHistory, _fnComplete, _sDefault)
|
||||
expect(1, _sReplaceChar, "string", "nil")
|
||||
expect(2, _tHistory, "table", "nil")
|
||||
expect(3, _fnComplete, "function", "nil")
|
||||
expect(4, _sDefault, "string", "nil")
|
||||
function io.write(text)
|
||||
text = tostring(text)
|
||||
|
||||
local lines = 0
|
||||
local w, h = term.getSize()
|
||||
|
||||
local function inc_cy(cy)
|
||||
lines = lines + 1
|
||||
|
||||
if cy > h - 1 then
|
||||
term.scroll(1)
|
||||
return cy
|
||||
else
|
||||
return cy + 1
|
||||
end
|
||||
end
|
||||
|
||||
while #text > 0 do
|
||||
local nl = text:find("\n") or #text
|
||||
local chunk = text:sub(1, nl)
|
||||
text = text:sub(#chunk + 1)
|
||||
|
||||
local has_nl = chunk:sub(-1) == "\n"
|
||||
if has_nl then chunk = chunk:sub(1, -2) end
|
||||
|
||||
local cx, cy = term.getPos()
|
||||
while #chunk > 0 do
|
||||
if cx > w then
|
||||
term.setPos(1, inc_cy(cy))
|
||||
cx, cy = term.getPos()
|
||||
end
|
||||
|
||||
local to_write = chunk:sub(1, w - cx + 1)
|
||||
term.write(to_write)
|
||||
|
||||
chunk = chunk:sub(#to_write + 1)
|
||||
cx, cy = term.getPos()
|
||||
end
|
||||
|
||||
if has_nl then
|
||||
term.setPos(1, inc_cy(cy))
|
||||
end
|
||||
end
|
||||
|
||||
return lines
|
||||
end
|
||||
|
||||
local empty = {}
|
||||
function io.read(replace, history, complete, default)
|
||||
expect(1, replace, "string", "nil")
|
||||
expect(2, history, "table", "nil")
|
||||
expect(3, complete, "function", "nil")
|
||||
expect(4, default, "string", "nil")
|
||||
|
||||
if replace then replace = replace:sub(1, 1) end
|
||||
local hist = history or {}
|
||||
history = {}
|
||||
for i = 1, #hist, 1 do
|
||||
history[i] = hist[i]
|
||||
end
|
||||
|
||||
local buffer = default or ""
|
||||
local prev_buf = buffer
|
||||
history[#history + 1] = buffer
|
||||
|
||||
local hist_pos = #history
|
||||
local cursor_pos = 0
|
||||
|
||||
local stx, sty = term.getPos()
|
||||
local w, h = term.getSize()
|
||||
|
||||
local dirty = false
|
||||
local completions = {}
|
||||
local comp_id = 0
|
||||
|
||||
local function clearCompletion()
|
||||
if completions[comp_id] then
|
||||
write((" "):rep(#completions[comp_id]))
|
||||
end
|
||||
end
|
||||
|
||||
local function full_redraw(force)
|
||||
if force or dirty then
|
||||
if complete and buffer ~= prev_buf then
|
||||
completions = complete(buffer) or empty
|
||||
comp_id = math.min(1, #completions)
|
||||
end
|
||||
prev_buf = buffer
|
||||
|
||||
term.setPos(stx, sty)
|
||||
local text = buffer
|
||||
if replace then text = replace:rep(#text) end
|
||||
local ln = io.write(text)
|
||||
|
||||
if completions[comp_id] then
|
||||
local oldfg = term.getForeground()
|
||||
local oldbg = term.getBackground()
|
||||
term.setForeground(colors.white)
|
||||
term.setBackground(colors.gray)
|
||||
ln = ln + write(completions[comp_id])
|
||||
term.setForeground(oldfg)
|
||||
term.setBackground(oldbg)
|
||||
else
|
||||
ln = ln + io.write(" ")
|
||||
end
|
||||
|
||||
if sty + ln > h then
|
||||
sty = sty - (sty + ln - h)
|
||||
end
|
||||
end
|
||||
|
||||
-- set cursor to the appropriate spot
|
||||
local cx, cy = stx, sty
|
||||
cx = cx + #buffer - cursor_pos -- + #(completions[comp_id] or "")
|
||||
while cx > w do
|
||||
cx = cx - w
|
||||
cy = cy + 1
|
||||
end
|
||||
term.setPos(cx, cy)
|
||||
end
|
||||
|
||||
term.setBlink(true)
|
||||
|
||||
local sLine
|
||||
if type(_sDefault) == "string" then
|
||||
sLine = _sDefault
|
||||
else
|
||||
sLine = ""
|
||||
end
|
||||
local nHistoryPos
|
||||
local nPos, nScroll = #sLine, 0
|
||||
if _sReplaceChar then
|
||||
_sReplaceChar = string.sub(_sReplaceChar, 1, 1)
|
||||
end
|
||||
|
||||
local tCompletions
|
||||
local nCompletion
|
||||
local function recomplete()
|
||||
if _fnComplete and nPos == #sLine then
|
||||
tCompletions = _fnComplete(sLine)
|
||||
if tCompletions and #tCompletions > 0 then
|
||||
nCompletion = 1
|
||||
else
|
||||
nCompletion = nil
|
||||
end
|
||||
else
|
||||
tCompletions = nil
|
||||
nCompletion = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function uncomplete()
|
||||
tCompletions = nil
|
||||
nCompletion = nil
|
||||
end
|
||||
|
||||
local w = term.getSize()
|
||||
local sx = term.getPos()
|
||||
|
||||
local function redraw(_bClear)
|
||||
local cursor_pos = nPos - nScroll
|
||||
if sx + cursor_pos >= w then
|
||||
-- We've moved beyond the RHS, ensure we're on the edge.
|
||||
nScroll = sx + nPos - w
|
||||
elseif cursor_pos < 0 then
|
||||
-- We've moved beyond the LHS, ensure we're on the edge.
|
||||
nScroll = nPos
|
||||
end
|
||||
|
||||
local _, cy = term.getPos()
|
||||
term.setPos(sx, cy)
|
||||
local sReplace = _bClear and " " or _sReplaceChar
|
||||
if sReplace then
|
||||
term.write(string.rep(sReplace, math.max(#sLine - nScroll, 0)))
|
||||
else
|
||||
term.write(string.sub(sLine, nScroll + 1))
|
||||
end
|
||||
|
||||
if nCompletion then
|
||||
local sCompletion = tCompletions[nCompletion]
|
||||
local oldText, oldBg
|
||||
if not _bClear then
|
||||
oldText = term.getForeground()
|
||||
oldBg = term.getBackground()
|
||||
term.setForeground(colors.white)
|
||||
term.setBackground(colors.gray)
|
||||
end
|
||||
if sReplace then
|
||||
term.write(string.rep(sReplace, #sCompletion))
|
||||
else
|
||||
term.write(sCompletion)
|
||||
end
|
||||
if not _bClear then
|
||||
term.setForeground(oldText)
|
||||
term.setBackground(oldBg)
|
||||
end
|
||||
end
|
||||
|
||||
term.setPos(sx + nPos - nScroll, cy)
|
||||
end
|
||||
|
||||
local function clear()
|
||||
redraw(true)
|
||||
end
|
||||
|
||||
recomplete()
|
||||
redraw()
|
||||
|
||||
local function acceptCompletion()
|
||||
if nCompletion then
|
||||
-- Clear
|
||||
clear()
|
||||
|
||||
-- Find the common prefix of all the other suggestions which start with the same letter as the current one
|
||||
local sCompletion = tCompletions[nCompletion]
|
||||
sLine = sLine .. sCompletion
|
||||
nPos = #sLine
|
||||
|
||||
-- Redraw
|
||||
recomplete()
|
||||
redraw()
|
||||
end
|
||||
end
|
||||
while true do
|
||||
local sEvent, param, param1, param2 = event.pull()
|
||||
if sEvent == "char" then
|
||||
-- Typed key
|
||||
clear()
|
||||
sLine = string.sub(sLine, 1, nPos) .. param .. string.sub(sLine, nPos + 1)
|
||||
nPos = nPos + 1
|
||||
recomplete()
|
||||
redraw()
|
||||
full_redraw()
|
||||
-- get input
|
||||
local evt, par1, par2 = event.pull()
|
||||
|
||||
elseif sEvent == "paste" then
|
||||
-- Pasted text
|
||||
clear()
|
||||
sLine = string.sub(sLine, 1, nPos) .. param .. string.sub(sLine, nPos + 1)
|
||||
nPos = nPos + #param
|
||||
recomplete()
|
||||
redraw()
|
||||
if evt == "char" then
|
||||
dirty = true
|
||||
clearCompletion()
|
||||
if cursor_pos == 0 then
|
||||
buffer = buffer .. par1
|
||||
elseif cursor_pos == #buffer then
|
||||
buffer = par1 .. buffer
|
||||
else
|
||||
buffer = buffer:sub(0, -cursor_pos - 1) .. par1 .. buffer:sub(-cursor_pos)
|
||||
end
|
||||
|
||||
elseif sEvent == "key_down" then
|
||||
if param1 == "enter" then
|
||||
-- Enter/Numpad Enter
|
||||
if nCompletion then
|
||||
clear()
|
||||
uncomplete()
|
||||
redraw()
|
||||
end
|
||||
break
|
||||
elseif evt == "paste" then
|
||||
dirty = true
|
||||
clearCompletion()
|
||||
if cursor_pos == 0 then
|
||||
buffer = buffer .. par1
|
||||
elseif cursor_pos == #buffer then
|
||||
buffer = par1 .. buffer
|
||||
else
|
||||
buffer = buffer:sub(0, -cursor_pos - 1) .. par1 ..
|
||||
buffer:sub(-cursor_pos + (#par1 - 1))
|
||||
end
|
||||
|
||||
elseif param1 == "left" then
|
||||
-- Left
|
||||
if nPos > 0 then
|
||||
clear()
|
||||
nPos = nPos - 1
|
||||
recomplete()
|
||||
redraw()
|
||||
elseif evt == "key_down" then
|
||||
if par2 == "back" and #buffer > 0 then
|
||||
dirty = true
|
||||
if cursor_pos == 0 then
|
||||
buffer = buffer:sub(1, -2)
|
||||
clearCompletion()
|
||||
elseif cursor_pos < #buffer then
|
||||
buffer = buffer:sub(0, -cursor_pos - 2) .. buffer:sub(-cursor_pos)
|
||||
end
|
||||
|
||||
elseif param1 == "right" then
|
||||
-- Right
|
||||
if nPos < #sLine then
|
||||
-- Move right
|
||||
clear()
|
||||
nPos = nPos + 1
|
||||
recomplete()
|
||||
redraw()
|
||||
elseif par2 == "delete" and cursor_pos > 0 then
|
||||
dirty = true
|
||||
|
||||
if cursor_pos == #buffer then
|
||||
buffer = buffer:sub(2)
|
||||
elseif cursor_pos == 1 then
|
||||
buffer = buffer:sub(1, -2)
|
||||
else
|
||||
-- Accept autocomplete
|
||||
acceptCompletion()
|
||||
buffer = buffer:sub(0, -cursor_pos - 1) .. buffer:sub(-cursor_pos + 1)
|
||||
end
|
||||
cursor_pos = cursor_pos - 1
|
||||
|
||||
elseif param1 == "up" or param1 == "down" then
|
||||
-- Up or down
|
||||
if nCompletion then
|
||||
-- Cycle completions
|
||||
clear()
|
||||
if param == "up" then
|
||||
nCompletion = nCompletion - 1
|
||||
if nCompletion < 1 then
|
||||
nCompletion = #tCompletions
|
||||
end
|
||||
elseif param == "down" then
|
||||
nCompletion = nCompletion + 1
|
||||
if nCompletion > #tCompletions then
|
||||
nCompletion = 1
|
||||
end
|
||||
end
|
||||
redraw()
|
||||
|
||||
elseif _tHistory then
|
||||
-- Cycle history
|
||||
clear()
|
||||
if param1 == "up" then
|
||||
-- Up
|
||||
if nHistoryPos == nil then
|
||||
if #_tHistory > 0 then
|
||||
nHistoryPos = #_tHistory
|
||||
end
|
||||
elseif nHistoryPos > 1 then
|
||||
nHistoryPos = nHistoryPos - 1
|
||||
end
|
||||
elseif par2 == "up" then
|
||||
if #completions > 1 then
|
||||
dirty = true
|
||||
clearCompletion()
|
||||
if comp_id > 1 then
|
||||
comp_id = comp_id - 1
|
||||
else
|
||||
-- Down
|
||||
if nHistoryPos == #_tHistory then
|
||||
nHistoryPos = nil
|
||||
elseif nHistoryPos ~= nil then
|
||||
nHistoryPos = nHistoryPos + 1
|
||||
end
|
||||
comp_id = #completions
|
||||
end
|
||||
if nHistoryPos then
|
||||
sLine = _tHistory[nHistoryPos]
|
||||
nPos, nScroll = #sLine, 0
|
||||
|
||||
elseif hist_pos > 1 then
|
||||
cursor_pos = 0
|
||||
|
||||
history[hist_pos] = buffer
|
||||
hist_pos = hist_pos - 1
|
||||
|
||||
buffer = (" "):rep(#buffer)
|
||||
full_redraw(true)
|
||||
|
||||
buffer = history[hist_pos]
|
||||
dirty = true
|
||||
end
|
||||
|
||||
elseif par2 == "down" then
|
||||
if #completions > 1 then
|
||||
dirty = true
|
||||
clearCompletion()
|
||||
if comp_id < #completions then
|
||||
comp_id = comp_id + 1
|
||||
else
|
||||
sLine = ""
|
||||
nPos, nScroll = 0, 0
|
||||
comp_id = 1
|
||||
end
|
||||
uncomplete()
|
||||
redraw()
|
||||
|
||||
elseif hist_pos < #history then
|
||||
cursor_pos = 0
|
||||
|
||||
history[hist_pos] = buffer
|
||||
hist_pos = hist_pos + 1
|
||||
|
||||
buffer = (" "):rep(#buffer)
|
||||
full_redraw(true)
|
||||
|
||||
buffer = history[hist_pos]
|
||||
dirty = true
|
||||
end
|
||||
|
||||
elseif param1 == "back" then
|
||||
-- Backspace
|
||||
if nPos > 0 then
|
||||
clear()
|
||||
sLine = string.sub(sLine, 1, nPos - 1) .. string.sub(sLine, nPos + 1)
|
||||
nPos = nPos - 1
|
||||
if nScroll > 0 then nScroll = nScroll - 1 end
|
||||
recomplete()
|
||||
redraw()
|
||||
elseif par2 == "left" then
|
||||
if cursor_pos < #buffer then
|
||||
clearCompletion()
|
||||
cursor_pos = cursor_pos + 1
|
||||
end
|
||||
|
||||
elseif param1 == "home" then
|
||||
-- Home
|
||||
if nPos > 0 then
|
||||
clear()
|
||||
nPos = 0
|
||||
recomplete()
|
||||
redraw()
|
||||
elseif par2 == "right" then
|
||||
if cursor_pos > 0 then
|
||||
cursor_pos = cursor_pos - 1
|
||||
|
||||
elseif comp_id > 0 then
|
||||
dirty = true
|
||||
buffer = buffer .. completions[comp_id]
|
||||
end
|
||||
|
||||
elseif param1 == "delete" then
|
||||
-- Delete
|
||||
if nPos < #sLine then
|
||||
clear()
|
||||
sLine = string.sub(sLine, 1, nPos) .. string.sub(sLine, nPos + 2)
|
||||
recomplete()
|
||||
redraw()
|
||||
elseif par2 == "tab" then
|
||||
if comp_id > 0 then
|
||||
dirty = true
|
||||
buffer = buffer .. completions[comp_id]
|
||||
end
|
||||
|
||||
elseif param1 == "end" then
|
||||
-- End
|
||||
if nPos < #sLine then
|
||||
clear()
|
||||
nPos = #sLine
|
||||
recomplete()
|
||||
redraw()
|
||||
end
|
||||
elseif par2 == "home" then
|
||||
cursor_pos = #buffer
|
||||
|
||||
elseif param1 == "tab" then
|
||||
-- Tab (accept autocomplete)
|
||||
acceptCompletion()
|
||||
elseif par2 == "end" then
|
||||
cursor_pos = 0
|
||||
|
||||
elseif par2 == "enter" then
|
||||
clearCompletion()
|
||||
print()
|
||||
break
|
||||
end
|
||||
|
||||
elseif sEvent == "mouse_down" or sEvent == "mouse_move" and param == 1 then
|
||||
local _, cy = term.getPos()
|
||||
if param1 >= sx and param1 <= w and param2 == cy then
|
||||
-- Ensure we don't scroll beyond the current line
|
||||
nPos = math.min(math.max(nScroll + param1 - sx, 0), #sLine)
|
||||
redraw()
|
||||
end
|
||||
|
||||
elseif sEvent == "term_resize" then
|
||||
-- Terminal resized
|
||||
w = term.getSize()
|
||||
redraw()
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
local _, cy = term.getPos()
|
||||
term.setBlink(false)
|
||||
term.setPos(w + 1, cy)
|
||||
print()
|
||||
|
||||
return sLine
|
||||
return buffer
|
||||
end
|
||||
|
||||
return io
|
||||
io.stderr = {}
|
||||
|
||||
function io.stderr.write(text)
|
||||
local fg = term.getForeground()
|
||||
term.setForeground(0xff0000)
|
||||
io.write(text)
|
||||
term.setForeground(fg)
|
||||
end
|
||||
|
||||
function io.stderr.print(...)
|
||||
local fg = term.getForeground()
|
||||
term.setForeground(0xff0000)
|
||||
print(...)
|
||||
term.setForeground(fg)
|
||||
end
|
||||
|
||||
return io
|
||||
|
|
61
Capy64/Assets/Lua/lib/parallel.lua
Normal file
61
Capy64/Assets/Lua/lib/parallel.lua
Normal file
|
@ -0,0 +1,61 @@
|
|||
local expect = require("expect")
|
||||
|
||||
local parallel = {}
|
||||
|
||||
local function contains(array, value)
|
||||
for k, v in pairs(array) do
|
||||
if v == value then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function run(threads, exitOnAny)
|
||||
local alive = #threads
|
||||
local filters = {}
|
||||
local ev = {}
|
||||
while true do
|
||||
for i, thread in pairs(threads) do
|
||||
if not filters[i] or #filters[i] == 0 or contains(filters[i], ev[1]) or ev[1] == "interrupt" then
|
||||
local pars = table.pack(coroutine.resume(thread, table.unpack(ev)))
|
||||
if pars[1] then
|
||||
filters[i] = table.pack(table.unpack(pars, 2))
|
||||
else
|
||||
error(pars[2], 0)
|
||||
end
|
||||
end
|
||||
|
||||
if coroutine.status(thread) == "dead" then
|
||||
alive = alive - 1
|
||||
if exitOnAny or alive <= 0 then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ev = table.pack(coroutine.yield())
|
||||
end
|
||||
end
|
||||
|
||||
function parallel.waitForAll(...)
|
||||
local threads = {}
|
||||
for k, v in ipairs({ ... }) do
|
||||
expect(k, v, "function")
|
||||
table.insert(threads, coroutine.create(v))
|
||||
end
|
||||
|
||||
return run(threads, false)
|
||||
end
|
||||
|
||||
function parallel.waitForAny(...)
|
||||
local threads = {}
|
||||
for k, v in ipairs({ ... }) do
|
||||
expect(k, v, "function")
|
||||
table.insert(threads, coroutine.create(v))
|
||||
end
|
||||
|
||||
return run(threads, true)
|
||||
end
|
||||
|
||||
return parallel
|
|
@ -1,7 +1,7 @@
|
|||
local expect = require "expect"
|
||||
|
||||
local UTFString = {}
|
||||
local UTFString_mt = {__index = UTFString, __name = "UTFString"}
|
||||
local UTFString_mt = { __index = UTFString, __name = "UTFString" }
|
||||
|
||||
local function toUTF8(s)
|
||||
-- convert from ANSI if the string is invalid in UTF-8
|
||||
|
@ -18,10 +18,10 @@ local function toUTF8(s)
|
|||
end
|
||||
|
||||
function UTFString:new(s)
|
||||
return setmetatable({str = toUTF8(s)}, UTFString_mt)
|
||||
return setmetatable({ str = toUTF8(s) }, UTFString_mt)
|
||||
end
|
||||
|
||||
setmetatable(UTFString, {__call = UTFString.new})
|
||||
setmetatable(UTFString, { __call = UTFString.new })
|
||||
|
||||
local utf8_case_conv_utl, utf8_case_conv_ltu = nil, {} -- defined at bottom of file
|
||||
|
||||
|
@ -40,10 +40,12 @@ function UTFString:find(pattern, init, plain)
|
|||
expect(1, pattern, "string", "table")
|
||||
expect(2, init, "number", "nil")
|
||||
if type(pattern) == "table" then
|
||||
if getmetatable(pattern) ~= UTFString_mt then error("bad argument #1 (expected string or UTFString, got table)", 2) end
|
||||
if getmetatable(pattern) ~= UTFString_mt then error("bad argument #1 (expected string or UTFString, got table)",
|
||||
2) end
|
||||
pattern = pattern.str
|
||||
else pattern = toUTF8(pattern) end
|
||||
pattern = string.gsub(string.gsub(pattern, "(.)%.", function(s) if s == "%" then return "%." else return s .. utf8.charpattern end end), "^%.", utf8.charpattern)
|
||||
pattern = string.gsub(string.gsub(pattern, "(.)%.",
|
||||
function(s) if s == "%" then return "%." else return s .. utf8.charpattern end end), "^%.", utf8.charpattern)
|
||||
local s, e = string.find(self.str, pattern, init and utf8.offset(self.str, init), plain)
|
||||
if not s then return nil end
|
||||
return utf8.len(string.sub(self.str, 1, s - 1)) + 1, utf8.len(string.sub(self.str, 1, e - 1)) + 1
|
||||
|
@ -61,10 +63,12 @@ end
|
|||
function UTFString:gmatch(pattern)
|
||||
expect(1, pattern, "string", "table")
|
||||
if type(pattern) == "table" then
|
||||
if getmetatable(pattern) ~= UTFString_mt then error("bad argument #1 (expected string or UTFString, got table)", 2) end
|
||||
if getmetatable(pattern) ~= UTFString_mt then error("bad argument #1 (expected string or UTFString, got table)",
|
||||
2) end
|
||||
pattern = pattern.str
|
||||
else pattern = toUTF8(pattern) end
|
||||
pattern = string.gsub(string.gsub(pattern, "(.)%.", function(s) if s == "%" then return "%." else return s .. utf8.charpattern end end), "^%.", utf8.charpattern)
|
||||
pattern = string.gsub(string.gsub(pattern, "(.)%.",
|
||||
function(s) if s == "%" then return "%." else return s .. utf8.charpattern end end), "^%.", utf8.charpattern)
|
||||
local iter = string.gmatch(self.str, pattern)
|
||||
return function()
|
||||
local matches = table.pack(iter())
|
||||
|
@ -82,12 +86,14 @@ function UTFString:gsub(pattern, repl, n)
|
|||
expect(2, repl, "string", "table", "function")
|
||||
expect(3, n, "number", "nil")
|
||||
if type(pattern) == "table" then
|
||||
if getmetatable(pattern) ~= UTFString_mt then error("bad argument #1 (expected string or UTFString, got table)", 2) end
|
||||
if getmetatable(pattern) ~= UTFString_mt then error("bad argument #1 (expected string or UTFString, got table)",
|
||||
2) end
|
||||
pattern = pattern.str
|
||||
else pattern = toUTF8(pattern)end
|
||||
else pattern = toUTF8(pattern) end
|
||||
if type(repl) == "table" and getmetatable(repl) == UTFString_mt then repl = repl.str
|
||||
elseif type(repl) == "string" then repl = toUTF8(repl) end
|
||||
pattern = string.gsub(string.gsub(pattern, "(.)%.", function(s) if s == "%" then return "%." else return s .. utf8.charpattern end end), "^%.", utf8.charpattern)
|
||||
pattern = string.gsub(string.gsub(pattern, "(.)%.",
|
||||
function(s) if s == "%" then return "%." else return s .. utf8.charpattern end end), "^%.", utf8.charpattern)
|
||||
local s, total = string.gsub(self.str, pattern, repl, n)
|
||||
return UTFString(s), total
|
||||
end
|
||||
|
@ -111,10 +117,12 @@ function UTFString:match(pattern, init)
|
|||
expect(1, pattern, "string", "table")
|
||||
expect(2, init, "number", "nil")
|
||||
if type(pattern) == "table" then
|
||||
if getmetatable(pattern) ~= UTFString_mt then error("bad argument #1 (expected string or UTFString, got table)", 2) end
|
||||
if getmetatable(pattern) ~= UTFString_mt then error("bad argument #1 (expected string or UTFString, got table)",
|
||||
2) end
|
||||
pattern = pattern.str
|
||||
else pattern = toUTF8(pattern) end
|
||||
pattern = string.gsub(string.gsub(pattern, "(.)%.", function(s) if s == "%" then return "%." else return s .. utf8.charpattern end end), "^%.", utf8.charpattern)
|
||||
pattern = string.gsub(string.gsub(pattern, "(.)%.",
|
||||
function(s) if s == "%" then return "%." else return s .. utf8.charpattern end end), "^%.", utf8.charpattern)
|
||||
local matches = table.pack(string.match(self.str, pattern, init and utf8.offset(self.str, init)))
|
||||
for i = 1, matches.n do
|
||||
local tt = type(matches[i])
|
||||
|
@ -143,7 +151,7 @@ function UTFString:rep(n, sep)
|
|||
end
|
||||
|
||||
function UTFString:reverse()
|
||||
local codes = {n = 0}
|
||||
local codes = { n = 0 }
|
||||
for _, c in utf8.codes(self.str) do
|
||||
codes.n = codes.n + 1
|
||||
codes[codes.n] = c
|
||||
|
@ -191,8 +199,10 @@ function UTFString_mt.__concat(a, b)
|
|||
if type(a) == "string" then return UTFString(a .. b.str)
|
||||
elseif type(b) == "string" then return UTFString(a.str .. b)
|
||||
else
|
||||
if type(a) ~= "table" or getmetatable(a) ~= UTFString_mt then error("attempt to concatenate " .. type(a) .. " and UTFString", 2)
|
||||
elseif type(b) ~= "table" or getmetatable(b) ~= UTFString_mt then error("attempt to concatenate UTFString and " .. type(b), 2) end
|
||||
if type(a) ~= "table" or getmetatable(a) ~= UTFString_mt then error("attempt to concatenate " ..
|
||||
type(a) .. " and UTFString", 2)
|
||||
elseif type(b) ~= "table" or getmetatable(b) ~= UTFString_mt then error("attempt to concatenate UTFString and "
|
||||
.. type(b), 2) end
|
||||
return UTFString(a.str .. b.str)
|
||||
end
|
||||
end
|
||||
|
@ -208,8 +218,10 @@ function UTFString_mt.__lt(a, b)
|
|||
if type(a) == "string" then return a < b.str
|
||||
elseif type(b) == "string" then return a.str < b
|
||||
else
|
||||
if type(a) ~= "table" or getmetatable(a) ~= UTFString_mt then error("attempt to compare " .. type(a) .. " and UTFString", 2)
|
||||
elseif type(b) ~= "table" or getmetatable(b) ~= UTFString_mt then error("attempt to compare UTFString and " .. type(b), 2) end
|
||||
if type(a) ~= "table" or getmetatable(a) ~= UTFString_mt then error("attempt to compare " ..
|
||||
type(a) .. " and UTFString", 2)
|
||||
elseif type(b) ~= "table" or getmetatable(b) ~= UTFString_mt then error("attempt to compare UTFString and " ..
|
||||
type(b), 2) end
|
||||
return a.str < b.str
|
||||
end
|
||||
end
|
||||
|
@ -218,8 +230,10 @@ function UTFString_mt.__le(a, b)
|
|||
if type(a) == "string" then return a <= b.str
|
||||
elseif type(b) == "string" then return a.str <= b
|
||||
else
|
||||
if type(a) ~= "table" or getmetatable(a) ~= UTFString_mt then error("attempt to compare " .. type(a) .. " and UTFString", 2)
|
||||
elseif type(b) ~= "table" or getmetatable(b) ~= UTFString_mt then error("attempt to compare UTFString and " .. type(b), 2) end
|
||||
if type(a) ~= "table" or getmetatable(a) ~= UTFString_mt then error("attempt to compare " ..
|
||||
type(a) .. " and UTFString", 2)
|
||||
elseif type(b) ~= "table" or getmetatable(b) ~= UTFString_mt then error("attempt to compare UTFString and " ..
|
||||
type(b), 2) end
|
||||
return a.str <= b.str
|
||||
end
|
||||
end
|
||||
|
@ -245,7 +259,7 @@ utf8_case_conv_utl = {
|
|||
[0x0047] = 0x0067,
|
||||
[0x0048] = 0x0068,
|
||||
[0x0049] = 0x0069,
|
||||
|
||||
|
||||
[0x004A] = 0x006A,
|
||||
[0x004B] = 0x006B,
|
||||
[0x004C] = 0x006C,
|
||||
|
@ -294,7 +308,7 @@ utf8_case_conv_utl = {
|
|||
[0x00DC] = 0x00FC,
|
||||
[0x00DD] = 0x00FD,
|
||||
[0x00DE] = 0x00FE,
|
||||
[0x00DF] = {0x0073, 0x0073},
|
||||
[0x00DF] = { 0x0073, 0x0073 },
|
||||
[0x0100] = 0x0101,
|
||||
[0x0102] = 0x0103,
|
||||
[0x0104] = 0x0105,
|
||||
|
@ -319,8 +333,8 @@ utf8_case_conv_utl = {
|
|||
[0x012A] = 0x012B,
|
||||
[0x012C] = 0x012D,
|
||||
[0x012E] = 0x012F,
|
||||
[0x0130] = {0x0069, 0x0307},
|
||||
|
||||
[0x0130] = { 0x0069, 0x0307 },
|
||||
|
||||
[0x0132] = 0x0133,
|
||||
[0x0134] = 0x0135,
|
||||
[0x0136] = 0x0137,
|
||||
|
@ -332,7 +346,7 @@ utf8_case_conv_utl = {
|
|||
[0x0143] = 0x0144,
|
||||
[0x0145] = 0x0146,
|
||||
[0x0147] = 0x0148,
|
||||
[0x0149] = {0x02BC, 0x006E},
|
||||
[0x0149] = { 0x02BC, 0x006E },
|
||||
[0x014A] = 0x014B,
|
||||
[0x014C] = 0x014D,
|
||||
[0x014E] = 0x014F,
|
||||
|
@ -420,7 +434,7 @@ utf8_case_conv_utl = {
|
|||
[0x01EA] = 0x01EB,
|
||||
[0x01EC] = 0x01ED,
|
||||
[0x01EE] = 0x01EF,
|
||||
[0x01F0] = {0x006A, 0x030C},
|
||||
[0x01F0] = { 0x006A, 0x030C },
|
||||
[0x01F1] = 0x01F3,
|
||||
[0x01F2] = 0x01F3,
|
||||
[0x01F4] = 0x01F5,
|
||||
|
@ -481,7 +495,7 @@ utf8_case_conv_utl = {
|
|||
[0x038C] = 0x03CC,
|
||||
[0x038E] = 0x03CD,
|
||||
[0x038F] = 0x03CE,
|
||||
[0x0390] = {0x03B9, 0x0308, 0x0301},
|
||||
[0x0390] = { 0x03B9, 0x0308, 0x0301 },
|
||||
[0x0391] = 0x03B1,
|
||||
[0x0392] = 0x03B2,
|
||||
[0x0393] = 0x03B3,
|
||||
|
@ -508,7 +522,7 @@ utf8_case_conv_utl = {
|
|||
[0x03A9] = 0x03C9,
|
||||
[0x03AA] = 0x03CA,
|
||||
[0x03AB] = 0x03CB,
|
||||
[0x03B0] = {0x03C5, 0x0308, 0x0301},
|
||||
[0x03B0] = { 0x03C5, 0x0308, 0x0301 },
|
||||
[0x03C2] = 0x03C3,
|
||||
[0x03CF] = 0x03D7,
|
||||
[0x03D0] = 0x03B2,
|
||||
|
@ -723,7 +737,7 @@ utf8_case_conv_utl = {
|
|||
[0x0554] = 0x0584,
|
||||
[0x0555] = 0x0585,
|
||||
[0x0556] = 0x0586,
|
||||
[0x0587] = {0x0565, 0x0582},
|
||||
[0x0587] = { 0x0565, 0x0582 },
|
||||
[0x10A0] = 0x2D00,
|
||||
[0x10A1] = 0x2D01,
|
||||
[0x10A2] = 0x2D02,
|
||||
|
@ -900,13 +914,13 @@ utf8_case_conv_utl = {
|
|||
[0x1E90] = 0x1E91,
|
||||
[0x1E92] = 0x1E93,
|
||||
[0x1E94] = 0x1E95,
|
||||
[0x1E96] = {0x0068, 0x0331},
|
||||
[0x1E97] = {0x0074, 0x0308},
|
||||
[0x1E98] = {0x0077, 0x030A},
|
||||
[0x1E99] = {0x0079, 0x030A},
|
||||
[0x1E9A] = {0x0061, 0x02BE},
|
||||
[0x1E96] = { 0x0068, 0x0331 },
|
||||
[0x1E97] = { 0x0074, 0x0308 },
|
||||
[0x1E98] = { 0x0077, 0x030A },
|
||||
[0x1E99] = { 0x0079, 0x030A },
|
||||
[0x1E9A] = { 0x0061, 0x02BE },
|
||||
[0x1E9B] = 0x1E61,
|
||||
[0x1E9E] = {0x0073, 0x0073},
|
||||
[0x1E9E] = { 0x0073, 0x0073 },
|
||||
--1E9E; S;0x00DF, ; # LATIN CAPITAL LETTER SHARP S
|
||||
[0x1EA0] = 0x1EA1,
|
||||
[0x1EA2] = 0x1EA3,
|
||||
|
@ -992,10 +1006,10 @@ utf8_case_conv_utl = {
|
|||
[0x1F4B] = 0x1F43,
|
||||
[0x1F4C] = 0x1F44,
|
||||
[0x1F4D] = 0x1F45,
|
||||
[0x1F50] = {0x03C5, 0x0313},
|
||||
[0x1F52] = {0x03C5, 0x0313, 0x0300},
|
||||
[0x1F54] = {0x03C5, 0x0313, 0x0301},
|
||||
[0x1F56] = {0x03C5, 0x0313, 0x0342},
|
||||
[0x1F50] = { 0x03C5, 0x0313 },
|
||||
[0x1F52] = { 0x03C5, 0x0313, 0x0300 },
|
||||
[0x1F54] = { 0x03C5, 0x0313, 0x0301 },
|
||||
[0x1F56] = { 0x03C5, 0x0313, 0x0342 },
|
||||
[0x1F59] = 0x1F51,
|
||||
[0x1F5B] = 0x1F53,
|
||||
[0x1F5D] = 0x1F55,
|
||||
|
@ -1008,129 +1022,129 @@ utf8_case_conv_utl = {
|
|||
[0x1F6D] = 0x1F65,
|
||||
[0x1F6E] = 0x1F66,
|
||||
[0x1F6F] = 0x1F67,
|
||||
[0x1F80] = {0x1F00, 0x03B9},
|
||||
[0x1F81] = {0x1F01, 0x03B9},
|
||||
[0x1F82] = {0x1F02, 0x03B9},
|
||||
[0x1F83] = {0x1F03, 0x03B9},
|
||||
[0x1F84] = {0x1F04, 0x03B9},
|
||||
[0x1F85] = {0x1F05, 0x03B9},
|
||||
[0x1F86] = {0x1F06, 0x03B9},
|
||||
[0x1F87] = {0x1F07, 0x03B9},
|
||||
[0x1F88] = {0x1F00, 0x03B9},
|
||||
[0x1F80] = { 0x1F00, 0x03B9 },
|
||||
[0x1F81] = { 0x1F01, 0x03B9 },
|
||||
[0x1F82] = { 0x1F02, 0x03B9 },
|
||||
[0x1F83] = { 0x1F03, 0x03B9 },
|
||||
[0x1F84] = { 0x1F04, 0x03B9 },
|
||||
[0x1F85] = { 0x1F05, 0x03B9 },
|
||||
[0x1F86] = { 0x1F06, 0x03B9 },
|
||||
[0x1F87] = { 0x1F07, 0x03B9 },
|
||||
[0x1F88] = { 0x1F00, 0x03B9 },
|
||||
--1F88; S;0x1F80, ; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
|
||||
[0x1F89] = {0x1F01, 0x03B9},
|
||||
[0x1F89] = { 0x1F01, 0x03B9 },
|
||||
--1F89; S;0x1F81, ; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
|
||||
[0x1F8A] = {0x1F02, 0x03B9},
|
||||
[0x1F8A] = { 0x1F02, 0x03B9 },
|
||||
--1F8A; S;0x1F82, ; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
|
||||
[0x1F8B] = {0x1F03, 0x03B9},
|
||||
[0x1F8B] = { 0x1F03, 0x03B9 },
|
||||
--1F8B; S;0x1F83, ; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
|
||||
[0x1F8C] = {0x1F04, 0x03B9},
|
||||
[0x1F8C] = { 0x1F04, 0x03B9 },
|
||||
--1F8C; S;0x1F84, ; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
|
||||
[0x1F8D] = {0x1F05, 0x03B9},
|
||||
[0x1F8D] = { 0x1F05, 0x03B9 },
|
||||
--1F8D; S;0x1F85, ; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
|
||||
[0x1F8E] = {0x1F06, 0x03B9},
|
||||
[0x1F8E] = { 0x1F06, 0x03B9 },
|
||||
--1F8E; S;0x1F86, ; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
|
||||
[0x1F8F] = {0x1F07, 0x03B9},
|
||||
[0x1F8F] = { 0x1F07, 0x03B9 },
|
||||
--1F8F; S;0x1F87, ; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
|
||||
[0x1F90] = {0x1F20, 0x03B9},
|
||||
[0x1F91] = {0x1F21, 0x03B9},
|
||||
[0x1F92] = {0x1F22, 0x03B9},
|
||||
[0x1F93] = {0x1F23, 0x03B9},
|
||||
[0x1F94] = {0x1F24, 0x03B9},
|
||||
[0x1F95] = {0x1F25, 0x03B9},
|
||||
[0x1F96] = {0x1F26, 0x03B9},
|
||||
[0x1F97] = {0x1F27, 0x03B9},
|
||||
[0x1F98] = {0x1F20, 0x03B9},
|
||||
[0x1F90] = { 0x1F20, 0x03B9 },
|
||||
[0x1F91] = { 0x1F21, 0x03B9 },
|
||||
[0x1F92] = { 0x1F22, 0x03B9 },
|
||||
[0x1F93] = { 0x1F23, 0x03B9 },
|
||||
[0x1F94] = { 0x1F24, 0x03B9 },
|
||||
[0x1F95] = { 0x1F25, 0x03B9 },
|
||||
[0x1F96] = { 0x1F26, 0x03B9 },
|
||||
[0x1F97] = { 0x1F27, 0x03B9 },
|
||||
[0x1F98] = { 0x1F20, 0x03B9 },
|
||||
--1F98; S;0x1F90, ; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
|
||||
[0x1F99] = {0x1F21, 0x03B9},
|
||||
[0x1F99] = { 0x1F21, 0x03B9 },
|
||||
--1F99; S;0x1F91, ; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
|
||||
[0x1F9A] = {0x1F22, 0x03B9},
|
||||
[0x1F9A] = { 0x1F22, 0x03B9 },
|
||||
--1F9A; S;0x1F92, ; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
|
||||
[0x1F9B] = {0x1F23, 0x03B9},
|
||||
[0x1F9B] = { 0x1F23, 0x03B9 },
|
||||
--1F9B; S;0x1F93, ; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
|
||||
[0x1F9C] = {0x1F24, 0x03B9},
|
||||
[0x1F9C] = { 0x1F24, 0x03B9 },
|
||||
--1F9C; S;0x1F94, ; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
|
||||
[0x1F9D] = {0x1F25, 0x03B9},
|
||||
[0x1F9D] = { 0x1F25, 0x03B9 },
|
||||
--1F9D; S;0x1F95, ; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
|
||||
[0x1F9E] = {0x1F26, 0x03B9},
|
||||
[0x1F9E] = { 0x1F26, 0x03B9 },
|
||||
--1F9E; S;0x1F96, ; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
|
||||
[0x1F9F] = {0x1F27, 0x03B9},
|
||||
[0x1F9F] = { 0x1F27, 0x03B9 },
|
||||
--1F9F; S;0x1F97, ; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
|
||||
[0x1FA0] = {0x1F60, 0x03B9},
|
||||
[0x1FA1] = {0x1F61, 0x03B9},
|
||||
[0x1FA2] = {0x1F62, 0x03B9},
|
||||
[0x1FA3] = {0x1F63, 0x03B9},
|
||||
[0x1FA4] = {0x1F64, 0x03B9},
|
||||
[0x1FA5] = {0x1F65, 0x03B9},
|
||||
[0x1FA6] = {0x1F66, 0x03B9},
|
||||
[0x1FA7] = {0x1F67, 0x03B9},
|
||||
[0x1FA8] = {0x1F60, 0x03B9},
|
||||
[0x1FA0] = { 0x1F60, 0x03B9 },
|
||||
[0x1FA1] = { 0x1F61, 0x03B9 },
|
||||
[0x1FA2] = { 0x1F62, 0x03B9 },
|
||||
[0x1FA3] = { 0x1F63, 0x03B9 },
|
||||
[0x1FA4] = { 0x1F64, 0x03B9 },
|
||||
[0x1FA5] = { 0x1F65, 0x03B9 },
|
||||
[0x1FA6] = { 0x1F66, 0x03B9 },
|
||||
[0x1FA7] = { 0x1F67, 0x03B9 },
|
||||
[0x1FA8] = { 0x1F60, 0x03B9 },
|
||||
--1FA8; S;0x1FA0, ; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
|
||||
[0x1FA9] = {0x1F61, 0x03B9},
|
||||
[0x1FA9] = { 0x1F61, 0x03B9 },
|
||||
--1FA9; S;0x1FA1, ; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
|
||||
[0x1FAA] = {0x1F62, 0x03B9},
|
||||
[0x1FAA] = { 0x1F62, 0x03B9 },
|
||||
--1FAA; S;0x1FA2, ; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
|
||||
[0x1FAB] = {0x1F63, 0x03B9},
|
||||
[0x1FAB] = { 0x1F63, 0x03B9 },
|
||||
--1FAB; S;0x1FA3, ; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
|
||||
[0x1FAC] = {0x1F64, 0x03B9},
|
||||
[0x1FAC] = { 0x1F64, 0x03B9 },
|
||||
--1FAC; S;0x1FA4, ; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
|
||||
[0x1FAD] = {0x1F65, 0x03B9},
|
||||
[0x1FAD] = { 0x1F65, 0x03B9 },
|
||||
--1FAD; S;0x1FA5, ; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
|
||||
[0x1FAE] = {0x1F66, 0x03B9},
|
||||
[0x1FAE] = { 0x1F66, 0x03B9 },
|
||||
--1FAE; S;0x1FA6, ; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
|
||||
[0x1FAF] = {0x1F67, 0x03B9},
|
||||
[0x1FAF] = { 0x1F67, 0x03B9 },
|
||||
--1FAF; S;0x1FA7, ; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
|
||||
[0x1FB2] = {0x1F70, 0x03B9},
|
||||
[0x1FB3] = {0x03B1, 0x03B9},
|
||||
[0x1FB4] = {0x03AC, 0x03B9},
|
||||
[0x1FB6] = {0x03B1, 0x0342},
|
||||
[0x1FB7] = {0x03B1, 0x0342, 0x03B9},
|
||||
[0x1FB2] = { 0x1F70, 0x03B9 },
|
||||
[0x1FB3] = { 0x03B1, 0x03B9 },
|
||||
[0x1FB4] = { 0x03AC, 0x03B9 },
|
||||
[0x1FB6] = { 0x03B1, 0x0342 },
|
||||
[0x1FB7] = { 0x03B1, 0x0342, 0x03B9 },
|
||||
[0x1FB8] = 0x1FB0,
|
||||
[0x1FB9] = 0x1FB1,
|
||||
[0x1FBA] = 0x1F70,
|
||||
[0x1FBB] = 0x1F71,
|
||||
[0x1FBC] = {0x03B1, 0x03B9},
|
||||
[0x1FBC] = { 0x03B1, 0x03B9 },
|
||||
--1FBC; S;0x1FB3, ; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
|
||||
[0x1FBE] = 0x03B9,
|
||||
[0x1FC2] = {0x1F74, 0x03B9},
|
||||
[0x1FC3] = {0x03B7, 0x03B9},
|
||||
[0x1FC4] = {0x03AE, 0x03B9},
|
||||
[0x1FC6] = {0x03B7, 0x0342},
|
||||
[0x1FC7] = {0x03B7, 0x0342, 0x03B9},
|
||||
[0x1FC2] = { 0x1F74, 0x03B9 },
|
||||
[0x1FC3] = { 0x03B7, 0x03B9 },
|
||||
[0x1FC4] = { 0x03AE, 0x03B9 },
|
||||
[0x1FC6] = { 0x03B7, 0x0342 },
|
||||
[0x1FC7] = { 0x03B7, 0x0342, 0x03B9 },
|
||||
[0x1FC8] = 0x1F72,
|
||||
[0x1FC9] = 0x1F73,
|
||||
[0x1FCA] = 0x1F74,
|
||||
[0x1FCB] = 0x1F75,
|
||||
[0x1FCC] = {0x03B7, 0x03B9},
|
||||
[0x1FCC] = { 0x03B7, 0x03B9 },
|
||||
--1FCC; S;0x1FC3, ; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
|
||||
[0x1FD2] = {0x03B9, 0x0308, 0x0300},
|
||||
[0x1FD3] = {0x03B9, 0x0308, 0x0301},
|
||||
[0x1FD6] = {0x03B9, 0x0342},
|
||||
[0x1FD7] = {0x03B9, 0x0308, 0x0342},
|
||||
[0x1FD2] = { 0x03B9, 0x0308, 0x0300 },
|
||||
[0x1FD3] = { 0x03B9, 0x0308, 0x0301 },
|
||||
[0x1FD6] = { 0x03B9, 0x0342 },
|
||||
[0x1FD7] = { 0x03B9, 0x0308, 0x0342 },
|
||||
[0x1FD8] = 0x1FD0,
|
||||
[0x1FD9] = 0x1FD1,
|
||||
[0x1FDA] = 0x1F76,
|
||||
[0x1FDB] = 0x1F77,
|
||||
[0x1FE2] = {0x03C5, 0x0308, 0x0300},
|
||||
[0x1FE3] = {0x03C5, 0x0308, 0x0301},
|
||||
[0x1FE4] = {0x03C1, 0x0313},
|
||||
[0x1FE6] = {0x03C5, 0x0342},
|
||||
[0x1FE7] = {0x03C5, 0x0308, 0x0342},
|
||||
[0x1FE2] = { 0x03C5, 0x0308, 0x0300 },
|
||||
[0x1FE3] = { 0x03C5, 0x0308, 0x0301 },
|
||||
[0x1FE4] = { 0x03C1, 0x0313 },
|
||||
[0x1FE6] = { 0x03C5, 0x0342 },
|
||||
[0x1FE7] = { 0x03C5, 0x0308, 0x0342 },
|
||||
[0x1FE8] = 0x1FE0,
|
||||
[0x1FE9] = 0x1FE1,
|
||||
[0x1FEA] = 0x1F7A,
|
||||
[0x1FEB] = 0x1F7B,
|
||||
[0x1FEC] = 0x1FE5,
|
||||
[0x1FF2] = {0x1F7C, 0x03B9},
|
||||
[0x1FF3] = {0x03C9, 0x03B9},
|
||||
[0x1FF4] = {0x03CE, 0x03B9},
|
||||
[0x1FF6] = {0x03C9, 0x0342},
|
||||
[0x1FF7] = {0x03C9, 0x0342, 0x03B9},
|
||||
[0x1FF2] = { 0x1F7C, 0x03B9 },
|
||||
[0x1FF3] = { 0x03C9, 0x03B9 },
|
||||
[0x1FF4] = { 0x03CE, 0x03B9 },
|
||||
[0x1FF6] = { 0x03C9, 0x0342 },
|
||||
[0x1FF7] = { 0x03C9, 0x0342, 0x03B9 },
|
||||
[0x1FF8] = 0x1F78,
|
||||
[0x1FF9] = 0x1F79,
|
||||
[0x1FFA] = 0x1F7C,
|
||||
[0x1FFB] = 0x1F7D,
|
||||
[0x1FFC] = {0x03C9, 0x03B9},
|
||||
[0x1FFC] = { 0x03C9, 0x03B9 },
|
||||
--1FFC; S;0x1FF3, ; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
|
||||
[0x2126] = 0x03C9,
|
||||
[0x212A] = 0x006B,
|
||||
|
@ -1493,18 +1507,18 @@ utf8_case_conv_utl = {
|
|||
[0xABBD] = 0x13ED,
|
||||
[0xABBE] = 0x13EE,
|
||||
[0xABBF] = 0x13EF,
|
||||
[0xFB00] = {0x0066, 0x0066},
|
||||
[0xFB01] = {0x0066, 0x0069},
|
||||
[0xFB02] = {0x0066, 0x006C},
|
||||
[0xFB03] = {0x0066, 0x0066, 0x0069},
|
||||
[0xFB04] = {0x0066, 0x0066, 0x006C},
|
||||
[0xFB05] = {0x0073, 0x0074},
|
||||
[0xFB06] = {0x0073, 0x0074},
|
||||
[0xFB13] = {0x0574, 0x0576},
|
||||
[0xFB14] = {0x0574, 0x0565},
|
||||
[0xFB15] = {0x0574, 0x056B},
|
||||
[0xFB16] = {0x057E, 0x0576},
|
||||
[0xFB17] = {0x0574, 0x056D},
|
||||
[0xFB00] = { 0x0066, 0x0066 },
|
||||
[0xFB01] = { 0x0066, 0x0069 },
|
||||
[0xFB02] = { 0x0066, 0x006C },
|
||||
[0xFB03] = { 0x0066, 0x0066, 0x0069 },
|
||||
[0xFB04] = { 0x0066, 0x0066, 0x006C },
|
||||
[0xFB05] = { 0x0073, 0x0074 },
|
||||
[0xFB06] = { 0x0073, 0x0074 },
|
||||
[0xFB13] = { 0x0574, 0x0576 },
|
||||
[0xFB14] = { 0x0574, 0x0565 },
|
||||
[0xFB15] = { 0x0574, 0x056B },
|
||||
[0xFB16] = { 0x057E, 0x0576 },
|
||||
[0xFB17] = { 0x0574, 0x056D },
|
||||
[0xFF21] = 0xFF41,
|
||||
[0xFF22] = 0xFF42,
|
||||
[0xFF23] = 0xFF43,
|
||||
|
@ -1757,6 +1771,6 @@ utf8_case_conv_utl = {
|
|||
[0x1E920] = 0x1E942,
|
||||
[0x1E921] = 0x1E943,
|
||||
}
|
||||
for k,v in pairs(utf8_case_conv_utl) do utf8_case_conv_ltu[v] = k end
|
||||
for k, v in pairs(utf8_case_conv_utl) do utf8_case_conv_ltu[v] = k end
|
||||
|
||||
return UTFString
|
||||
return UTFString
|
||||
|
|
Loading…
Reference in a new issue