Upload System Image
This commit is contained in:
648
Program_Files/Common_Files/oop.lua
Normal file
648
Program_Files/Common_Files/oop.lua
Normal file
@@ -0,0 +1,648 @@
|
||||
------------------------------------------------ LevelOOPer Library 2.2.6 ------------------------------------------------
|
||||
function _G.pairs(t)
|
||||
local mt = getmetatable(t)
|
||||
if mt and type(mt.__pairs) == "function" then
|
||||
return mt.__pairs(t)
|
||||
else
|
||||
return next, t, nil
|
||||
end
|
||||
end
|
||||
|
||||
local function fread(file)
|
||||
local f = fs.open(file,"r")
|
||||
local txt = f.readAll()
|
||||
f.close()
|
||||
return txt
|
||||
end
|
||||
|
||||
local env = _ENV
|
||||
local oop = {}
|
||||
|
||||
local classCache = {}
|
||||
local privCache = {}
|
||||
local publicCache = {}
|
||||
local objectCache = {}
|
||||
|
||||
local dir = fs.getDir(({...})[1] or shell.getRunningProgram())
|
||||
|
||||
local function typeRestriction(index, sType, value)
|
||||
if not oop.isType(value, sType) then
|
||||
return false, "cannot convert "..sType.." '"..index.."' to '"..oop.type(value, true).."'"
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function getNumberType(number)
|
||||
if number%1 == 0 then
|
||||
return "int"
|
||||
else
|
||||
return "double"
|
||||
end
|
||||
end
|
||||
|
||||
oop.setEnv = function(newEnv)
|
||||
env = newEnv
|
||||
end
|
||||
|
||||
oop.setDir = function(newDir)
|
||||
oop.expect(1, newDir, "string")
|
||||
dir = newDir
|
||||
end
|
||||
|
||||
oop.getDir = function()
|
||||
return dir
|
||||
end
|
||||
|
||||
local default = {
|
||||
int = 0,
|
||||
double = 0,
|
||||
number = 0,
|
||||
string = "",
|
||||
["function"] = function() end,
|
||||
table = {},
|
||||
boolean = false,
|
||||
}
|
||||
|
||||
local varTypes = {
|
||||
int = "int",
|
||||
double = "double",
|
||||
num = "number",
|
||||
str = "string",
|
||||
func = "function",
|
||||
tbl = "table",
|
||||
bool = "boolean",
|
||||
}
|
||||
|
||||
local newVar = {
|
||||
var = function(name)
|
||||
local tbl = {name=name}
|
||||
setmetatable(tbl, {
|
||||
__call = function(self, value)
|
||||
self.value = value
|
||||
return self
|
||||
end
|
||||
})
|
||||
return tbl
|
||||
end,
|
||||
obj = function(class)
|
||||
oop.expect(1, class, "class")
|
||||
local var = {type=classCache[class].name}
|
||||
setmetatable(var, {
|
||||
__call = function(self, name)
|
||||
self.name = name
|
||||
setmetatable(var, {
|
||||
__call = function(self, value)
|
||||
local ok,err = typeRestriction(name, var.type, value)
|
||||
if not ok then
|
||||
error(err, 2)
|
||||
else
|
||||
self.value = value
|
||||
return self
|
||||
end
|
||||
end,
|
||||
})
|
||||
return self
|
||||
end,
|
||||
})
|
||||
return var
|
||||
end,
|
||||
}
|
||||
|
||||
local const = function(name)
|
||||
if type(name) == "function" then
|
||||
return function(realname)
|
||||
local var = name(realname)
|
||||
var.const = true
|
||||
return var
|
||||
end
|
||||
elseif type(name) == "string" then
|
||||
local var = {name=name, const=true}
|
||||
setmetatable(var, {
|
||||
__call = function(self, value)
|
||||
self.value = value
|
||||
return self
|
||||
end,
|
||||
})
|
||||
return var
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(varTypes) do
|
||||
newVar[k] = function(name)
|
||||
local tbl = {name=name, type=varTypes[k]}
|
||||
setmetatable(tbl, {
|
||||
__call = function(self, value)
|
||||
local stat,err = typeRestriction(name, tbl.type, value)
|
||||
if not stat then
|
||||
error(err, 2)
|
||||
else
|
||||
self.value = value
|
||||
return self
|
||||
end
|
||||
end,
|
||||
})
|
||||
return tbl
|
||||
end
|
||||
end
|
||||
|
||||
oop.injectEnv = function(env)
|
||||
env.oop = oop
|
||||
env.class = oop.class
|
||||
env.const = const
|
||||
env.import = oop.import
|
||||
env.type = oop.type
|
||||
env.getPublicObject = oop.getPublicObject
|
||||
for k,v in pairs(newVar) do
|
||||
env[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
local metamethods = {
|
||||
["__add"] = true,
|
||||
["__sub"] = true,
|
||||
["__mul"] = true,
|
||||
["__div"] = true,
|
||||
["__mod"] = true,
|
||||
["__pow"] = true,
|
||||
["__unm"] = true,
|
||||
["__concat"] = true,
|
||||
["__len"] = true,
|
||||
["__eq"] = true,
|
||||
["__lt"] = true,
|
||||
["__le"] = true,
|
||||
["__index"] = true,
|
||||
["__newindex"] = true,
|
||||
["__call"] = true,
|
||||
["__tostring"] = true,
|
||||
["__metatable"] = true,
|
||||
["__pairs"] = true,
|
||||
["__ipairs"] = true
|
||||
}
|
||||
|
||||
local function sanitizeArgs(...)
|
||||
local args = table.pack(...)
|
||||
for k,v in pairs(args) do
|
||||
if publicCache[v] then
|
||||
args[k] = publicCache[v]
|
||||
end
|
||||
end
|
||||
return table.unpack(args, nil, args.n)
|
||||
end
|
||||
|
||||
local function instantiate(orig)
|
||||
local function deepCopy(o, seen)
|
||||
seen = seen or {}
|
||||
if seen[o] then
|
||||
return seen[o]
|
||||
end
|
||||
local copy
|
||||
if type(o) == 'table' then
|
||||
copy = {}
|
||||
seen[o] = copy
|
||||
for k,v in pairs(o) do
|
||||
copy[deepCopy(k, seen)] = deepCopy(v, seen)
|
||||
end
|
||||
setmetatable(copy, deepCopy(getmetatable(o), seen))
|
||||
else
|
||||
copy = o
|
||||
end
|
||||
return copy
|
||||
end
|
||||
return deepCopy(orig)
|
||||
end
|
||||
|
||||
local function makeClass(name, classTbl, inherit)
|
||||
local class = {
|
||||
static = {
|
||||
},
|
||||
private = {
|
||||
},
|
||||
public = {
|
||||
},
|
||||
properties = {
|
||||
static = {
|
||||
},
|
||||
private = {
|
||||
},
|
||||
public = {
|
||||
},
|
||||
types = {
|
||||
},
|
||||
consts = {
|
||||
},
|
||||
},
|
||||
metatable = {
|
||||
public = {
|
||||
},
|
||||
private = {
|
||||
},
|
||||
},
|
||||
name = name,
|
||||
}
|
||||
|
||||
class.metatable.static = {
|
||||
__index = class.static,
|
||||
__newindex = function(tbl, k, v)
|
||||
if class.properties.static[k] then
|
||||
if class.properties.consts[k] then
|
||||
error("cannot modify const '"..tostring(k).."'", 2)
|
||||
elseif class.properties.types[k] then
|
||||
local stat,err = typeRestriction(k, class.properties.types[k], v)
|
||||
if not stat then
|
||||
error(err, 2)
|
||||
else
|
||||
class.static[k] = v
|
||||
end
|
||||
end
|
||||
elseif class.properties.private[k] then
|
||||
error("cannot modify private property '"..tostring(k).."' outside of class", 2)
|
||||
elseif class.properties.public[k] then
|
||||
error("cannot modify public property '"..tostring(k).."' outside of object", 2)
|
||||
end
|
||||
end,
|
||||
__call = function(self, ...)
|
||||
local privObj = {}
|
||||
local obj = {}
|
||||
|
||||
privCache[obj] = privObj
|
||||
publicCache[privObj] = obj
|
||||
|
||||
local properties = {}
|
||||
local privProperties = {}
|
||||
|
||||
setmetatable(properties, {__index=class.public})
|
||||
setmetatable(privProperties, {
|
||||
__index=function(t, k)
|
||||
return properties[k] or class.private[k]
|
||||
end
|
||||
})
|
||||
|
||||
local mt = {
|
||||
__index = function(t, k)
|
||||
local p = properties
|
||||
if t == privObj then
|
||||
p = privProperties
|
||||
end
|
||||
local v = p[k]
|
||||
if type(v) == "function" then
|
||||
local tEnv = {self=privObj}
|
||||
oop.injectEnv(tEnv)
|
||||
setmetatable(tEnv, {__index=env})
|
||||
setfenv(v, tEnv)
|
||||
end
|
||||
return v
|
||||
end
|
||||
}
|
||||
|
||||
local inConstructor = false
|
||||
|
||||
mt.__pairs = function(tbl)
|
||||
local loopThroughTables = {properties, class.public, class.static}
|
||||
if tbl == privObj then
|
||||
table.insert(loopThroughTables, 2, class.private)
|
||||
end
|
||||
local cls = class
|
||||
while cls.parent do -- this WONT WORK
|
||||
cls = cls.parent
|
||||
if tbl == privObj then
|
||||
table.insert(loopThroughTables, cls.private)
|
||||
end
|
||||
table.insert(loopThroughTables, cls.public)
|
||||
table.insert(loopThroughTables, cls.static)
|
||||
end
|
||||
|
||||
local currentIndex = 1
|
||||
|
||||
local had = {}
|
||||
|
||||
local function customIterator(_, prevKey)
|
||||
local key, value
|
||||
|
||||
while currentIndex <= #loopThroughTables do
|
||||
key, value = next(loopThroughTables[currentIndex], prevKey)
|
||||
while key ~= nil and had[key] do -- skip keys that were already found
|
||||
key, value = next(loopThroughTables[currentIndex], key)
|
||||
end
|
||||
|
||||
if key ~= nil then
|
||||
had[key] = true
|
||||
return key, tbl[key]
|
||||
else
|
||||
prevKey = nil
|
||||
currentIndex = currentIndex + 1
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
return customIterator, tbl, nil
|
||||
end
|
||||
|
||||
mt.__newindex = function(tbl, k, v)
|
||||
if class.properties.consts[k] and not inConstructor then
|
||||
error("cannot modify const '"..tostring(k).."'", 2)
|
||||
end
|
||||
if tbl ~= privObj and class.properties.private[k] then
|
||||
error("cannot modify private property '"..tostring(k).."' outside of class", 2)
|
||||
end
|
||||
if class.properties.types[k] then
|
||||
local stat,err = typeRestriction(k, class.properties.types[k], v)
|
||||
if not stat then
|
||||
error(err, 2)
|
||||
end
|
||||
end
|
||||
if class.properties.static[k] then
|
||||
-- change in whole class
|
||||
class.static[k] = v
|
||||
elseif class.properties.private[k] then
|
||||
privProperties[k] = v
|
||||
else
|
||||
properties[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
local mt2 = {}
|
||||
|
||||
for k,v in pairs(mt) do
|
||||
mt2[k] = v
|
||||
end
|
||||
|
||||
for k,v in pairs(class.metatable.public) do
|
||||
mt[k] = function(...)
|
||||
local tEnv = {self=privObj}
|
||||
oop.injectEnv(tEnv)
|
||||
setmetatable(tEnv, {__index=env})
|
||||
setfenv(v, tEnv)
|
||||
return v(sanitizeArgs(...))
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(class.metatable.private) do
|
||||
mt2[k] = function(...)
|
||||
local tEnv = {self=privObj}
|
||||
oop.injectEnv(tEnv)
|
||||
setmetatable(tEnv, {__index=env})
|
||||
setfenv(v, tEnv)
|
||||
return v(sanitizeArgs(...))
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(obj, mt)
|
||||
setmetatable(privObj, mt2)
|
||||
|
||||
local constructors = {class.constructor}
|
||||
local cls = class
|
||||
while cls.parent do
|
||||
cls = cls.parent
|
||||
if cls.constructor then
|
||||
table.insert(constructors, 1, cls.constructor)
|
||||
end
|
||||
end
|
||||
for t=1,#constructors do
|
||||
inConstructor = true
|
||||
local tEnv = {self=privCache[obj] or obj}
|
||||
oop.injectEnv(tEnv)
|
||||
setmetatable(tEnv, {__index=env})
|
||||
setfenv(constructors[t], tEnv)
|
||||
local status,tObj = pcall(constructors[t],sanitizeArgs(...))
|
||||
if not status then
|
||||
error(tObj, 2)
|
||||
end
|
||||
if tObj == false then
|
||||
return false
|
||||
elseif tObj then
|
||||
obj = publicCache[tObj] or tObj
|
||||
end
|
||||
inConstructor = false
|
||||
end
|
||||
|
||||
objectCache[obj] = class
|
||||
objectCache[privObj] = class
|
||||
|
||||
for k,v in pairs(privObj) do
|
||||
if type(v) == "table" and v == class.private[k] then
|
||||
privObj[k] = instantiate(v)
|
||||
end
|
||||
end
|
||||
|
||||
return obj
|
||||
end,
|
||||
}
|
||||
|
||||
local iClass
|
||||
if inherit then
|
||||
iClass = classCache[inherit]
|
||||
class.parent = iClass
|
||||
setmetatable(class.static, {__index=iClass.static})
|
||||
setmetatable(class.public, {
|
||||
__index = function(tbl, key)
|
||||
if iClass.public[key] ~= nil then
|
||||
return iClass.public[key]
|
||||
else
|
||||
return class.static[key]
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
setmetatable(class.private, {
|
||||
__index = function(tbl, key)
|
||||
if iClass.private[key] ~= nil then
|
||||
return iClass.private[key]
|
||||
else
|
||||
return class.public[key]
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
for k,v in pairs(class.properties) do
|
||||
setmetatable(v, {__index=iClass.properties[k]})
|
||||
end
|
||||
|
||||
setmetatable(class, {__index=iClass})
|
||||
else
|
||||
setmetatable(class.public, {__index=class.static})
|
||||
setmetatable(class.private, {__index=class.public})
|
||||
end
|
||||
|
||||
loopThrough = {"static","private","public"}
|
||||
for i,l in ipairs(loopThrough) do
|
||||
if classTbl[l] then
|
||||
for k,v in pairs(classTbl[l]) do
|
||||
if type(k) == "number" then
|
||||
if type(v) == "table" and v.name then
|
||||
if v.const then
|
||||
class.properties.consts[v.name] = true
|
||||
end
|
||||
if v.type then
|
||||
class.properties.types[v.name] = v.type
|
||||
end
|
||||
if v.value or v.type then
|
||||
class[l][v.name] = v.value or default[v.type]
|
||||
end
|
||||
class.properties[l][v.name] = true -- now values can be generic typed starting with nil but still recognized
|
||||
elseif type(v) == "string" then
|
||||
class.properties[l][v] = true
|
||||
end
|
||||
elseif type(k) == "string" then
|
||||
if l == "public" and k == name then -- constructor
|
||||
if type(v) ~= "function" then
|
||||
error("invalid constructor: expected function, got "..type(v),2)
|
||||
end
|
||||
class.constructor = v
|
||||
elseif metamethods[k] then
|
||||
class.metatable[l][k] = v
|
||||
else
|
||||
class[l][k] = v
|
||||
class.properties[l][k] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local classObj = {}
|
||||
|
||||
classCache[classObj] = class
|
||||
class.obj = classObj
|
||||
|
||||
setmetatable(classObj, class.metatable.static)
|
||||
|
||||
env[name] = classObj
|
||||
end
|
||||
|
||||
function oop.class(name)
|
||||
return function(class)
|
||||
if classCache[class] then -- a class object was passed meaning we're gonna inherit
|
||||
return function(realclass)
|
||||
makeClass(name, realclass, class)
|
||||
end
|
||||
else
|
||||
makeClass(name, class)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local oType = type
|
||||
function oop.type(value, numberType)
|
||||
if oType(value) == "table" then
|
||||
if objectCache[value] then
|
||||
return objectCache[value].name
|
||||
elseif classCache[value] then
|
||||
return "class"
|
||||
else
|
||||
return "table"
|
||||
end
|
||||
elseif numberType and oType(value) == "number" then
|
||||
return getNumberType(value)
|
||||
else
|
||||
return oType(value)
|
||||
end
|
||||
end
|
||||
|
||||
function oop.getClassName(class)
|
||||
oop.expect(1, class, "class")
|
||||
return classCache[class].name
|
||||
end
|
||||
|
||||
function oop.isType(value, ...)
|
||||
local types = {oop.type(value), oType(value), oop.type(value, true)}
|
||||
if types[1] ~= types[2] and types[3] ~= "class" then
|
||||
types[3] = "object"
|
||||
end
|
||||
local allowedTypes = {...}
|
||||
for i,t in ipairs(types) do
|
||||
for i=1, #allowedTypes do
|
||||
if allowedTypes[i] == t or (allowedTypes[i] == "double" and t == "number") then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function oop.expect(index, value, ...)
|
||||
local level = 3
|
||||
local allowedTypes = {...}
|
||||
if type(allowedTypes[1]) == "number" then
|
||||
level = allowedTypes[1]
|
||||
table.remove(allowedTypes, 1)
|
||||
end
|
||||
if type(allowedTypes[1]) ~= "string" then
|
||||
error("bad argument #3: expected string", 2)
|
||||
end
|
||||
if oop.isType(value, ...) then
|
||||
return value
|
||||
end
|
||||
|
||||
local expectlist
|
||||
local numbertype = false
|
||||
for t=1,#allowedTypes do
|
||||
if allowedTypes[t] == "int" then
|
||||
numbertype = true
|
||||
end
|
||||
end
|
||||
if #allowedTypes > 1 then
|
||||
local lastType = allowedTypes[#allowedTypes]
|
||||
allowedTypes[#allowedTypes] = nil
|
||||
expectlist = table.concat(allowedTypes, ", ").." or "..lastType
|
||||
else
|
||||
expectlist = allowedTypes[1]
|
||||
end
|
||||
local t = oop.type(value, numbertype)
|
||||
|
||||
error("bad argument #"..index..": expected "..expectlist.." got "..t.." ("..tostring(value)..")", level)
|
||||
end
|
||||
|
||||
function oop.getPublicObject(privateObject)
|
||||
return publicCache[privateObject] or privateObject
|
||||
end
|
||||
|
||||
function oop.import(filepath)
|
||||
oop.expect(1, filepath, "string")
|
||||
|
||||
local makePackage = require("cc.require")
|
||||
local tEnv = setmetatable({shell=shell, multishell=multishell},{__index=env})
|
||||
tEnv.require, tEnv.package = makePackage.make(tEnv, dir)
|
||||
tEnv.oop = oop
|
||||
|
||||
oop.injectEnv(tEnv)
|
||||
|
||||
local pathlog = filepath
|
||||
local filepath2 = filepath..".lua"
|
||||
pathlog = pathlog.."\n"..filepath2
|
||||
|
||||
if filepath:sub(1,1) ~= "/" then
|
||||
pathlog = pathlog.."\n"..fs.combine(dir, filepath)
|
||||
pathlog = pathlog.."\n"..fs.combine(dir, filepath2)
|
||||
if fs.exists(fs.combine(dir, filepath)) then
|
||||
filepath = fs.combine(dir, filepath)
|
||||
elseif fs.exists(fs.combine(dir, filepath2)) then
|
||||
filepath = fs.combine(dir, filepath2)
|
||||
end
|
||||
end
|
||||
|
||||
if fs.exists(filepath2) and not fs.exists(filepath) then
|
||||
filepath = filepath2
|
||||
end
|
||||
|
||||
if not fs.exists(filepath) then
|
||||
error("Could not find file:"..pathlog,2)
|
||||
end
|
||||
|
||||
local f = fread(filepath)
|
||||
|
||||
local func, err = load(f, "@"..filepath, nil, tEnv)
|
||||
|
||||
if not func then
|
||||
error(err, 2)
|
||||
else
|
||||
local ok,err = pcall(func)
|
||||
if not ok then
|
||||
error(err, 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return oop
|
||||
723
Program_Files/LevelOS/CMD/latch.lua
Normal file
723
Program_Files/LevelOS/CMD/latch.lua
Normal file
@@ -0,0 +1,723 @@
|
||||
local tokens = {
|
||||
whitespace = {
|
||||
["\t"] = true,
|
||||
[" "] = true,
|
||||
["\n"] = true,
|
||||
[","] = true,
|
||||
},
|
||||
|
||||
line = {
|
||||
["\n"] = true,
|
||||
[","] = true,
|
||||
},
|
||||
|
||||
label = {
|
||||
[":"] = true,
|
||||
},
|
||||
|
||||
indexVar = {
|
||||
["%"] = true,
|
||||
},
|
||||
|
||||
operator = {},
|
||||
op = {
|
||||
add = {
|
||||
["+"] = true,
|
||||
},
|
||||
subtract = {
|
||||
["-"] = true,
|
||||
},
|
||||
multiply = {
|
||||
["*"] = true,
|
||||
},
|
||||
modulo = {
|
||||
["%"] = true,
|
||||
},
|
||||
power = {
|
||||
["^"] = true,
|
||||
},
|
||||
divide = {
|
||||
["/"] = true,
|
||||
},
|
||||
},
|
||||
|
||||
assign = {
|
||||
["="] = true,
|
||||
},
|
||||
|
||||
comparison = {},
|
||||
comp = {
|
||||
equals = {
|
||||
["=="] = true,
|
||||
},
|
||||
notEquals = {
|
||||
["~="] = true,
|
||||
},
|
||||
bigger = {
|
||||
[">"] = true,
|
||||
},
|
||||
biggerOrEquals = {
|
||||
[">="] = true,
|
||||
},
|
||||
smaller = {
|
||||
["<"] = true,
|
||||
},
|
||||
smallerOrEquals = {
|
||||
["<="] = true,
|
||||
},
|
||||
},
|
||||
|
||||
logic = {},
|
||||
logicAnd = {
|
||||
["and"] = true,
|
||||
["&&"] = true,
|
||||
},
|
||||
logicOr = {
|
||||
["or"] = true,
|
||||
["||"] = true,
|
||||
},
|
||||
logicNot = {
|
||||
["not"] = true,
|
||||
["!"] = true,
|
||||
},
|
||||
|
||||
keyword = {},
|
||||
ifStatement = {
|
||||
["if"] = true,
|
||||
},
|
||||
whileStatement = {
|
||||
["while"] = true,
|
||||
},
|
||||
forStatement = {
|
||||
["for"] = true,
|
||||
},
|
||||
elseStatement = {
|
||||
["else"] = true,
|
||||
},
|
||||
localStatement = {
|
||||
["local"] = true,
|
||||
},
|
||||
eof = {
|
||||
["end"] = true,
|
||||
["exit"] = true,
|
||||
},
|
||||
|
||||
boolean = {},
|
||||
boolTrue = {
|
||||
["true"] = true,
|
||||
},
|
||||
boolFalse = {
|
||||
["false"] = true,
|
||||
},
|
||||
|
||||
ident = {
|
||||
["_"] = true,
|
||||
},
|
||||
digits = {
|
||||
},
|
||||
|
||||
string = {
|
||||
["\""] = true,
|
||||
["'"] = true,
|
||||
},
|
||||
|
||||
symbol = {
|
||||
["("] = true,
|
||||
[")"] = true,
|
||||
},
|
||||
|
||||
escape = {
|
||||
["\\"] = true,
|
||||
}
|
||||
}
|
||||
|
||||
for c=("a"):byte(), ("z"):byte() do
|
||||
tokens.ident[string.char(c)] = true
|
||||
tokens.ident[string.char(c):upper()] = true
|
||||
end
|
||||
|
||||
for c=("0"):byte(), ("9"):byte() do
|
||||
tokens.ident[string.char(c)] = true
|
||||
tokens.digits[string.char(c)] = true
|
||||
end
|
||||
|
||||
local function addTo(root, ...)
|
||||
if not root then error("invalid argument #1: expected table, got nil",2) end
|
||||
local tbls = {...}
|
||||
for i,t in ipairs(tbls) do
|
||||
for k,v in pairs(t) do
|
||||
root[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(tokens.comp) do
|
||||
addTo(tokens.comparison, v)
|
||||
end
|
||||
|
||||
for k,v in pairs(tokens.op) do
|
||||
addTo(tokens.operator, v)
|
||||
end
|
||||
|
||||
addTo(tokens.logic, tokens.logicAnd, tokens.logicOr, tokens.logicNot)
|
||||
|
||||
addTo(tokens.keyword, tokens.logic, tokens.ifStatement, tokens.whileStatement, tokens.forStatement, tokens.elseStatement, tokens.localStatement, tokens.eof)
|
||||
|
||||
addTo(tokens.boolean, tokens.boolTrue, tokens.boolFalse)
|
||||
|
||||
local statementValues = {
|
||||
["string"] = true,
|
||||
["number"] = true,
|
||||
["variable"] = true,
|
||||
["arg"] = true,
|
||||
["value"] = true,
|
||||
}
|
||||
|
||||
local validVarTypes = {
|
||||
["function"] = true,
|
||||
["arg"] = true,
|
||||
["variable"] = true,
|
||||
["escape"] = true,
|
||||
}
|
||||
|
||||
local function lex(text)
|
||||
local char = 1
|
||||
local function get(p)
|
||||
local tPos = p or char
|
||||
return text:sub(tPos,tPos)
|
||||
end
|
||||
local beginline = true
|
||||
local inStatement = false
|
||||
local isLabel = false
|
||||
local data = {{}}
|
||||
local line = data[1]
|
||||
local posOffset = 0
|
||||
|
||||
local function newline()
|
||||
posOffset = char
|
||||
table.insert(data,{})
|
||||
line = data[#data]
|
||||
end
|
||||
|
||||
local function addData(txt,type)
|
||||
if not txt then error("no txt",2) end
|
||||
if line[#line] and line[#line].type == type then
|
||||
line[#line].data = line[#line].data..txt
|
||||
line[#line].posLast = line[#line].posLast+#txt
|
||||
else
|
||||
table.insert(line,{data=txt,posFirst=(char-posOffset),posLast=(char-posOffset)+(#txt-1),type=type})
|
||||
end
|
||||
end
|
||||
|
||||
local function readWhitespace(acceptNewline)
|
||||
local txt = get()
|
||||
local oldchar = char
|
||||
while tokens.whitespace[txt] and (acceptNewline or not tokens.line[txt]) do
|
||||
char = char + 1
|
||||
addData(txt,"whitespace")
|
||||
isLabel = false
|
||||
txt = get()
|
||||
end
|
||||
if oldchar == char then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
while char <= #text do
|
||||
local txt = get()
|
||||
if tokens.whitespace[txt] and not tokens.line[txt] then
|
||||
addData(txt,"whitespace")
|
||||
isLabel = false
|
||||
|
||||
elseif tokens.escape[txt] then
|
||||
addData(txt..text:sub(char+1,char+1),"escape")
|
||||
char = char+1
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
isLabel = false
|
||||
beginline = false
|
||||
end
|
||||
|
||||
elseif tokens.string[txt] then
|
||||
local bchar = txt
|
||||
local echar = bchar
|
||||
local stype = "string"
|
||||
if isLabel then
|
||||
stype = "label"
|
||||
elseif beginline then
|
||||
stype = "function"
|
||||
end
|
||||
isLabel = false
|
||||
beginline = false
|
||||
addData(txt,stype)
|
||||
char = char+1
|
||||
while char <= #text do
|
||||
local c = text:sub(char,char)
|
||||
if tokens.escape[c] then
|
||||
addData(c..get(char+1),"escape")
|
||||
char = char+1
|
||||
if tokens.digits[get()] then
|
||||
char = char+1
|
||||
for i=1,2 do
|
||||
if tokens.digits[get()] then
|
||||
addData(get(),"escape")
|
||||
char = char+1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
char = char+1
|
||||
end
|
||||
elseif tokens.indexVar[c] then
|
||||
local b2,e2 = text:find("^%%[A-Za-z0-9_]+%%", char)
|
||||
if b2 then
|
||||
addData(text:sub(b2,e2), "variable")
|
||||
char = e2
|
||||
else
|
||||
local b3,e3 = text:find("^%%[0-9]+", char)
|
||||
if not b3 then
|
||||
b3,e3 = text:find("^%%~[0-9]+", char)
|
||||
end
|
||||
if b3 then
|
||||
addData(text:sub(b3,e3), "arg")
|
||||
char = e3
|
||||
else
|
||||
addData(c, stype)
|
||||
end
|
||||
end
|
||||
char = char+1
|
||||
elseif c == echar then
|
||||
addData(c, stype)
|
||||
break
|
||||
else
|
||||
if c == "\n" then
|
||||
newline()
|
||||
else
|
||||
addData(c, stype)
|
||||
end
|
||||
char = char+1
|
||||
end
|
||||
end
|
||||
|
||||
elseif tokens.indexVar[txt] then
|
||||
if inStatement == 1 and line[#line] and line[#line].type == "whitespace" and line[#line-1] and statementValues[line[#line-1].type] then
|
||||
inStatement = false
|
||||
beginline = true
|
||||
end
|
||||
local b2,e2 = text:find("^%%[A-Za-z0-9_]+%%", char)
|
||||
if b2 then
|
||||
if isLabel and beginline then
|
||||
addData(text:sub(b2,e2), "unidentified")
|
||||
else
|
||||
addData(text:sub(b2,e2), "variable")
|
||||
end
|
||||
char = e2
|
||||
else
|
||||
local b3,e3 = text:find("^%%[0-9]+", char)
|
||||
if not b3 then
|
||||
b3,e3 = text:find("^%%~[0-9]+", char)
|
||||
end
|
||||
if b3 then
|
||||
if isLabel and beginline then
|
||||
addData(text:sub(b3,e3), "unidentified")
|
||||
else
|
||||
addData(text:sub(b3,e3), "arg")
|
||||
end
|
||||
char = e3
|
||||
elseif isLabel then
|
||||
addData(txt, "label")
|
||||
elseif beginline then
|
||||
addData(txt, "function")
|
||||
elseif not inStatement then
|
||||
addData(txt, "string")
|
||||
elseif tokens.operator[txt] then
|
||||
addData(txt, "operator")
|
||||
else
|
||||
addData(txt, "unidentified")
|
||||
end
|
||||
end
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
beginline = false
|
||||
end
|
||||
|
||||
elseif tokens.ident[txt] or (not inStatement and not (tokens.line[txt] or tokens.label[txt] or tokens.assign[txt] or tokens.symbol[txt])) then
|
||||
local b,e
|
||||
if inStatement then
|
||||
b,e = text:find("^[A-Za-z0-9_.]+", char)
|
||||
else
|
||||
b,e = char,char+1
|
||||
local c = get(e)
|
||||
while e <= #text and not (tokens.line[c] or tokens.label[c] or tokens.assign[c] or tokens.indexVar[c] or tokens.whitespace[c] or tokens.symbol[c] or tokens.escape[c]) do
|
||||
e = e + 1
|
||||
c = get(e)
|
||||
end
|
||||
e = e - 1
|
||||
end
|
||||
local token = text:sub(b,e)
|
||||
local ltoken = token:lower()
|
||||
local statementValue = false
|
||||
if inStatement then
|
||||
if line[#line] and line[#line].type == "whitespace" and line[#line-1] and statementValues[line[#line-1].type] then
|
||||
if inStatement == 1 then
|
||||
inStatement = 0
|
||||
beginline = true
|
||||
end
|
||||
statementValue = true
|
||||
end
|
||||
end
|
||||
char = e
|
||||
if isLabel then
|
||||
addData(token, "label")
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
isLabel = false
|
||||
beginline = false
|
||||
end
|
||||
|
||||
elseif tokens.localStatement[ltoken] and not inStatement then
|
||||
if not beginline then
|
||||
addData(token, "string")
|
||||
else
|
||||
addData(token, "keyword")
|
||||
end
|
||||
|
||||
elseif tokens.eof[ltoken] and (inStatement == 0 or not inStatement) then
|
||||
addData(token, "keyword")
|
||||
|
||||
elseif (tokens.ifStatement[ltoken] or tokens.whileStatement[ltoken]) and (inStatement == 0 or not inStatement) then
|
||||
addData(token, "keyword")
|
||||
inStatement = 1
|
||||
|
||||
elseif (tokens.elseStatement[ltoken] or tokens.eof[ltoken]) and (inStatement == 0 or not inStatement) then
|
||||
addData(token, "keyword")
|
||||
|
||||
elseif (tokens.logicAnd[ltoken] or tokens.logicOr[ltoken]) and statementValue then
|
||||
addData(token, "logic")
|
||||
if inStatement == 0 then
|
||||
inStatement = 1
|
||||
end
|
||||
|
||||
elseif tokens.logicNot[ltoken] and inStatement and not statementValue then
|
||||
addData(token, "logic")
|
||||
if inStatement == 0 then
|
||||
inStatement = 1
|
||||
end
|
||||
|
||||
elseif tokens.forStatement[ltoken] and (inStatement == 0 or not inStatement) then
|
||||
-- other handling
|
||||
|
||||
elseif tokens.boolean[ltoken] and inStatement and not statementValue then
|
||||
addData(token, "value")
|
||||
|
||||
elseif beginline and (inStatement == 0 or not inStatement) then
|
||||
addData(token, "function")
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
beginline = false
|
||||
end
|
||||
|
||||
elseif tonumber(token) then
|
||||
addData(token, "number")
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
beginline = false
|
||||
end
|
||||
|
||||
else
|
||||
addData(token, "string")
|
||||
|
||||
end
|
||||
if inStatement == 0 then
|
||||
inStatement = false
|
||||
end
|
||||
|
||||
elseif tokens.label[txt] then
|
||||
if char+1 > #text or tokens.whitespace[get(char+1)] then
|
||||
addData(txt, "string")
|
||||
else
|
||||
addData(txt, "label")
|
||||
isLabel = true
|
||||
end
|
||||
|
||||
elseif tokens.line[txt] then
|
||||
beginline = true
|
||||
inStatement = false
|
||||
if txt ~= "\n" then
|
||||
addData(txt, "symbol")
|
||||
end
|
||||
|
||||
elseif tokens.symbol[txt] then
|
||||
addData(txt, "symbol")
|
||||
|
||||
elseif txt:find("%p") then
|
||||
local b,e = text:find("^%p+", char)
|
||||
local token = text:sub(b,e)
|
||||
char = e
|
||||
if inStatement then
|
||||
if tokens.operator[token] then
|
||||
addData(token, "operator")
|
||||
elseif tokens.comparison[token] then
|
||||
addData(token, "comparison")
|
||||
elseif tokens.logic[token] then
|
||||
addData(token, "logic")
|
||||
else
|
||||
addData(token, "string")
|
||||
end
|
||||
else
|
||||
if tokens.assign[token] then
|
||||
local v = line[#line]
|
||||
if v and v.type == "whitespace" then
|
||||
v = line[#line-1]
|
||||
end
|
||||
if v and (validVarTypes[v.type]) then
|
||||
local it = #line-1
|
||||
while v and (validVarTypes[v.type]) do
|
||||
if v.type == "function" then
|
||||
v.type = "variable"
|
||||
end
|
||||
it = it-1
|
||||
v = line[it]
|
||||
end
|
||||
addData(token, "assign")
|
||||
inStatement = true
|
||||
elseif beginline then
|
||||
addData(token, "unidentified")
|
||||
else
|
||||
addData(token, "string")
|
||||
end
|
||||
elseif beginline then
|
||||
addData(token, "unidentified")
|
||||
else
|
||||
addData(token, "string")
|
||||
end
|
||||
end
|
||||
|
||||
elseif txt ~= "\n" then
|
||||
addData(txt, "unidentified")
|
||||
end
|
||||
if txt == "\n" then
|
||||
newline()
|
||||
end
|
||||
char = char+1
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
local function parse(data, filename)
|
||||
filename = filename or "latch"
|
||||
if type(data) == "string" then
|
||||
data = lex(data)
|
||||
end
|
||||
|
||||
local function err(lineNum, txt, txtafter)
|
||||
local err = filename..": "..txt.." on line "..lineNum
|
||||
if txtafter then
|
||||
err = err.." ("..txtafter..")"
|
||||
end
|
||||
error(err, 0)
|
||||
end
|
||||
|
||||
local function unexpectedToken(line, token, ...)
|
||||
_G.debugtoken = token
|
||||
local exp = {...}
|
||||
local expstr
|
||||
if #exp > 0 then
|
||||
expstr = "expected "..table.concat(exp, ", ")
|
||||
end
|
||||
err(line, "unexpected token '"..tostring(token.data).."' ("..tostring(token.type)..")", expstr)
|
||||
end
|
||||
|
||||
local function locateEntry(tbl, value)
|
||||
for k,v in pairs(tbl) do
|
||||
if v == value then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function parseToken(line, i, allowed, stopAt)
|
||||
local token = line[i]
|
||||
local data = {}
|
||||
|
||||
stopAt = stopAt or {"whitespace"}
|
||||
|
||||
while true do
|
||||
if locateEntry(allowed, token.type) then
|
||||
if token.type == "number" then
|
||||
table.insert(data, {type="number", data=token.data})
|
||||
elseif token.type == "operator" then
|
||||
table.insert(data, {type="operator", data=token.data})
|
||||
elseif token.type == "variable" and token.data:sub(1,1) == "%" then
|
||||
table.insert(data, {type="variable", data=token.data:sub(2,#token.data-1)})
|
||||
elseif token.type == "variable" then
|
||||
table.insert(data, {type="string", data=token.data})
|
||||
elseif token.type == "arg" then
|
||||
table.insert(data, {type="argument", data=token.data:sub(2)})
|
||||
elseif token.type == "label" then
|
||||
if tokens.string[token.data:sub(2,2)] then
|
||||
table.insert(data, {type="label", data=token.data:sub(2):gsub(token.data:sub(2,2),"")})
|
||||
else
|
||||
table.insert(data, {type="label", data=token.data:sub(2)})
|
||||
end
|
||||
elseif tokens.string[token.data:sub(1,1)] then
|
||||
table.insert(data, {type="string", data=token.data:gsub(token.data:sub(1,1),"")})
|
||||
else
|
||||
table.insert(data, {type="string", data=token.data})
|
||||
end
|
||||
elseif locateEntry(stopAt, token.type) then
|
||||
i = i - 1
|
||||
break
|
||||
else
|
||||
local expected = {}
|
||||
addTo(expected, stopAt)
|
||||
addTo(expected, allowed)
|
||||
unexpectedToken(ln, token, unpack(expected))
|
||||
end
|
||||
i = i + 1
|
||||
token = line[i]
|
||||
if not token then break end
|
||||
end
|
||||
|
||||
return data, i
|
||||
end
|
||||
|
||||
local function parseExpression(line, i, whitespaceConcat) -- this is all wrong FUCK, value (x+5) > comparison (x+5 == 8) > expression(x+5 == 8 and %potato%)
|
||||
-- expression structure
|
||||
local token = line[i]
|
||||
local conditions = {
|
||||
{
|
||||
{} -- current condition (value)
|
||||
-- more AND conditions
|
||||
}
|
||||
-- more OR conditions
|
||||
}
|
||||
local condition = conditions[1][1]
|
||||
local isValid = false
|
||||
while true do
|
||||
token = line[i]
|
||||
if not token then break end
|
||||
if token.type == "whitespace" then -- optional token
|
||||
elseif token.type == "logic" and tokens.logicNot[token.data] then -- optional token
|
||||
table.insert(condition, token)
|
||||
isValid = false
|
||||
elseif statementValues[token.type] then -- REQUIRED token, expression is invalid without it
|
||||
table.insert(condition, token)
|
||||
isValid = true
|
||||
i = i + 1
|
||||
token = line[i]
|
||||
if not token then break end
|
||||
if token.type == "whitespace" then
|
||||
i = i + 1
|
||||
token = line[i]
|
||||
end
|
||||
if not token then break end
|
||||
if token.type == "logic" and tokens.logicAnd[token.data] then
|
||||
condition = {}
|
||||
table.insert(conditions[#conditions], condition)
|
||||
isValid = false
|
||||
elseif token.type == "logic" and tokens.logicOr[token.data] then
|
||||
condition = {}
|
||||
table.insert(conditions, {})
|
||||
table.insert(conditions[#conditions], condition)
|
||||
isValid = false
|
||||
elseif token.type == "operator" then
|
||||
table.insert(condition, token)
|
||||
elseif whitespaceConcat then
|
||||
i = i - 1
|
||||
else
|
||||
i = i - 1
|
||||
break -- end of statement
|
||||
end
|
||||
else
|
||||
unexpectedToken(i, token, "expression")
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
if not isValid then
|
||||
err(i, "invalid statement")
|
||||
else
|
||||
return conditions, i
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local program = {
|
||||
arguments = {},
|
||||
env = {},
|
||||
commands = {},
|
||||
labels = {},
|
||||
code = {},
|
||||
}
|
||||
local scope = program.code
|
||||
for ln,line in ipairs(data) do
|
||||
local token
|
||||
local i = 1
|
||||
local beginline = true
|
||||
local function nextToken(includeWhitespace)
|
||||
if line[i+1] and (includeWhitespace or line[i+1].type ~= "whitespace") then
|
||||
return line[i+1]
|
||||
elseif line[i+2] then
|
||||
return line[i+2]
|
||||
end
|
||||
end
|
||||
local function nextTokenType(includeWhitespace)
|
||||
local nt = nextToken(includeWhitespace)
|
||||
if nt then
|
||||
return nt.type
|
||||
end
|
||||
end
|
||||
while i <= #line do
|
||||
token = line[i]
|
||||
if beginline then
|
||||
if token.type == "function" or token.type == "variable" or token.type == "arg" then
|
||||
local data
|
||||
data, i = parseToken(line, i, {"function", "variable", "arg", "escape"}, {"whitespace", "symbol", "assign"})
|
||||
local l
|
||||
if nextTokenType() == "assign" then
|
||||
l = {type="assign", data=data, value={}}
|
||||
while nextTokenType() == "assign" do
|
||||
i = i + 1
|
||||
end
|
||||
i = i + 1
|
||||
l.value, i = parseExpression(line, i, true)
|
||||
else
|
||||
l = {type="command", data=data, line=ln, params={}}
|
||||
beginline = false
|
||||
end
|
||||
table.insert(scope, l)
|
||||
|
||||
elseif token.type == "label" then
|
||||
program.labels[token.data] = {scope=scope, commandNum=#scope+1}
|
||||
|
||||
elseif token.type ~= "whitespace" then
|
||||
--unexpectedToken(ln, token, "whitespace", "function", "variable", "arg")
|
||||
end
|
||||
|
||||
else
|
||||
if token.type == "label" then
|
||||
if scope[#scope].type == "command" then
|
||||
local data
|
||||
data, i = parseToken(line, i, {"label", "variable", "arg", "escape"}, {"whitespace", "symbol"})
|
||||
table.insert(scope[#scope].params, data)
|
||||
else
|
||||
unexpectedToken(ln, token)
|
||||
end
|
||||
|
||||
elseif token.type == "string" or token.type == "number" then
|
||||
if scope[#scope].type == "command" then
|
||||
local data
|
||||
data, i = parseToken(line, i, {"string", "number", "variable", "arg", "escape"}, {"whitespace", "symbol"})
|
||||
table.insert(scope[#scope].params, data)
|
||||
end
|
||||
|
||||
elseif token.type ~= "whitespace" then
|
||||
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return program
|
||||
end
|
||||
|
||||
return {lex=lex,parse=parse}
|
||||
1
Program_Files/LevelOS/Cloud/icon.limg
Normal file
1
Program_Files/LevelOS/Cloud/icon.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," b ","b ",},{"","bb9"," 9 ",},{""," "," ",},},}
|
||||
1493
Program_Files/LevelOS/Cloud/main.lua
Normal file
1493
Program_Files/LevelOS/Cloud/main.lua
Normal file
File diff suppressed because it is too large
Load Diff
1
Program_Files/LevelOS/Cloud/taskbar.limg
Normal file
1
Program_Files/LevelOS/Cloud/taskbar.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," 0","00 ",},{"","000"," ",},},}
|
||||
1
Program_Files/LevelOS/Explorer/icon.limg
Normal file
1
Program_Files/LevelOS/Explorer/icon.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{"","1 ","444",},{"","499","944",},{""," "," ",},},}
|
||||
3685
Program_Files/LevelOS/Explorer/main.lua
Normal file
3685
Program_Files/LevelOS/Explorer/main.lua
Normal file
File diff suppressed because it is too large
Load Diff
1
Program_Files/LevelOS/Explorer/taskbar.limg
Normal file
1
Program_Files/LevelOS/Explorer/taskbar.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," 0","00 ",},{"
","000"," ",},},}
|
||||
1
Program_Files/LevelOS/Lua/icon.limg
Normal file
1
Program_Files/LevelOS/Lua/icon.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," b","bb ",},{""," 0b","bb ",},{"","bb "," ",},},}
|
||||
172
Program_Files/LevelOS/Lua/main.lua
Normal file
172
Program_Files/LevelOS/Lua/main.lua
Normal file
@@ -0,0 +1,172 @@
|
||||
local tArgs = {...}
|
||||
if type(tArgs[1]) == "string" and fs.exists(tArgs[1]) then
|
||||
lOS.execute(table.concat(tArgs," "))
|
||||
return
|
||||
end
|
||||
if LevelOS then LevelOS.self.window.icon = {"\3","b"} end
|
||||
local lex = "LevelOS/modules/lex.lua"
|
||||
local docs = "Program_Files/Slime_Text/highlight/lua/docs.json"
|
||||
local docstable
|
||||
if not fs.exists(lex) then
|
||||
-- oh no
|
||||
end
|
||||
if not fs.exists(docs) then
|
||||
local webres = http.get("http://tweaked.cc/index.json")
|
||||
if webres then
|
||||
docstable = textutils.unserializeJSON(webres.readAll())
|
||||
end
|
||||
--[[if webres then
|
||||
lUtils.fwrite(docs,webres.readAll())
|
||||
end]]
|
||||
end
|
||||
if fs.exists(docs) then
|
||||
docstable = textutils.unserializeJSON(lUtils.fread(docs))
|
||||
end
|
||||
local pretty = require "cc.pretty"
|
||||
|
||||
local tCommandHistory = {}
|
||||
local hCur = 0
|
||||
local bRunning = true
|
||||
local tEnv = {
|
||||
["exit"] = setmetatable({}, {
|
||||
__tostring = function() return "Call exit() to exit." end,
|
||||
__call = function() bRunning = false end,
|
||||
__type = "function",
|
||||
}),
|
||||
["_echo"] = function(...)
|
||||
return ...
|
||||
end,
|
||||
}
|
||||
setmetatable(tEnv, { __index = _ENV })
|
||||
term.setTextColor(colors.yellow)
|
||||
print("LevelOS interactive Lua prompt.\nCall exit() to exit.")
|
||||
term.setTextColor(colors.white)
|
||||
while bRunning do
|
||||
hCur = #tCommandHistory+1
|
||||
write("lua> ")
|
||||
local w,h = term.getSize()
|
||||
local x,y = term.getCursorPos()
|
||||
local self = lUtils.input(x,y,w,y)
|
||||
self.opt.cursorColor = colors.white
|
||||
self.opt.overflowY = "scroll"
|
||||
self.scrollY = 0
|
||||
self.opt.syntax = {
|
||||
type="lua",
|
||||
keyword=colors.yellow,
|
||||
comment=colors.green,
|
||||
string=colors.red,
|
||||
number=colors.purple,
|
||||
symbol=colors.white,
|
||||
operator=colors.lightGray,
|
||||
value=colors.purple,
|
||||
ident=colors.white,
|
||||
["function"]=colors.cyan,
|
||||
nfunction=colors.lime,
|
||||
arg=colors.orange,
|
||||
lexer=lex,
|
||||
whitespace=colors.lightGray,
|
||||
}
|
||||
self.opt.complete = {
|
||||
docs = docstable,
|
||||
env = tEnv,
|
||||
overlay = true,
|
||||
LevelOS = LevelOS,
|
||||
}
|
||||
self.opt.selectColor=colors.gray
|
||||
self.opt.overflowY="stretch"
|
||||
self.opt.overflowX="scroll"
|
||||
_G.debugeditor = self
|
||||
while true do
|
||||
tCommandHistory[hCur] = self.txt
|
||||
self.state = true
|
||||
local doUpdate = true
|
||||
local e = {os.pullEvent()}
|
||||
if e[1] == "term_resize" then
|
||||
local w,h = term.getSize()
|
||||
self.x2 = w
|
||||
elseif e[1] == "key" and (e[2] == keys.up or e[2] == keys.down) and not self.opt.complete.list then
|
||||
doUpdate = false
|
||||
local o = 1
|
||||
if e[2] == keys.up then
|
||||
o = -1
|
||||
end
|
||||
if tCommandHistory[hCur+o] then
|
||||
hCur = hCur+o
|
||||
self.txt = tCommandHistory[hCur]
|
||||
self.cursor.x = #self.txt+1
|
||||
self.cursor.a = #self.txt+1
|
||||
end
|
||||
self.update("term_resize")
|
||||
elseif e[1] == "key" and e[2] == keys.enter and not lUtils.isHolding(keys.leftShift) then
|
||||
if hCur < #tCommandHistory then
|
||||
hCur = #tCommandHistory
|
||||
tCommandHistory[hCur] = self.txt
|
||||
end
|
||||
doUpdate = false
|
||||
term.setCursorBlink(false)
|
||||
LevelOS.overlay = nil
|
||||
print("")
|
||||
local s = self.txt
|
||||
local nForcePrint = 0
|
||||
local func, e = load(s, "=lua", "t", tEnv)
|
||||
local func2 = load("return _echo(" .. s .. ");", "=lua", "t", tEnv)
|
||||
if not func then
|
||||
if func2 then
|
||||
func = func2
|
||||
e = nil
|
||||
nForcePrint = 1
|
||||
end
|
||||
else
|
||||
if func2 then
|
||||
func = func2
|
||||
end
|
||||
end
|
||||
|
||||
if func then
|
||||
local tResults = table.pack(pcall(func))
|
||||
if tResults[1] then
|
||||
local n = 1
|
||||
while n < tResults.n or n <= nForcePrint do
|
||||
local value = tResults[n + 1]
|
||||
local ok, serialised = pcall(pretty.pretty, value, {
|
||||
function_args = settings.get("lua.function_args"),
|
||||
function_source = settings.get("lua.function_source"),
|
||||
})
|
||||
if ok then
|
||||
pretty.print(serialised)
|
||||
else
|
||||
print(tostring(value))
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
else
|
||||
printError(tResults[2])
|
||||
end
|
||||
else
|
||||
printError(e)
|
||||
end
|
||||
break
|
||||
elseif e[1] == "key" or e[1] == "char" or e[1] == "paste" then
|
||||
if hCur < #tCommandHistory then
|
||||
hCur = #tCommandHistory
|
||||
tCommandHistory[hCur] = self.txt
|
||||
end
|
||||
end
|
||||
if doUpdate then
|
||||
self.update(unpack(e))
|
||||
end
|
||||
local w,h = term.getSize()
|
||||
while self.y2 > h do
|
||||
if self.y1 > 1 then
|
||||
term.scroll(1)
|
||||
self.y2 = self.y2-1
|
||||
self.y1 = self.y1-1
|
||||
else
|
||||
self.y1 = 1
|
||||
self.y2 = h
|
||||
self.opt.overflowY = "scroll"
|
||||
end
|
||||
end
|
||||
self.render()
|
||||
end
|
||||
end
|
||||
1
Program_Files/LevelOS/Lua/taskbar.limg
Normal file
1
Program_Files/LevelOS/Lua/taskbar.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," 00","0 ",},{"","000"," ",},},}
|
||||
1
Program_Files/LevelOS/Notepad/icon.limg
Normal file
1
Program_Files/LevelOS/Notepad/icon.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," ","77 ",},{"","888","77 ",},{"","778","88 ",},},}
|
||||
273
Program_Files/LevelOS/Notepad/main.lua
Normal file
273
Program_Files/LevelOS/Notepad/main.lua
Normal file
@@ -0,0 +1,273 @@
|
||||
local tArgs = {...}
|
||||
local tFilepath = ""
|
||||
if tArgs[1] ~= nil then
|
||||
tFilepath = tArgs[1]
|
||||
end
|
||||
local isReadOnly = false
|
||||
if tArgs[2] ~= nil and tArgs[2] == "true" then
|
||||
isReadOnly = true
|
||||
end
|
||||
local tCol = {bg=colors.white,txt=colors.black,misc=colors.lightGray,misc2=colors.gray}
|
||||
local btns = {{"File",{{"New","New window","Open...","Save","Save as..."},"Print","Quit"}},{"Edit",{"Undo",{"Search","Replace"},{"Time"}}},{"View",{"Dark Mode"}}}
|
||||
local function topbar()
|
||||
local w,h = term.getSize()
|
||||
theline = ""
|
||||
for t=1,w-1 do
|
||||
theline = theline.."\131"
|
||||
end
|
||||
term.setCursorPos(1,1)
|
||||
term.setBackgroundColor(tCol.bg)
|
||||
term.setTextColor(tCol.misc)
|
||||
term.clearLine()
|
||||
term.setCursorPos(1,2)
|
||||
term.write(theline)
|
||||
term.setCursorPos(1,1)
|
||||
term.setTextColor(tCol.txt)
|
||||
for t=1,#btns do
|
||||
btns[t].x = ({term.getCursorPos()})[1]
|
||||
btns[t].w = string.len(btns[t][1])+2
|
||||
term.write(" "..btns[t][1].." ")
|
||||
end
|
||||
end
|
||||
local w,h = term.getSize()
|
||||
local a = {}
|
||||
local function txt()
|
||||
a = {{width=w-1,height=h-4,sTable={},filepath="",lines={""},changed=false},0,0,1,1}
|
||||
if tFilepath ~= "" then
|
||||
if fs.exists(tFilepath) == true then
|
||||
local openfile = fs.open(tFilepath,"r")
|
||||
a[1].lines = {}
|
||||
for line in openfile.readLine do
|
||||
a[1].lines[#a[1].lines+1] = line
|
||||
end
|
||||
openfile.close()
|
||||
if a[1].lines[1] == nil then
|
||||
a[1].lines[1] = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
while true do
|
||||
local w,h = term.getSize()
|
||||
a[1].width = w-1
|
||||
a[1].height = h-4
|
||||
a[1].sTable = {background={tCol.bg},text={tCol.txt},cursor={colors.red}}
|
||||
term.setCursorPos(1,5)
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setTextColor(colors.black)
|
||||
--print("I am present.")
|
||||
local changesAllowed = true
|
||||
if isReadOnly == true or (tFilepath ~= "" and fs.isReadOnly(tFilepath) == true) then
|
||||
changesAllowed = false
|
||||
end
|
||||
a = {lUtils.drawEditBox(a[1],1,3,a[2],a[3],a[4],a[5],true,true,nil,changesAllowed)}
|
||||
--term.setCursorPos(1,3)
|
||||
--term.clearLine()
|
||||
--term.write("HIII: ")
|
||||
--term.write(textutils.serialize(a))
|
||||
os.sleep(0)
|
||||
end
|
||||
end
|
||||
_G.thetxtfunction = txt
|
||||
local function save()
|
||||
if tFilepath == "" then
|
||||
while true do
|
||||
local i = {lUtils.inputbox("Filepath","Please enter a new filepath:",29,10,{"Done","Cancel"})}
|
||||
if i[2] == false or i[4] == "Cancel" then
|
||||
return false
|
||||
end
|
||||
if fs.exists(i[1]) == true then
|
||||
lUtils.popup("Error","This path already exists!",29,9,{"OK"})
|
||||
else
|
||||
tFilepath = i[1]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local savefile = fs.open(tFilepath,"w")
|
||||
for t=1,#a[1].lines do
|
||||
savefile.writeLine(a[1].lines[t])
|
||||
end
|
||||
savefile.close()
|
||||
return true
|
||||
end
|
||||
function uwansave()
|
||||
local name = ""
|
||||
if tFilepath == "" then
|
||||
name = "Untitled"
|
||||
else
|
||||
name = fs.getName(tFilepath)
|
||||
end
|
||||
local c = {lUtils.popup("Notepad","Do you want to save your changes in "..name.."?",30,8,{"Save","Don't save","Cancel"})}
|
||||
if c[1] == false then return false
|
||||
elseif c[3] == "Save" then
|
||||
if tFilepath == "" then
|
||||
-- select file path with explorer asap
|
||||
return false
|
||||
end
|
||||
local ayyy = fs.open(tFilepath,"w")
|
||||
for t=1,#a[1].lines do
|
||||
ayyy.writeLine(a[1].lines[t])
|
||||
end
|
||||
end
|
||||
if c[3] ~= "Cancel" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
local function scrollbars()
|
||||
local w,h = term.getSize()
|
||||
term.setCursorPos(1,h-1)
|
||||
term.setBackgroundColor(tCol.misc)
|
||||
term.setTextColor(tCol.misc2)
|
||||
term.clearLine()
|
||||
term.setCursorPos(1,h-1)
|
||||
term.write("\17")
|
||||
term.setCursorPos(w-1,h-1)
|
||||
term.write("\16")
|
||||
for t=2,h-2 do
|
||||
term.setCursorPos(w,t)
|
||||
if t == 3 then
|
||||
term.write("\30")
|
||||
elseif t == h-2 then
|
||||
term.write("\31")
|
||||
else
|
||||
term.write(" ")
|
||||
end
|
||||
end
|
||||
term.setCursorPos(1,h)
|
||||
for t=1,w do
|
||||
term.write("\131")
|
||||
end
|
||||
end
|
||||
function LevelOS.close()
|
||||
local u = true
|
||||
if a[1].changed == true then
|
||||
u = uwansave()
|
||||
end
|
||||
if u == true then
|
||||
return
|
||||
else
|
||||
regevents()
|
||||
end
|
||||
end
|
||||
function regevents()
|
||||
scrollbars()
|
||||
local txtcor = coroutine.create(txt)
|
||||
topbar()
|
||||
coroutine.resume(txtcor)
|
||||
while true do
|
||||
e = {os.pullEvent()}
|
||||
scrollbars()
|
||||
if not ((e[1] == "mouse_click" or e[1] == "mouse_up") and e[4] == 1) then
|
||||
coroutine.resume(txtcor,table.unpack(e))
|
||||
end
|
||||
--term.setCursorPos(1,3)
|
||||
--term.setBackgroundColor(colors.white)
|
||||
--term.setTextColor(colors.black)
|
||||
--term.clearLine()
|
||||
--term.setCursorPos(1,3)
|
||||
--term.write(coroutine.status(txtcor).." "..textutils.serialize(a[1]))
|
||||
if e[1] == "term_resize" then
|
||||
topbar()
|
||||
scrollbars()
|
||||
coroutine.resume(txtcor,"mouse_click",1,1,1)
|
||||
elseif e[1] == "mouse_click" then
|
||||
if e[4] == 1 then
|
||||
topbar()
|
||||
term.setCursorBlink(false)
|
||||
local oldcursorpos = {term.getCursorPos()}
|
||||
for t=1,#btns do
|
||||
if e[3] >= btns[t].x and e[3] <= btns[t].x+btns[t].w-1 then
|
||||
-- open menu and color button light blue
|
||||
term.setCursorPos(btns[t].x,1)
|
||||
term.setBackgroundColor(colors.blue)
|
||||
term.write(" "..btns[t][1].." ")
|
||||
local disabled = {}
|
||||
if btns[t][1] == "File" then
|
||||
if a[1].changed == false then
|
||||
disabled = {"Save","Save as..."}
|
||||
end
|
||||
end
|
||||
local b = {lUtils.clickmenu(btns[t].x,2,20,btns[t][2],true,disabled)}
|
||||
if b[1] ~= false then
|
||||
if b[3] == "New" then
|
||||
local d = true
|
||||
if a[1].changed == true then
|
||||
d = uwansave()
|
||||
end
|
||||
if d == true then
|
||||
tFilepath = ""
|
||||
txtcor = coroutine.create(txt)
|
||||
os.startTimer(0.1)
|
||||
end
|
||||
elseif b[3] == "New window" then
|
||||
lOS.execute(LevelOS.path)
|
||||
elseif b[3] == "Open..." then
|
||||
local u = true
|
||||
if a[1].changed == true then
|
||||
u = uwansave()
|
||||
end
|
||||
if u == true then
|
||||
local d = {lUtils.explorer("/","SelFile false")}
|
||||
if d[1] ~= nil then
|
||||
if fs.exists(d[1]) == true then
|
||||
a = {}
|
||||
txtcor = coroutine.create(txt)
|
||||
coroutine.resume(txtcor)
|
||||
tFilepath = d[1]
|
||||
local openfile = fs.open(tFilepath,"r")
|
||||
a[1].lines = {}
|
||||
for line in openfile.readLine do
|
||||
a[1].lines[#a[1].lines+1] = line
|
||||
end
|
||||
openfile.close()
|
||||
if a[1].lines[1] == nil then
|
||||
a[1].lines[1] = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif b[3] == "Save" then
|
||||
if save() == true then
|
||||
a[1].changed = false
|
||||
end
|
||||
elseif b[3] == "Save as..." then
|
||||
local oldF = tFilepath
|
||||
tFilepath = ""
|
||||
if save() == false then
|
||||
tFilepath = oldF
|
||||
else
|
||||
a[1].changed = false
|
||||
end
|
||||
elseif b[3] == "Quit" then
|
||||
local u = true
|
||||
if a[1].changed == true then
|
||||
u = uwansave()
|
||||
end
|
||||
if u == true then
|
||||
return
|
||||
end
|
||||
elseif b[3] == "Dark Mode" then
|
||||
tCol = {bg=colors.black,txt=colors.white,misc=colors.gray,misc2=colors.lightGray}
|
||||
topbar()
|
||||
scrollbars()
|
||||
coroutine.resume(txtcor,"mouse_click",1,1,1)
|
||||
btns[3][2][1] = "Light Mode"
|
||||
elseif b[3] == "Light Mode" then
|
||||
tCol = {bg=colors.white,txt=colors.black,misc=colors.lightGray,misc2=colors.gray}
|
||||
topbar()
|
||||
scrollbars()
|
||||
coroutine.resume(txtcor,"mouse_click",1,1,1)
|
||||
btns[3][2][1] = "Dark Mode"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
topbar()
|
||||
term.setCursorPos(table.unpack(oldcursorpos))
|
||||
term.setTextColor(colors.red)
|
||||
term.setCursorBlink(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
regevents()
|
||||
1
Program_Files/LevelOS/Notepad/taskbar.limg
Normal file
1
Program_Files/LevelOS/Notepad/taskbar.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," 0","00 ",},{"
","000"," ",},},}
|
||||
1
Program_Files/LevelOS/Store/icon.limg
Normal file
1
Program_Files/LevelOS/Store/icon.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," ","999",},{""," 9 ","909",},{"","999"," ",},},}
|
||||
1538
Program_Files/LevelOS/Store/main.lua
Normal file
1538
Program_Files/LevelOS/Store/main.lua
Normal file
File diff suppressed because it is too large
Load Diff
1
Program_Files/LevelOS/Store/taskbar.limg
Normal file
1
Program_Files/LevelOS/Store/taskbar.limg
Normal file
@@ -0,0 +1 @@
|
||||
{{{""," 0","00 ",},{"
","000"," ",},},}
|
||||
Reference in New Issue
Block a user