Upload System Image
This commit is contained in:
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