diff options
| author | Andrew Lee <alee14498@protonmail.com> | 2020-11-16 15:31:33 -0500 |
|---|---|---|
| committer | Andrew Lee <alee14498@protonmail.com> | 2020-11-16 15:31:33 -0500 |
| commit | 4475d80db9a8eb0db0b7bb88cf2d76794073f46c (patch) | |
| tree | 1759ed70057c4f4062222258e890a4170bb120dd /Programs/LuaIDE.bup/Contents/bits-UI/luaide.lua | |
| parent | 59acb51a3297917dd8eebc84ea85abd91e7803df (diff) | |
| download | bits-UI-4475d80db9a8eb0db0b7bb88cf2d76794073f46c.tar.gz bits-UI-4475d80db9a8eb0db0b7bb88cf2d76794073f46c.tar.bz2 bits-UI-4475d80db9a8eb0db0b7bb88cf2d76794073f46c.zip | |
Removed unnecessary stuff in programs
Diffstat (limited to 'Programs/LuaIDE.bup/Contents/bits-UI/luaide.lua')
| -rw-r--r-- | Programs/LuaIDE.bup/Contents/bits-UI/luaide.lua | 2224 |
1 files changed, 0 insertions, 2224 deletions
diff --git a/Programs/LuaIDE.bup/Contents/bits-UI/luaide.lua b/Programs/LuaIDE.bup/Contents/bits-UI/luaide.lua deleted file mode 100644 index 5e06e6b..0000000 --- a/Programs/LuaIDE.bup/Contents/bits-UI/luaide.lua +++ /dev/null @@ -1,2224 +0,0 @@ - --- --- Lua IDE --- Made by GravityScore --- - - - - --- Variables - -local version = "1.1" -local arguments = {...} - - -local w, h = term.getSize() -local tabWidth = 2 - - -local autosaveInterval = 20 -local allowEditorEvent = true -local keyboardShortcutTimeout = 0.4 - - -local clipboard = nil - - -local theme = { - background = colors.gray, - titleBar = colors.lightGray, - - top = colors.lightBlue, - bottom = colors.cyan, - - button = colors.cyan, - buttonHighlighted = colors.lightBlue, - - dangerButton = colors.red, - dangerButtonHighlighted = colors.pink, - - text = colors.white, - folder = colors.lime, - readOnly = colors.red, -} - - -local languages = {} -local currentLanguage = {} - - -local updateURL = "https://raw.github.com/GravityScore/LuaIDE/master/computercraft/ide.lua" -local ideLocation = "/" .. shell.getRunningProgram() -local themeLocation = "/.luaide_theme" - -local function isAdvanced() - return term.isColor and term.isColor() -end - - - - --- -------- Utilities - -local function modRead(properties) - local w, h = term.getSize() - local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil, - liveUpdates = nil, exitOnKey = nil} - if not properties then properties = {} end - for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end - if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end - if not properties.visibleLength then properties.visibleLength = w end - - local sx, sy = term.getCursorPos() - local line = "" - local pos = 0 - local historyPos = nil - - local function redraw(repl) - local scroll = 0 - if properties.visibleLength and sx + pos > properties.visibleLength + 1 then - scroll = (sx + pos) - (properties.visibleLength + 1) - end - - term.setCursorPos(sx, sy) - local a = repl or properties.replaceChar - if a then term.write(string.rep(a, line:len() - scroll)) - else term.write(line:sub(scroll + 1, -1)) end - term.setCursorPos(sx + pos - scroll, sy) - end - - local function sendLiveUpdates(event, ...) - if type(properties.liveUpdates) == "function" then - local ox, oy = term.getCursorPos() - local a, data = properties.liveUpdates(line, event, ...) - if a == true and data == nil then - term.setCursorBlink(false) - return line - elseif a == true and data ~= nil then - term.setCursorBlink(false) - return data - end - term.setCursorPos(ox, oy) - end - end - - term.setCursorBlink(true) - while true do - local e, but, x, y, p4, p5 = os.pullEvent() - - if e == "char" then - local s = false - if properties.textLength and line:len() < properties.textLength then s = true - elseif not properties.textLength then s = true end - - local canType = true - if not properties.grantPrint and properties.refusePrint then - local canTypeKeys = {} - if type(properties.refusePrint) == "table" then - for _, v in pairs(properties.refusePrint) do - table.insert(canTypeKeys, tostring(v):sub(1, 1)) - end - elseif type(properties.refusePrint) == "string" then - for char in properties.refusePrint:gmatch(".") do - table.insert(canTypeKeys, char) - end - end - for _, v in pairs(canTypeKeys) do if but == v then canType = false end end - elseif properties.grantPrint then - canType = false - local canTypeKeys = {} - if type(properties.grantPrint) == "table" then - for _, v in pairs(properties.grantPrint) do - table.insert(canTypeKeys, tostring(v):sub(1, 1)) - end - elseif type(properties.grantPrint) == "string" then - for char in properties.grantPrint:gmatch(".") do - table.insert(canTypeKeys, char) - end - end - for _, v in pairs(canTypeKeys) do if but == v then canType = true end end - end - - if s and canType then - line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1) - pos = pos + 1 - redraw() - end - elseif e == "key" then - if but == keys.enter then break - elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end - elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end - elseif (but == keys.up or but == keys.down) and properties.history then - redraw(" ") - if but == keys.up then - if historyPos == nil and #properties.history > 0 then - historyPos = #properties.history - elseif historyPos > 1 then - historyPos = historyPos - 1 - end - elseif but == keys.down then - if historyPos == #properties.history then historyPos = nil - elseif historyPos ~= nil then historyPos = historyPos + 1 end - end - - if properties.history and historyPos then - line = properties.history[historyPos] - pos = line:len() - else - line = "" - pos = 0 - end - - redraw() - local a = sendLiveUpdates("history") - if a then return a end - elseif but == keys.backspace and pos > 0 then - redraw(" ") - line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1) - pos = pos - 1 - redraw() - local a = sendLiveUpdates("delete") - if a then return a end - elseif but == keys.home then - pos = 0 - redraw() - elseif but == keys.delete and pos < line:len() then - redraw(" ") - line = line:sub(1, pos) .. line:sub(pos + 2, -1) - redraw() - local a = sendLiveUpdates("delete") - if a then return a end - elseif but == keys["end"] then - pos = line:len() - redraw() - elseif properties.exitOnKey then - if but == properties.exitOnKey or (properties.exitOnKey == "control" and - (but == 29 or but == 157)) then - term.setCursorBlink(false) - return nil - end - end - end - local a = sendLiveUpdates(e, but, x, y, p4, p5) - if a then return a end - end - - term.setCursorBlink(false) - if line ~= nil then line = line:gsub("^%s*(.-)%s*$", "%1") end - return line -end - - --- -------- Themes - -local defaultTheme = { - background = "gray", - backgroundHighlight = "lightGray", - prompt = "cyan", - promptHighlight = "lightBlue", - err = "red", - errHighlight = "pink", - - editorBackground = "gray", - editorLineHightlight = "lightBlue", - editorLineNumbers = "gray", - editorLineNumbersHighlight = "lightGray", - editorError = "pink", - editorErrorHighlight = "red", - - textColor = "white", - conditional = "yellow", - constant = "orange", - ["function"] = "magenta", - string = "red", - comment = "lime" -} - -local normalTheme = { - background = "black", - backgroundHighlight = "black", - prompt = "black", - promptHighlight = "black", - err = "black", - errHighlight = "black", - - editorBackground = "black", - editorLineHightlight = "black", - editorLineNumbers = "black", - editorLineNumbersHighlight = "white", - editorError = "black", - editorErrorHighlight = "black", - - textColor = "white", - conditional = "white", - constant = "white", - ["function"] = "white", - string = "white", - comment = "white" -} - -local availableThemes = { - {"Water (Default)", "https://raw.github.com/GravityScore/LuaIDE/master/themes/default.txt"}, - {"Fire", "https://raw.github.com/GravityScore/LuaIDE/master/themes/fire.txt"}, - {"Sublime Text 2", "https://raw.github.com/GravityScore/LuaIDE/master/themes/st2.txt"}, - {"Midnight", "https://raw.github.com/GravityScore/LuaIDE/master/themes/midnight.txt"}, - {"TheOriginalBIT", "https://raw.github.com/GravityScore/LuaIDE/master/themes/bit.txt"}, - {"Superaxander", "https://raw.github.com/GravityScore/LuaIDE/master/themes/superaxander.txt"}, - {"Forest", "https://raw.github.com/GravityScore/LuaIDE/master/themes/forest.txt"}, - {"Night", "https://raw.github.com/GravityScore/LuaIDE/master/themes/night.txt"}, - {"Original", "https://raw.github.com/GravityScore/LuaIDE/master/themes/original.txt"}, -} - -local function loadTheme(path) - local f = io.open(path) - local l = f:read("*l") - local config = {} - while l ~= nil do - local k, v = string.match(l, "^(%a+)=(%a+)") - if k and v then config[k] = v end - l = f:read("*l") - end - f:close() - return config -end - --- Load Theme -if isAdvanced() then theme = defaultTheme -else theme = normalTheme end - - --- -------- Drawing - -local function centerPrint(text, ny) - if type(text) == "table" then for _, v in pairs(text) do centerPrint(v) end - else - local x, y = term.getCursorPos() - local w, h = term.getSize() - term.setCursorPos(w/2 - text:len()/2 + (#text % 2 == 0 and 1 or 0), ny or y) - print(text) - end -end - -local function title(t) - term.setTextColor(colors[theme.textColor]) - term.setBackgroundColor(colors[theme.background]) - term.clear() - - term.setBackgroundColor(colors[theme.backgroundHighlight]) - for i = 2, 4 do term.setCursorPos(1, i) term.clearLine() end - term.setCursorPos(3, 3) - term.write(t) -end - -local function centerRead(wid, begt) - local function liveUpdate(line, e, but, x, y, p4, p5) - if isAdvanced() and e == "mouse_click" and x >= w/2 - wid/2 and x <= w/2 - wid/2 + 10 - and y >= 13 and y <= 15 then - return true, "" - end - end - - if not begt then begt = "" end - term.setTextColor(colors[theme.textColor]) - term.setBackgroundColor(colors[theme.promptHighlight]) - for i = 8, 10 do - term.setCursorPos(w/2 - wid/2, i) - term.write(string.rep(" ", wid)) - end - - if isAdvanced() then - term.setBackgroundColor(colors[theme.errHighlight]) - for i = 13, 15 do - term.setCursorPos(w/2 - wid/2 + 1, i) - term.write(string.rep(" ", 10)) - end - term.setCursorPos(w/2 - wid/2 + 2, 14) - term.write("> Cancel") - end - - term.setBackgroundColor(colors[theme.promptHighlight]) - term.setCursorPos(w/2 - wid/2 + 1, 9) - term.write("> " .. begt) - return modRead({visibleLength = w/2 + wid/2, liveUpdates = liveUpdate}) -end - - --- -------- Prompt - -local function prompt(list, dir, isGrid) - local function draw(sel) - for i, v in ipairs(list) do - if i == sel then term.setBackgroundColor(v.highlight or colors[theme.promptHighlight]) - else term.setBackgroundColor(v.bg or colors[theme.prompt]) end - term.setTextColor(v.tc or colors[theme.textColor]) - for i = -1, 1 do - term.setCursorPos(v[2], v[3] + i) - term.write(string.rep(" ", v[1]:len() + 4)) - end - - term.setCursorPos(v[2], v[3]) - if i == sel then - term.setBackgroundColor(v.highlight or colors[theme.promptHighlight]) - term.write(" > ") - else term.write(" - ") end - term.write(v[1] .. " ") - end - end - - local key1 = dir == "horizontal" and 203 or 200 - local key2 = dir == "horizontal" and 205 or 208 - local sel = 1 - draw(sel) - - while true do - local e, but, x, y = os.pullEvent() - if e == "key" and but == 28 then - return list[sel][1] - elseif e == "key" and but == key1 and sel > 1 then - sel = sel - 1 - draw(sel) - elseif e == "key" and but == key2 and ((err == true and sel < #list - 1) or (sel < #list)) then - sel = sel + 1 - draw(sel) - elseif isGrid and e == "key" and but == 203 and sel > 2 then - sel = sel - 2 - draw(sel) - elseif isGrid and e == "key" and but == 205 and sel < 3 then - sel = sel + 2 - draw(sel) - elseif e == "mouse_click" then - for i, v in ipairs(list) do - if x >= v[2] - 1 and x <= v[2] + v[1]:len() + 3 and y >= v[3] - 1 and y <= v[3] + 1 then - return list[i][1] - end - end - end - end -end - -local function scrollingPrompt(list) - local function draw(items, sel, loc) - for i, v in ipairs(items) do - local bg = colors[theme.prompt] - local bghigh = colors[theme.promptHighlight] - if v:find("Back") or v:find("Return") then - bg = colors[theme.err] - bghigh = colors[theme.errHighlight] - end - - if i == sel then term.setBackgroundColor(bghigh) - else term.setBackgroundColor(bg) end - term.setTextColor(colors[theme.textColor]) - for x = -1, 1 do - term.setCursorPos(3, (i * 4) + x + 4) - term.write(string.rep(" ", w - 13)) - end - - term.setCursorPos(3, i * 4 + 4) - if i == sel then - term.setBackgroundColor(bghigh) - term.write(" > ") - else term.write(" - ") end - term.write(v .. " ") - end - end - - local function updateDisplayList(items, loc, len) - local ret = {} - for i = 1, len do - local item = items[i + loc - 1] - if item then table.insert(ret, item) end - end - return ret - end - - -- Variables - local sel = 1 - local loc = 1 - local len = 3 - local disList = updateDisplayList(list, loc, len) - draw(disList, sel, loc) - - -- Loop - while true do - local e, key, x, y = os.pullEvent() - - if e == "mouse_click" then - for i, v in ipairs(disList) do - if x >= 3 and x <= w - 11 and y >= i * 4 + 3 and y <= i * 4 + 5 then return v end - end - elseif e == "key" and key == 200 then - if sel > 1 then - sel = sel - 1 - draw(disList, sel, loc) - elseif loc > 1 then - loc = loc - 1 - disList = updateDisplayList(list, loc, len) - draw(disList, sel, loc) - end - elseif e == "key" and key == 208 then - if sel < len then - sel = sel + 1 - draw(disList, sel, loc) - elseif loc + len - 1 < #list then - loc = loc + 1 - disList = updateDisplayList(list, loc, len) - draw(disList, sel, loc) - end - elseif e == "mouse_scroll" then - os.queueEvent("key", key == -1 and 200 or 208) - elseif e == "key" and key == 28 then - return disList[sel] - end - end -end - -function monitorKeyboardShortcuts() - local ta, tb = nil, nil - local allowChar = false - local shiftPressed = false - while true do - local event, char = os.pullEvent() - if event == "key" and (char == 42 or char == 52) then - shiftPressed = true - tb = os.startTimer(keyboardShortcutTimeout) - elseif event == "key" and (char == 29 or char == 157 or char == 219 or char == 220) then - allowEditorEvent = false - allowChar = true - ta = os.startTimer(keyboardShortcutTimeout) - elseif event == "key" and allowChar then - local name = nil - for k, v in pairs(keys) do - if v == char then - if shiftPressed then os.queueEvent("shortcut", "ctrl shift", k:lower()) - else os.queueEvent("shortcut", "ctrl", k:lower()) end - sleep(0.005) - allowEditorEvent = true - end - end - if shiftPressed then os.queueEvent("shortcut", "ctrl shift", char) - else os.queueEvent("shortcut", "ctrl", char) end - elseif event == "timer" and char == ta then - allowEditorEvent = true - allowChar = false - elseif event == "timer" and char == tb then - shiftPressed = false - end - end -end - - --- -------- Saving and Loading - -local function download(url, path) - for i = 1, 3 do - local response = http.get(url) - if response then - local data = response.readAll() - response.close() - if path then - local f = io.open(path, "w") - f:write(data) - f:close() - end - return true - end - end - - return false -end - -local function saveFile(path, lines) - local dir = path:sub(1, path:len() - fs.getName(path):len()) - if not fs.exists(dir) then fs.makeDir(dir) end - if not fs.isDir(path) and not fs.isReadOnly(path) then - local a = "" - for _, v in pairs(lines) do a = a .. v .. "\n" end - - local f = io.open(path, "w") - f:write(a) - f:close() - return true - else return false end -end - -local function loadFile(path) - if not fs.exists(path) then - local dir = path:sub(1, path:len() - fs.getName(path):len()) - if not fs.exists(dir) then fs.makeDir(dir) end - local f = io.open(path, "w") - f:write("") - f:close() - end - - local l = {} - if fs.exists(path) and not fs.isDir(path) then - local f = io.open(path, "r") - if f then - local a = f:read("*l") - while a do - table.insert(l, a) - a = f:read("*l") - end - f:close() - end - else return nil end - - if #l < 1 then table.insert(l, "") end - return l -end - - --- -------- Languages - -languages.lua = {} -languages.brainfuck = {} -languages.none = {} - --- Lua - -languages.lua.helpTips = { - "A function you tried to call doesn't exist.", - "You made a typo.", - "The index of an array is nil.", - "The wrong variable type was passed.", - "A function/variable doesn't exist.", - "You missed an 'end'.", - "You missed a 'then'.", - "You declared a variable incorrectly.", - "One of your variables is mysteriously nil." -} - -languages.lua.defaultHelpTips = { - 2, 5 -} - -languages.lua.errors = { - ["Attempt to call nil."] = {1, 2}, - ["Attempt to index nil."] = {3, 2}, - [".+ expected, got .+"] = {4, 2, 9}, - ["'end' expected"] = {6, 2}, - ["'then' expected"] = {7, 2}, - ["'=' expected"] = {8, 2} -} - -languages.lua.keywords = { - ["and"] = "conditional", - ["break"] = "conditional", - ["do"] = "conditional", - ["else"] = "conditional", - ["elseif"] = "conditional", - ["end"] = "conditional", - ["for"] = "conditional", - ["function"] = "conditional", - ["if"] = "conditional", - ["in"] = "conditional", - ["local"] = "conditional", - ["not"] = "conditional", - ["or"] = "conditional", - ["repeat"] = "conditional", - ["return"] = "conditional", - ["then"] = "conditional", - ["until"] = "conditional", - ["while"] = "conditional", - - ["true"] = "constant", - ["false"] = "constant", - ["nil"] = "constant", - - ["print"] = "function", - ["write"] = "function", - ["sleep"] = "function", - ["pairs"] = "function", - ["ipairs"] = "function", - ["loadstring"] = "function", - ["loadfile"] = "function", - ["dofile"] = "function", - ["rawset"] = "function", - ["rawget"] = "function", - ["setfenv"] = "function", - ["getfenv"] = "function", -} - -languages.lua.parseError = function(e) - local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""} - if e and e ~= "" then - ret.err = e - if e:find(":") then - ret.filename = e:sub(1, e:find(":") - 1):gsub("^%s*(.-)%s*$", "%1") - -- The "" is needed to circumvent a CC bug - e = (e:sub(e:find(":") + 1) .. ""):gsub("^%s*(.-)%s*$", "%1") - if e:find(":") then - ret.line = e:sub(1, e:find(":") - 1) - e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. "" - end - end - ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "." - end - - return ret -end - -languages.lua.getCompilerErrors = function(code) - code = "local function ee65da6af1cb6f63fee9a081246f2fd92b36ef2(...)\n\n" .. code .. "\n\nend" - local fn, err = loadstring(code) - if not err then - local _, e = pcall(fn) - if e then err = e end - end - - if err then - local a = err:find("]", 1, true) - if a then err = "string" .. err:sub(a + 1, -1) end - local ret = languages.lua.parseError(err) - if tonumber(ret.line) then ret.line = tonumber(ret.line) end - return ret - else return languages.lua.parseError(nil) end -end - -languages.lua.run = function(path, ar) - local fn, err = loadfile(path) - setfenv(fn, getfenv()) - if not err then - _, err = pcall(function() fn(unpack(ar)) end) - end - return err -end - - --- Brainfuck - -languages.brainfuck.helpTips = { - "Well idk...", - "Isn't this the whole point of the language?", - "Ya know... Not being able to debug it?", - "You made a typo." -} - -languages.brainfuck.defaultHelpTips = { - 1, 2, 3 -} - -languages.brainfuck.errors = { - ["No matching '['"] = {1, 2, 3, 4} -} - -languages.brainfuck.keywords = {} - -languages.brainfuck.parseError = function(e) - local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""} - if e and e ~= "" then - ret.err = e - ret.line = e:sub(1, e:find(":") - 1) - e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. "" - ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "." - end - - return ret -end - -languages.brainfuck.mapLoops = function(code) - -- Map loops - local loopLocations = {} - local loc = 1 - local line = 1 - for let in string.gmatch(code, ".") do - if let == "[" then - loopLocations[loc] = true - elseif let == "]" then - local found = false - for i = loc, 1, -1 do - if loopLocations[i] == true then - loopLocations[i] = loc - found = true - end - end - - if not found then - return line .. ": No matching '['" - end - end - - if let == "\n" then line = line + 1 end - loc = loc + 1 - end - return loopLocations -end - -languages.brainfuck.getCompilerErrors = function(code) - local a = languages.brainfuck.mapLoops(code) - if type(a) == "string" then return languages.brainfuck.parseError(a) - else return languages.brainfuck.parseError(nil) end -end - -languages.brainfuck.run = function(path) - -- Read from file - local f = io.open(path, "r") - local content = f:read("*a") - f:close() - - -- Define environment - local dataCells = {} - local dataPointer = 1 - local instructionPointer = 1 - - -- Map loops - local loopLocations = languages.brainfuck.mapLoops(content) - if type(loopLocations) == "string" then return loopLocations end - - -- Execute code - while true do - local let = content:sub(instructionPointer, instructionPointer) - - if let == ">" then - dataPointer = dataPointer + 1 - if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end - elseif let == "<" then - if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end - dataPointer = dataPointer - 1 - if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end - elseif let == "+" then - if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end - dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] + 1 - elseif let == "-" then - if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end - dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] - 1 - elseif let == "." then - if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end - if term.getCursorPos() >= w then print("") end - write(string.char(math.max(1, dataCells[tostring(dataPointer)]))) - elseif let == "," then - if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end - term.setCursorBlink(true) - local e, but = os.pullEvent("char") - term.setCursorBlink(false) - dataCells[tostring(dataPointer)] = string.byte(but) - if term.getCursorPos() >= w then print("") end - write(but) - elseif let == "/" then - if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end - if term.getCursorPos() >= w then print("") end - write(dataCells[tostring(dataPointer)]) - elseif let == "[" then - if dataCells[tostring(dataPointer)] == 0 then - for k, v in pairs(loopLocations) do - if k == instructionPointer then instructionPointer = v end - end - end - elseif let == "]" then - for k, v in pairs(loopLocations) do - if v == instructionPointer then instructionPointer = k - 1 end - end - end - - instructionPointer = instructionPointer + 1 - if instructionPointer > content:len() then print("") break end - end -end - --- None - -languages.none.helpTips = {} -languages.none.defaultHelpTips = {} -languages.none.errors = {} -languages.none.keywords = {} - -languages.none.parseError = function(err) - return {filename = "", line = -1, display = "", err = ""} -end - -languages.none.getCompilerErrors = function(code) - return languages.none.parseError(nil) -end - -languages.none.run = function(path) end - - --- Load language -currentLanguage = languages.lua - - --- -------- Run GUI - -local function viewErrorHelp(e) - title("LuaIDE - Error Help") - - local tips = nil - for k, v in pairs(currentLanguage.errors) do - if e.display:find(k) then tips = v break end - end - - term.setBackgroundColor(colors[theme.err]) - for i = 6, 8 do - term.setCursorPos(5, i) - term.write(string.rep(" ", 35)) - end - - term.setBackgroundColor(colors[theme.prompt]) - for i = 10, 18 do - term.setCursorPos(5, i) - term.write(string.rep(" ", 46)) - end - - if tips then - term.setBackgroundColor(colors[theme.err]) - term.setCursorPos(6, 7) - term.write("Error Help") - - term.setBackgroundColor(colors[theme.prompt]) - for i, v in ipairs(tips) do - term.setCursorPos(7, i + 10) - term.write("- " .. currentLanguage.helpTips[v]) - end - else - term.setBackgroundColor(colors[theme.err]) - term.setCursorPos(6, 7) - term.write("No Error Tips Available!") - - term.setBackgroundColor(colors[theme.prompt]) - term.setCursorPos(6, 11) - term.write("There are no error tips available, but") - term.setCursorPos(6, 12) - term.write("you could see if it was any of these:") - - for i, v in ipairs(currentLanguage.defaultHelpTips) do - term.setCursorPos(7, i + 12) - term.write("- " .. currentLanguage.helpTips[v]) - end - end - - prompt({{"Back", w - 8, 7}}, "horizontal") -end - -local function run(path, lines, useArgs) - local ar = {} - if useArgs then - title("LuaIDE - Run " .. fs.getName(path)) - local s = centerRead(w - 13, fs.getName(path) .. " ") - for m in string.gmatch(s, "[^ \t]+") do ar[#ar + 1] = m:gsub("^%s*(.-)%s*$", "%1") end - end - - saveFile(path, lines) - term.setCursorBlink(false) - term.setBackgroundColor(colors.black) - term.setTextColor(colors.white) - term.clear() - term.setCursorPos(1, 1) - local err = currentLanguage.run(path, ar) - - term.setBackgroundColor(colors.black) - print("\n") - if err then - if isAdvanced() then term.setTextColor(colors.red) end - centerPrint("The program has crashed!") - end - term.setTextColor(colors.white) - centerPrint("Press any key to return to LuaIDE...") - while true do - local e = os.pullEvent() - if e == "key" then break end - end - - -- To prevent key from showing up in editor - os.queueEvent("") - os.pullEvent() - - if err then - if currentLanguage == languages.lua and err:find("]") then - err = fs.getName(path) .. err:sub(err:find("]", 1, true) + 1, -1) - end - - while true do - title("LuaIDE - Error!") - - term.setBackgroundColor(colors[theme.err]) - for i = 6, 8 do - term.setCursorPos(3, i) - term.write(string.rep(" ", w - 5)) - end - term.setCursorPos(4, 7) - term.write("The program has crashed!") - - term.setBackgroundColor(colors[theme.prompt]) - for i = 10, 14 do - term.setCursorPos(3, i) - term.write(string.rep(" ", w - 5)) - end - - local formattedErr = currentLanguage.parseError(err) - term.setCursorPos(4, 11) - term.write("Line: " .. formattedErr.line) - term.setCursorPos(4, 12) - term.write("Error:") - term.setCursorPos(5, 13) - - local a = formattedErr.display - local b = nil - if a:len() > w - 8 then - for i = a:len(), 1, -1 do - if a:sub(i, i) == " " then - b = a:sub(i + 1, -1) - a = a:sub(1, i) - break - end - end - end - - term.write(a) - if b then - term.setCursorPos(5, 14) - term.write(b) - end - - local opt = prompt({{"Error Help", w/2 - 15, 17}, {"Go To Line", w/2 + 2, 17}}, - "horizontal") - if opt == "Error Help" then - viewErrorHelp(formattedErr) - elseif opt == "Go To Line" then - -- To prevent key from showing up in editor - os.queueEvent("") - os.pullEvent() - - return "go to", tonumber(formattedErr.line) - end - end - end -end - - --- -------- Functions - -local function goto() - term.setBackgroundColor(colors[theme.backgroundHighlight]) - term.setCursorPos(2, 1) - term.clearLine() - term.write("Line: ") - local line = modRead({visibleLength = w - 2}) - - local num = tonumber(line) - if num and num > 0 then return num - else - term.setCursorPos(2, 1) - term.clearLine() - term.write("Not a line number!") - sleep(1.6) - return nil - end -end - -local function setsyntax() - local opts = { - "[Lua] Brainfuck None ", - " Lua [Brainfuck] None ", - " Lua Brainfuck [None]" - } - local sel = 1 - - term.setCursorBlink(false) - term.setBackgroundColor(colors[theme.backgroundHighlight]) - term.setCursorPos(2, 1) - term.clearLine() - term.write(opts[sel]) - while true do - local e, but, x, y = os.pullEvent("key") - if but == 203 then - sel = math.max(1, sel - 1) - term.setCursorPos(2, 1) - term.clearLine() - term.write(opts[sel]) - elseif but == 205 then - sel = math.min(#opts, sel + 1) - term.setCursorPos(2, 1) - term.clearLine() - term.write(opts[sel]) - elseif but == 28 then - if sel == 1 then currentLanguage = languages.lua - elseif sel == 2 then currentLanguage = languages.brainfuck - elseif sel == 3 then currentLanguage = languages.none end - term.setCursorBlink(true) - return - end - end -end - - --- -------- Re-Indenting - -local tabWidth = 2 - -local comments = {} -local strings = {} - -local increment = { - "if%s+.+%s+then%s*$", - "for%s+.+%s+do%s*$", - "while%s+.+%s+do%s*$", - "repeat%s*$", - "function%s+[a-zA-Z_0-9]\(.*\)%s*$" -} - -local decrement = { - "end", - "until%s+.+" -} - -local special = { - "else%s*$", - "elseif%s+.+%s+then%s*$" -} - -local function check(func) - for _, v in pairs(func) do - local cLineStart = v["lineStart"] - local cLineEnd = v["lineEnd"] - local cCharStart = v["charStart"] - local cCharEnd = v["charEnd"] - - if line >= cLineStart and line <= cLineEnd then - if line == cLineStart then return cCharStart < charNumb - elseif line == cLineEnd then return cCharEnd > charNumb - else return true end - end - end -end - -local function isIn(line, loc) - if check(comments) then return true end - if check(strings) then return true end - return false -end - -local function setComment(ls, le, cs, ce) - comments[#comments + 1] = {} - comments[#comments].lineStart = ls - comments[#comments].lineEnd = le - comments[#comments].charStart = cs - comments[#comments].charEnd = ce -end - -local function setString(ls, le, cs, ce) - strings[#strings + 1] = {} - strings[#strings].lineStart = ls - strings[#strings].lineEnd = le - strings[#strings].charStart = cs - strings[#strings].charEnd = ce -end - -local function map(contents) - local inCom = false - local inStr = false - - for i = 1, #contents do - if content[i]:find("%-%-%[%[") and not inStr and not inCom then - local cStart = content[i]:find("%-%-%[%[") - setComment(i, nil, cStart, nil) - inCom = true - elseif content[i]:find("%-%-%[=%[") and not inStr and not inCom then - local cStart = content[i]:find("%-%-%[=%[") - setComment(i, nil, cStart, nil) - inCom = true - elseif content[i]:find("%[%[") and not inStr and not inCom then - local cStart = content[i]:find("%[%[") - setString(i, nil, cStart, nil) - inStr = true - elseif content[i]:find("%[=%[") and not inStr and not inCom then - local cStart = content[i]:find("%[=%[") - setString(i, nil, cStart, nil) - inStr = true - end - - if content[i]:find("%]%]") and inStr and not inCom then - local cStart, cEnd = content[i]:find("%]%]") - strings[#strings].lineEnd = i - strings[#strings].charEnd = cEnd - inStr = false - elseif content[i]:find("%]=%]") and inStr and not inCom then - local cStart, cEnd = content[i]:find("%]=%]") - strings[#strings].lineEnd = i - strings[#strings].charEnd = cEnd - inStr = false - end - - if content[i]:find("%]%]") and not inStr and inCom then - local cStart, cEnd = content[i]:find("%]%]") - comments[#comments].lineEnd = i - comments[#comments].charEnd = cEnd - inCom = false - elseif content[i]:find("%]=%]") and not inStr and inCom then - local cStart, cEnd = content[i]:find("%]=%]") - comments[#comments].lineEnd = i - comments[#comments].charEnd = cEnd - inCom = false - end - - if content[i]:find("%-%-") and not inStr and not inCom then - local cStart = content[i]:find("%-%-") - setComment(i, i, cStart, -1) - elseif content[i]:find("'") and not inStr and not inCom then - local cStart, cEnd = content[i]:find("'") - local nextChar = content[i]:sub(cEnd + 1, string.len(content[i])) - local _, cEnd = nextChar:find("'") - setString(i, i, cStart, cEnd) - elseif content[i]:find('"') and not inStr and not inCom then - local cStart, cEnd = content[i]:find('"') - local nextChar = content[i]:sub(cEnd + 1, string.len(content[i])) - local _, cEnd = nextChar:find('"') - setString(i, i, cStart, cEnd) - end - end -end - -local function reindent(contents) - local err = nil - if currentLanguage ~= languages.lua then - err = "Cannot indent languages other than Lua!" - elseif currentLanguage.getCompilerErrors(table.concat(contents, "\n")).line ~= -1 then - err = "Cannot indent a program with errors!" - end - - if err then - term.setCursorBlink(false) - term.setCursorPos(2, 1) - term.setBackgroundColor(colors[theme.backgroundHighlight]) - term.clearLine() - term.write(err) - sleep(1.6) - return contents - end - - local new = {} - local level = 0 - for k, v in pairs(contents) do - local incrLevel = false - local foundIncr = false - for _, incr in pairs(increment) do - if v:find(incr) and not isIn(k, v:find(incr)) then - incrLevel = true - end - if v:find(incr:sub(1, -2)) and not isIn(k, v:find(incr)) then - foundIncr = true - end - end - - local decrLevel = false - if not incrLevel then - for _, decr in pairs(decrement) do - if v:find(decr) and not isIn(k, v:find(decr)) and not foundIncr then - level = math.max(0, level - 1) - decrLevel = true - end - end - end - - if not decrLevel then - for _, sp in pairs(special) do - if v:find(sp) and not isIn(k, v:find(sp)) then - incrLevel = true - level = math.max(0, level - 1) - end - end - end - - new[k] = string.rep(" ", level * tabWidth) .. v - if incrLevel then level = level + 1 end - end - - return new -end - - --- -------- Menu - -local menu = { - [1] = {"File", --- "About", --- "Settings", --- "", - "New File ^+N", - "Open File ^+O", - "Save File ^+S", - "Close ^+W", - "Print ^+P", - "Quit ^+Q" - }, [2] = {"Edit", - "Cut Line ^+X", - "Copy Line ^+C", - "Paste Line ^+V", - "Delete Line", - "Clear Line" - }, [3] = {"Functions", - "Go To Line ^+G", - "Re-Indent ^+I", - "Set Syntax ^+E", - "Start of Line ^+<", - "End of Line ^+>" - }, [4] = {"Run", - "Run Program ^+R", - "Run w/ Args ^+Shift+R" - } -} - -local shortcuts = { - -- File - ["ctrl n"] = "New File ^+N", - ["ctrl o"] = "Open File ^+O", - ["ctrl s"] = "Save File ^+S", - ["ctrl w"] = "Close ^+W", - ["ctrl p"] = "Print ^+P", - ["ctrl q"] = "Quit ^+Q", - - -- Edit - ["ctrl x"] = "Cut Line ^+X", - ["ctrl c"] = "Copy Line ^+C", - ["ctrl v"] = "Paste Line ^+V", - - -- Functions - ["ctrl g"] = "Go To Line ^+G", - ["ctrl i"] = "Re-Indent ^+I", - ["ctrl e"] = "Set Syntax ^+E", - ["ctrl 203"] = "Start of Line ^+<", - ["ctrl 205"] = "End of Line ^+>", - - -- Run - ["ctrl r"] = "Run Program ^+R", - ["ctrl shift r"] = "Run w/ Args ^+Shift+R" -} - -local menuFunctions = { - -- File --- ["About"] = function() end, --- ["Settings"] = function() end, - ["New File ^+N"] = function(path, lines) saveFile(path, lines) return "new" end, - ["Open File ^+O"] = function(path, lines) saveFile(path, lines) return "open" end, - ["Save File ^+S"] = function(path, lines) saveFile(path, lines) end, - ["Close ^+W"] = function(path, lines) saveFile(path, lines) return "menu" end, - ["Print ^+P"] = function(path, lines) saveFile(path, lines) return nil end, - ["Quit ^+Q"] = function(path, lines) saveFile(path, lines) return "exit" end, - - -- Edit - ["Cut Line ^+X"] = function(path, lines, y) - clipboard = lines[y] table.remove(lines, y) return nil, lines end, - ["Copy Line ^+C"] = function(path, lines, y) clipboard = lines[y] end, - ["Paste Line ^+V"] = function(path, lines, y) - if clipboard then table.insert(lines, y, clipboard) end return nil, lines end, - ["Delete Line"] = function(path, lines, y) table.remove(lines, y) return nil, lines end, - ["Clear Line"] = function(path, lines, y) lines[y] = "" return nil, lines, "cursor" end, - - -- Functions - ["Go To Line ^+G"] = function() return nil, "go to", goto() end, - ["Re-Indent ^+I"] = function(path, lines) - local a = reindent(lines) saveFile(path, lines) return nil, a - end, - ["Set Syntax ^+E"] = function(path, lines) - setsyntax() - if currentLanguage == languages.brainfuck and lines[1] ~= "-- Syntax: Brainfuck" then - table.insert(lines, 1, "-- Syntax: Brainfuck") - return nil, lines - end - end, - ["Start of Line ^+<"] = function() os.queueEvent("key", 199) end, - ["End of Line ^+>"] = function() os.queueEvent("key", 207) end, - - -- Run - ["Run Program ^+R"] = function(path, lines) - saveFile(path, lines) - return nil, run(path, lines, false) - end, - ["Run w/ Args ^+Shift+R"] = function(path, lines) - saveFile(path, lines) - return nil, run(path, lines, true) - end, -} - -local function drawMenu(open) - term.setCursorPos(1, 1) - term.setTextColor(colors[theme.textColor]) - term.setBackgroundColor(colors[theme.backgroundHighlight]) - term.clearLine() - local curX = 0 - for _, v in pairs(menu) do - term.setCursorPos(3 + curX, 1) - term.write(v[1]) - curX = curX + v[1]:len() + 3 - end - - if open then - local it = {} - local x = 1 - for _, v in pairs(menu) do - if open == v[1] then - it = v - break - end - x = x + v[1]:len() + 3 - end - x = x + 1 - - local items = {} - for i = 2, #it do - table.insert(items, it[i]) - end - - local len = 1 - for _, v in pairs(items) do if v:len() + 2 > len then len = v:len() + 2 end end - - for i, v in ipairs(items) do - term.setCursorPos(x, i + 1) - term.write(string.rep(" ", len)) - term.setCursorPos(x + 1, i + 1) - term.write(v) - end - term.setCursorPos(x, #items + 2) - term.write(string.rep(" ", len)) - return items, len - end -end - -local function triggerMenu(cx, cy) - -- Determine clicked menu - local curX = 0 - local open = nil - for _, v in pairs(menu) do - if cx >= curX + 3 and cx <= curX + v[1]:len() + 2 then - open = v[1] - break - end - curX = curX + v[1]:len() + 3 - end - local menux = curX + 2 - if not open then return false end - - -- Flash menu item - term.setCursorBlink(false) - term.setCursorPos(menux, 1) - term.setBackgroundColor(colors[theme.background]) - term.write(string.rep(" ", open:len() + 2)) - term.setCursorPos(menux + 1, 1) - term.write(open) - sleep(0.1) - local items, len = drawMenu(open) - - local ret = true - - -- Pull events on menu - local ox, oy = term.getCursorPos() - while type(ret) ~= "string" do - local e, but, x, y = os.pullEvent() - if e == "mouse_click" then - -- If clicked outside menu - if x < menux - 1 or x > menux + len - 1 then break - elseif y > #items + 2 then break - elseif y == 1 then break end - - for i, v in ipairs(items) do - if y == i + 1 and x >= menux and x <= menux + len - 2 then - -- Flash when clicked - term.setCursorPos(menux, y) - term.setBackgroundColor(colors[theme.background]) - term.write(string.rep(" ", len)) - term.setCursorPos(menux + 1, y) - term.write(v) - sleep(0.1) - drawMenu(open) - - -- Return item - ret = v - break - end - end - end - end - - term.setCursorPos(ox, oy) - term.setCursorBlink(true) - return ret -end - - --- -------- Editing - -local standardsCompletions = { - "if%s+.+%s+then%s*$", - "for%s+.+%s+do%s*$", - "while%s+.+%s+do%s*$", - "repeat%s*$", - "function%s+[a-zA-Z_0-9]?\(.*\)%s*$", - "=%s*function%s*\(.*\)%s*$", - "else%s*$", - "elseif%s+.+%s+then%s*$" -} - -local liveCompletions = { - ["("] = ")", - ["{"] = "}", - ["["] = "]", - ["\""] = "\"", - ["'"] = "'", -} - -local x, y = 0, 0 -local edw, edh = 0, h - 1 -local offx, offy = 0, 1 -local scrollx, scrolly = 0, 0 -local lines = {} -local liveErr = currentLanguage.parseError(nil) -local displayCode = true -local lastEventClock = os.clock() - -local function attemptToHighlight(line, regex, col) - local match = string.match(line, regex) - if match then - if type(col) == "number" then term.setTextColor(col) - elseif type(col) == "function" then term.setTextColor(col(match)) end - term.write(match) - term.setTextColor(colors[theme.textColor]) - return line:sub(match:len() + 1, -1) - end - return nil -end - -local function writeHighlighted(line) - if currentLanguage == languages.lua then - while line:len() > 0 do - line = attemptToHighlight(line, "^%-%-%[%[.-%]%]", colors[theme.comment]) or - attemptToHighlight(line, "^%-%-.*", colors[theme.comment]) or - attemptToHighlight(line, "^\".*[^\\]\"", colors[theme.string]) or - attemptToHighlight(line, "^\'.*[^\\]\'", colors[theme.string]) or - attemptToHighlight(line, "^%[%[.-%]%]", colors[theme.string]) or - attemptToHighlight(line, "^[%w_]+", function(match) - if currentLanguage.keywords[match] then - return colors[theme[currentLanguage.keywords[match]]] - end - return colors[theme.textColor] - end) or - attemptToHighlight(line, "^[^%w_]", colors[theme.textColor]) - end - else term.write(line) end -end - -local function draw() - -- Menu - term.setTextColor(colors[theme.textColor]) - term.setBackgroundColor(colors[theme.editorBackground]) - term.clear() - drawMenu() - - -- Line numbers - offx, offy = tostring(#lines):len() + 1, 1 - edw, edh = w - offx, h - 1 - - -- Draw text - for i = 1, edh do - local a = lines[scrolly + i] - if a then - local ln = string.rep(" ", offx - 1 - tostring(scrolly + i):len()) .. tostring(scrolly + i) - local l = a:sub(scrollx + 1, edw + scrollx + 1) - ln = ln .. ":" - - if liveErr.line == scrolly + i then ln = string.rep(" ", offx - 2) .. "!:" end - - term.setCursorPos(1, i + offy) - term.setBackgroundColor(colors[theme.editorBackground]) - if scrolly + i == y then - if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then - term.setBackgroundColor(colors[theme.editorErrorHighlight]) - else term.setBackgroundColor(colors[theme.editorLineHightlight]) end - term.clearLine() - elseif scrolly + i == liveErr.line then - term.setBackgroundColor(colors[theme.editorError]) - term.clearLine() - end - - term.setCursorPos(1 - scrollx + offx, i + offy) - if scrolly + i == y then - if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then - term.setBackgroundColor(colors[theme.editorErrorHighlight]) - else term.setBackgroundColor(colors[theme.editorLineHightlight]) end - elseif scrolly + i == liveErr.line then term.setBackgroundColor(colors[theme.editorError]) - else term.setBackgroundColor(colors[theme.editorBackground]) end - if scrolly + i == liveErr.line then - if displayCode then term.write(a) - else term.write(liveErr.display) end - else writeHighlighted(a) end - - term.setCursorPos(1, i + offy) - if scrolly + i == y then - if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then - term.setBackgroundColor(colors[theme.editorError]) - else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end - elseif scrolly + i == liveErr.line then - term.setBackgroundColor(colors[theme.editorErrorHighlight]) - else term.setBackgroundColor(colors[theme.editorLineNumbers]) end - term.write(ln) - end - end - term.setCursorPos(x - scrollx + offx, y - scrolly + offy) -end - -local function drawLine(...) - local ls = {...} - offx = tostring(#lines):len() + 1 - for _, ly in pairs(ls) do - local a = lines[ly] - if a then - local ln = string.rep(" ", offx - 1 - tostring(ly):len()) .. tostring(ly) - local l = a:sub(scrollx + 1, edw + scrollx + 1) - ln = ln .. ":" - - if liveErr.line == ly then ln = string.rep(" ", offx - 2) .. "!:" end - - term.setCursorPos(1, (ly - scrolly) + offy) - term.setBackgroundColor(colors[theme.editorBackground]) - if ly == y then - if ly == liveErr.line and os.clock() - lastEventClock > 3 then - term.setBackgroundColor(colors[theme.editorErrorHighlight]) - else term.setBackgroundColor(colors[theme.editorLineHightlight]) end - elseif ly == liveErr.line then - term.setBackgroundColor(colors[theme.editorError]) - end - term.clearLine() - - term.setCursorPos(1 - scrollx + offx, (ly - scrolly) + offy) - if ly == y then - if ly == liveErr.line and os.clock() - lastEventClock > 3 then - term.setBackgroundColor(colors[theme.editorErrorHighlight]) - else term.setBackgroundColor(colors[theme.editorLineHightlight]) end - elseif ly == liveErr.line then term.setBackgroundColor(colors[theme.editorError]) - else term.setBackgroundColor(colors[theme.editorBackground]) end - if ly == liveErr.line then - if displayCode then term.write(a) - else term.write(liveErr.display) end - else writeHighlighted(a) end - - term.setCursorPos(1, (ly - scrolly) + offy) - if ly == y then - if ly == liveErr.line and os.clock() - lastEventClock > 3 then - term.setBackgroundColor(colors[theme.editorError]) - else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end - elseif ly == liveErr.line then - term.setBackgroundColor(colors[theme.editorErrorHighlight]) - else term.setBackgroundColor(colors[theme.editorLineNumbers]) end - term.write(ln) - end - end - term.setCursorPos(x - scrollx + offx, y - scrolly + offy) -end - -local function cursorLoc(x, y, force) - local sx, sy = x - scrollx, y - scrolly - local redraw = false - if sx < 1 then - scrollx = x - 1 - sx = 1 - redraw = true - elseif sx > edw then - scrollx = x - edw - sx = edw - redraw = true - end if sy < 1 then - scrolly = y - 1 - sy = 1 - redraw = true - elseif sy > edh then - scrolly = y - edh - sy = edh - redraw = true - end if redraw or force then draw() end - term.setCursorPos(sx + offx, sy + offy) -end - -local function executeMenuItem(a, path) - if type(a) == "string" and menuFunctions[a] then - local opt, nl, gtln = menuFunctions[a](path, lines, y) - if type(opt) == "string" then term.setCursorBlink(false) return opt end - if type(nl) == "table" then - if #lines < 1 then table.insert(lines, "") end - y = math.min(y, #lines) - x = math.min(x, lines[y]:len() + 1) - lines = nl - elseif type(nl) == "string" then - if nl == "go to" and gtln then - x, y = 1, math.min(#lines, gtln) - cursorLoc(x, y) - end - end - end - term.setCursorBlink(true) - draw() - term.setCursorPos(x - scrollx + offx, y - scrolly + offy) -end - -local function edit(path) - -- Variables - x, y = 1, 1 - offx, offy = 0, 1 - scrollx, scrolly = 0, 0 - lines = loadFile(path) - if not lines then return "menu" end - - -- Enable brainfuck - if lines[1] == "-- Syntax: Brainfuck" then - currentLanguage = languages.brainfuck - end - - -- Clocks - local autosaveClock = os.clock() - local scrollClock = os.clock() -- To prevent redraw flicker - local liveErrorClock = os.clock() - local hasScrolled = false - - -- Draw - draw() - term.setCursorPos(x + offx, y + offy) - term.setCursorBlink(true) - - -- Main loop - local tid = os.startTimer(3) - while true do - local e, key, cx, cy = os.pullEvent() - if e == "key" and allowEditorEvent then - if key == 200 and y > 1 then - -- Up - x, y = math.min(x, lines[y - 1]:len() + 1), y - 1 - drawLine(y, y + 1) - cursorLoc(x, y) - elseif key == 208 and y < #lines then - -- Down - x, y = math.min(x, lines[y + 1]:len() + 1), y + 1 - drawLine(y, y - 1) - cursorLoc(x, y) - elseif key == 203 and x > 1 then - -- Left - x = x - 1 - local force = false - if y - scrolly + offy < offy + 1 then force = true end - cursorLoc(x, y, force) - elseif key == 205 and x < lines[y]:len() + 1 then - -- Right - x = x + 1 - local force = false - if y - scrolly + offy < offy + 1 then force = true end - cursorLoc(x, y, force) - elseif (key == 28 or key == 156) and (displayCode and true or y + scrolly - 1 == - liveErr.line) then - -- Enter - local f = nil - for _, v in pairs(standardsCompletions) do - if lines[y]:find(v) and x == #lines[y] + 1 then f = v end - end - - local _, spaces = lines[y]:find("^[ ]+") - if not spaces then spaces = 0 end - if f then - table.insert(lines, y + 1, string.rep(" ", spaces + 2)) - if not f:find("else", 1, true) and not f:find("elseif", 1, true) then - table.insert(lines, y + 2, string.rep(" ", spaces) .. - (f:find("repeat", 1, true) and "until " or f:find("{", 1, true) and "}" or - "end")) - end - x, y = spaces + 3, y + 1 - cursorLoc(x, y, true) - else - local oldLine = lines[y] - - lines[y] = lines[y]:sub(1, x - 1) - table.insert(lines, y + 1, string.rep(" ", spaces) .. oldLine:sub(x, -1)) - - x, y = spaces + 1, y + 1 - cursorLoc(x, y, true) - end - elseif key == 14 and (displayCode and true or y + scrolly - 1 == liveErr.line) then - -- Backspace - if x > 1 then - local f = false - for k, v in pairs(liveCompletions) do - if lines[y]:sub(x - 1, x - 1) == k then f = true end - end - - lines[y] = lines[y]:sub(1, x - 2) .. lines[y]:sub(x + (f and 1 or 0), -1) - drawLine(y) - x = x - 1 - cursorLoc(x, y) - elseif y > 1 then - local prevLen = lines[y - 1]:len() + 1 - lines[y - 1] = lines[y - 1] .. lines[y] - table.remove(lines, y) - x, y = prevLen, y - 1 - cursorLoc(x, y, true) - end - elseif key == 199 then - -- Home - x = 1 - local force = false - if y - scrolly + offy < offy + 1 then force = true end - cursorLoc(x, y, force) - elseif key == 207 then - -- End - x = lines[y]:len() + 1 - local force = false - if y - scrolly + offy < offy + 1 then force = true end - cursorLoc(x, y, force) - elseif key == 211 and (displayCode and true or y + scrolly - 1 == liveErr.line) then - -- Forward Delete - if x < lines[y]:len() + 1 then - lines[y] = lines[y]:sub(1, x - 1) .. lines[y]:sub(x + 1) - local force = false - if y - scrolly + offy < offy + 1 then force = true end - drawLine(y) - cursorLoc(x, y, force) - elseif y < #lines then - lines[y] = lines[y] .. lines[y + 1] - table.remove(lines, y + 1) - draw() - cursorLoc(x, y) - end - elseif key == 15 and (displayCode and true or y + scrolly - 1 == liveErr.line) then - -- Tab - lines[y] = string.rep(" ", tabWidth) .. lines[y] - x = x + 2 - local force = false - if y - scrolly + offy < offy + 1 then force = true end - drawLine(y) - cursorLoc(x, y, force) - elseif key == 201 then - -- Page up - y = math.min(math.max(y - edh, 1), #lines) - x = math.min(lines[y]:len() + 1, x) - cursorLoc(x, y, true) - elseif key == 209 then - -- Page down - y = math.min(math.max(y + edh, 1), #lines) - x = math.min(lines[y]:len() + 1, x) - cursorLoc(x, y, true) - end - elseif e == "char" and allowEditorEvent and (displayCode and true or - y + scrolly - 1 == liveErr.line) then - local shouldIgnore = false - for k, v in pairs(liveCompletions) do - if key == v and lines[y]:find(k, 1, true) and lines[y]:sub(x, x) == v then - shouldIgnore = true - end - end - - local addOne = false - if not shouldIgnore then - for k, v in pairs(liveCompletions) do - if key == k and lines[y]:sub(x, x) ~= k then key = key .. v addOne = true end - end - lines[y] = lines[y]:sub(1, x - 1) .. key .. lines[y]:sub(x, -1) - end - - x = x + (addOne and 1 or key:len()) - local force = false - if y - scrolly + offy < offy + 1 then force = true end - drawLine(y) - cursorLoc(x, y, force) - elseif e == "mouse_click" and key == 1 then - if cy > 1 then - if cx <= offx and cy - offy == liveErr.line - scrolly then - displayCode = not displayCode - drawLine(liveErr.line) - else - local oldy = y - y = math.min(math.max(scrolly + cy - offy, 1), #lines) - x = math.min(math.max(scrollx + cx - offx, 1), lines[y]:len() + 1) - if oldy ~= y then drawLine(oldy, y) end - cursorLoc(x, y) - end - else - local a = triggerMenu(cx, cy) - if a then - local opt = executeMenuItem(a, path) - if opt then return opt end - end - end - elseif e == "shortcut" then - local a = shortcuts[key .. " " .. cx] - if a then - local parent = nil - local curx = 0 - for i, mv in ipairs(menu) do - for _, iv in pairs(mv) do - if iv == a then - parent = menu[i][1] - break - end - end - if parent then break end - curx = curx + mv[1]:len() + 3 - end - local menux = curx + 2 - - -- Flash menu item - term.setCursorBlink(false) - term.setCursorPos(menux, 1) - term.setBackgroundColor(colors[theme.background]) - term.write(string.rep(" ", parent:len() + 2)) - term.setCursorPos(menux + 1, 1) - term.write(parent) - sleep(0.1) - drawMenu() - - -- Execute item - local opt = executeMenuItem(a, path) - if opt then return opt end - end - elseif e == "mouse_scroll" then - if key == -1 and scrolly > 0 then - scrolly = scrolly - 1 - if os.clock() - scrollClock > 0.0005 then - draw() - term.setCursorPos(x - scrollx + offx, y - scrolly + offy) - end - scrollClock = os.clock() - hasScrolled = true - elseif key == 1 and scrolly < #lines - edh then - scrolly = scrolly + 1 - if os.clock() - scrollClock > 0.0005 then - draw() - term.setCursorPos(x - scrollx + offx, y - scrolly + offy) - end - scrollClock = os.clock() - hasScrolled = true - end - elseif e == "timer" and key == tid then - drawLine(y) - tid = os.startTimer(3) - end - - -- Draw - if hasScrolled and os.clock() - scrollClock > 0.1 then - draw() - term.setCursorPos(x - scrollx + offx, y - scrolly + offy) - hasScrolled = false - end - - -- Autosave - if os.clock() - autosaveClock > autosaveInterval then - saveFile(path, lines) - autosaveClock = os.clock() - end - - -- Errors - if os.clock() - liveErrorClock > 1 then - local prevLiveErr = liveErr - liveErr = currentLanguage.parseError(nil) - local code = "" - for _, v in pairs(lines) do code = code .. v .. "\n" end - - liveErr = currentLanguage.getCompilerErrors(code) - liveErr.line = math.min(liveErr.line - 2, #lines) - if liveErr ~= prevLiveErr then draw() end - liveErrorClock = os.clock() - end - end - - return "menu" -end - - --- -------- Open File - -local function newFile() - local wid = w - 13 - - -- Get name - title("Lua IDE - New File") - local name = centerRead(wid, "/") - if not name or name == "" then return "menu" end - name = "/" .. name - - -- Clear - title("Lua IDE - New File") - term.setTextColor(colors[theme.textColor]) - term.setBackgroundColor(colors[theme.promptHighlight]) - for i = 8, 10 do - term.setCursorPos(w/2 - wid/2, i) - term.write(string.rep(" ", wid)) - end - term.setCursorPos(1, 9) - if fs.isDir(name) then - centerPrint("Cannot Edit a Directory!") - sleep(1.6) - return "menu" - elseif fs.exists(name) then - centerPrint("File Already Exists!") - local opt = prompt({{"Open", w/2 - 9, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal") - if opt == "Open" then return "edit", name - elseif opt == "Cancel" then return "menu" end - else return "edit", name end -end - -local function openFile() - local wid = w - 13 - - -- Get name - title("Lua IDE - Open File") - local name = centerRead(wid, "/") - if not name or name == "" then return "menu" end - name = "/" .. name - - -- Clear - title("Lua IDE - New File") - term.setTextColor(colors[theme.textColor]) - term.setBackgroundColor(colors[theme.promptHighlight]) - for i = 8, 10 do - term.setCursorPos(w/2 - wid/2, i) - term.write(string.rep(" ", wid)) - end - term.setCursorPos(1, 9) - if fs.isDir(name) then - centerPrint("Cannot Open a Directory!") - sleep(1.6) - return "menu" - elseif not fs.exists(name) then - centerPrint("File Doesn't Exist!") - local opt = prompt({{"Create", w/2 - 11, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal") - if opt == "Create" then return "edit", name - elseif opt == "Cancel" then return "menu" end - else return "edit", name end -end - - --- -------- Settings - -local function update() - local function draw(status) - title("LuaIDE - Update") - term.setBackgroundColor(colors[theme.prompt]) - term.setTextColor(colors[theme.textColor]) - for i = 8, 10 do - term.setCursorPos(w/2 - (status:len() + 4), i) - write(string.rep(" ", status:len() + 4)) - end - term.setCursorPos(w/2 - (status:len() + 4), 9) - term.write(" - " .. status .. " ") - - term.setBackgroundColor(colors[theme.errHighlight]) - for i = 8, 10 do - term.setCursorPos(w/2 + 2, i) - term.write(string.rep(" ", 10)) - end - term.setCursorPos(w/2 + 2, 9) - term.write(" > Cancel ") - end - - if not http then - draw("HTTP API Disabled!") - sleep(1.6) - return "settings" - end - - draw("Updating...") - local tID = os.startTimer(10) - http.request(updateURL) - while true do - local e, but, x, y = os.pullEvent() - if (e == "key" and but == 28) or - (e == "mouse_click" and x >= w/2 + 2 and x <= w/2 + 12 and y == 9) then - draw("Cancelled") - sleep(1.6) - break - elseif e == "http_success" and but == updateURL then - local new = x.readAll() - local curf = io.open(ideLocation, "r") - local cur = curf:read("*a") - curf:close() - - if cur ~= new then - draw("Update Found") - sleep(1.6) - local f = io.open(ideLocation, "w") - f:write(new) - f:close() - - draw("Click to Exit") - while true do - local e = os.pullEvent() - if e == "mouse_click" or (not isAdvanced() and e == "key") then break end - end - return "exit" - else - draw("No Updates Found!") - sleep(1.6) - break - end - elseif e == "http_failure" or (e == "timer" and but == tID) then - draw("Update Failed!") - sleep(1.6) - break - end - end - - return "settings" -end - -local function changeTheme() - title("LuaIDE - Theme") - - if isAdvanced() then - local disThemes = {"Back"} - for _, v in pairs(availableThemes) do table.insert(disThemes, v[1]) end - local t = scrollingPrompt(disThemes) - local url = nil - for _, v in pairs(availableThemes) do if v[1] == t then url = v[2] end end - - if not url then return "settings" end - if t == "Dawn (Default)" then - term.setBackgroundColor(colors[theme.backgroundHighlight]) - term.setCursorPos(3, 3) - term.clearLine() - term.write("LuaIDE - Loaded Theme!") - sleep(1.6) - - fs.delete(themeLocation) - theme = defaultTheme - return "menu" - end - - term.setBackgroundColor(colors[theme.backgroundHighlight]) - term.setCursorPos(3, 3) - term.clearLine() - term.write("LuaIDE - Downloading...") - - fs.delete("/.LuaIDE_temp_theme_file") - download(url, "/.LuaIDE_temp_theme_file") - local a = loadTheme("/.LuaIDE_temp_theme_file") - - term.setCursorPos(3, 3) - term.clearLine() - if a then - term.write("LuaIDE - Loaded Theme!") - fs.delete(themeLocation) - fs.move("/.LuaIDE_temp_theme_file", themeLocation) - theme = a - sleep(1.6) - return "menu" - end - - term.write("LuaIDE - Could Not Load Theme!") - fs.delete("/.LuaIDE_temp_theme_file") - sleep(1.6) - return "settings" - else - term.setCursorPos(1, 8) - centerPrint("Themes are not available on") - centerPrint("normal computers!") - end -end - -local function settings() - title("LuaIDE - Settings") - - local opt = prompt({{"Change Theme", w/2 - 17, 8}, {"Return to Menu", w/2 - 22, 13}, - {"Check for Updates", w/2 + 2, 8}, {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err], - highlight = colors[theme.errHighlight]}}, "vertical", true) - if opt == "Change Theme" then return changeTheme() - elseif opt == "Check for Updates" then return update() - elseif opt == "Return to Menu" then return "menu" - elseif opt == "Exit IDE" then return "exit" end -end - - --- -------- Menu - -local function menu() - title("Welcome to LuaIDE " .. version) - - local opt = prompt({{"New File", w/2 - 13, 8}, {"Open File", w/2 - 14, 13}, - {"Settings", w/2 + 2, 8}, {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err], - highlight = colors[theme.errHighlight]}}, "vertical", true) - if opt == "New File" then return "new" - elseif opt == "Open File" then return "open" - elseif opt == "Settings" then return "settings" - elseif opt == "Exit IDE" then return "exit" end -end - - --- -------- Main - -local function main(arguments) - local opt, data = "menu", nil - - -- Check arguments - if type(arguments) == "table" and #arguments > 0 then - local f = "/" .. shell.resolve(arguments[1]) - if fs.isDir(f) then print("Cannot edit a directory.") end - opt, data = "edit", f - end - - -- Main run loop - while true do - -- Menu - if opt == "menu" then opt = menu() end - - -- Other - if opt == "new" then opt, data = newFile() - elseif opt == "open" then opt, data = openFile() - elseif opt == "settings" then opt = settings() - end if opt == "exit" then break end - - -- Edit - if opt == "edit" and data then opt = edit(data) end - end -end - --- Load Theme -if fs.exists(themeLocation) then theme = loadTheme(themeLocation) end -if not theme and isAdvanced() then theme = defaultTheme -elseif not theme then theme = normalTheme end - --- Run -local _, err = pcall(function() - parallel.waitForAny(function() main(arguments) end, monitorKeyboardShortcuts) -end) - --- Catch errors -if err and not err:find("Terminated") then - term.setCursorBlink(false) - title("LuaIDE - Crash! D:") - - term.setBackgroundColor(colors[theme.err]) - for i = 6, 8 do - term.setCursorPos(5, i) - term.write(string.rep(" ", 36)) - end - term.setCursorPos(6, 7) - term.write("LuaIDE Has Crashed! D:") - - term.setBackgroundColor(colors[theme.background]) - term.setCursorPos(2, 10) - print(err) - - term.setBackgroundColor(colors[theme.prompt]) - local _, cy = term.getCursorPos() - for i = cy + 1, cy + 4 do - term.setCursorPos(5, i) - term.write(string.rep(" ", 36)) - end - term.setCursorPos(6, cy + 2) - term.write("Please report this error to") - term.setCursorPos(6, cy + 3) - term.write("GravityScore! ") - - term.setBackgroundColor(colors[theme.background]) - if isAdvanced() then centerPrint("Click to Exit...", h - 1) - else centerPrint("Press Any Key to Exit...", h - 1) end - while true do - local e = os.pullEvent() - if e == "mouse_click" or (not isAdvanced() and e == "key") then break end - end - - -- Prevent key from being shown - os.queueEvent("") - os.pullEvent() -end - --- Exit -term.setBackgroundColor(colors.black) -term.setTextColor(colors.white) -term.clear() -term.setCursorPos(1, 1) -centerPrint("Thank You for Using Lua IDE " .. version) -centerPrint("Made by GravityScore")
\ No newline at end of file |
