mirror of
https://github.com/CCLeonOS/LeonOS.git
synced 2026-03-03 15:17:01 +00:00
230 lines
5.1 KiB
Lua
230 lines
5.1 KiB
Lua
|
|
-- editor
|
||
|
|
|
||
|
|
local args = {...}
|
||
|
|
|
||
|
|
local rc = require("rc")
|
||
|
|
local keys = require("keys")
|
||
|
|
local term = require("term")
|
||
|
|
local shell = require("shell")
|
||
|
|
local colors = require("colors")
|
||
|
|
local settings = require("settings")
|
||
|
|
local textutils = require("textutils")
|
||
|
|
|
||
|
|
local scroll_offset = settings.get("edit.scroll_offset")
|
||
|
|
|
||
|
|
local state = {
|
||
|
|
file = args[1] or ".new",
|
||
|
|
unsaved = false,
|
||
|
|
scroll = 0,
|
||
|
|
hscroll = 0,
|
||
|
|
lines = {""},
|
||
|
|
status = "Press Control for menu",
|
||
|
|
cx = 1,
|
||
|
|
cy = 1,
|
||
|
|
}
|
||
|
|
|
||
|
|
if args[1] then
|
||
|
|
local path = shell.resolve(args[1])
|
||
|
|
local handle = io.open(path)
|
||
|
|
state.file = path
|
||
|
|
|
||
|
|
if handle then
|
||
|
|
state.lines = {}
|
||
|
|
|
||
|
|
for line in handle:lines() do
|
||
|
|
state.lines[#state.lines+1] = line
|
||
|
|
end
|
||
|
|
|
||
|
|
handle:close()
|
||
|
|
|
||
|
|
if not state.lines[1] then state.lines[1] = "" end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function redraw()
|
||
|
|
local w, h = term.getSize()
|
||
|
|
|
||
|
|
for i=1, h - 1, 1 do
|
||
|
|
local to_write = state.lines[state.scroll + i] or ""
|
||
|
|
if state.cx > w then
|
||
|
|
to_write = to_write:sub(state.cx - (w-1))
|
||
|
|
end
|
||
|
|
term.at(1, i).clearLine()
|
||
|
|
term.write(to_write)
|
||
|
|
end
|
||
|
|
|
||
|
|
term.at(1, h).clearLine()
|
||
|
|
textutils.coloredWrite(colors.yellow, state.status, colors.white)
|
||
|
|
|
||
|
|
term.setCursorPos(math.min(w, state.cx), state.cy - state.scroll)
|
||
|
|
end
|
||
|
|
|
||
|
|
local run, menu = true, false
|
||
|
|
|
||
|
|
local function save()
|
||
|
|
if state.file == ".new" then
|
||
|
|
local _, h = term.getSize()
|
||
|
|
term.setCursorPos(1, h)
|
||
|
|
textutils.coloredWrite(colors.yellow, "filename: ", colors.white)
|
||
|
|
state.file = term.read()
|
||
|
|
end
|
||
|
|
|
||
|
|
local handle, err = io.open(state.file, "w")
|
||
|
|
if not handle then
|
||
|
|
state.status = err
|
||
|
|
else
|
||
|
|
for i=1, #state.lines, 1 do
|
||
|
|
handle:write(state.lines[i] .. "\n")
|
||
|
|
end
|
||
|
|
handle:close()
|
||
|
|
state.status = "Saved to " .. state.file
|
||
|
|
state.unsaved = false
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function processMenuInput()
|
||
|
|
local event, id = rc.pullEvent()
|
||
|
|
|
||
|
|
if event == "char" then
|
||
|
|
if id:lower() == "e" then
|
||
|
|
if state.unsaved and menu ~= 2 then
|
||
|
|
state.status = "Lose unsaved work? E:yes C:no"
|
||
|
|
menu = 2
|
||
|
|
else
|
||
|
|
term.at(1, 1).clear()
|
||
|
|
run = false
|
||
|
|
end
|
||
|
|
|
||
|
|
elseif id:lower() == "c" and menu == 2 then
|
||
|
|
menu = false
|
||
|
|
|
||
|
|
elseif id:lower() == "s" then
|
||
|
|
save()
|
||
|
|
menu = false
|
||
|
|
end
|
||
|
|
|
||
|
|
elseif event == "key" then
|
||
|
|
id = keys.getName(id)
|
||
|
|
|
||
|
|
if id == "leftCtrl" or id == "rightCtrl" then
|
||
|
|
state.status = "Press Control for menu"
|
||
|
|
menu = false
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function processInput()
|
||
|
|
local event, id = rc.pullEvent()
|
||
|
|
|
||
|
|
local _, h = term.getSize()
|
||
|
|
|
||
|
|
if event == "char" then
|
||
|
|
local line = state.lines[state.cy]
|
||
|
|
state.unsaved = true
|
||
|
|
if state.cx > #line then
|
||
|
|
line = line .. id
|
||
|
|
|
||
|
|
elseif state.cx == 1 then
|
||
|
|
line = id .. line
|
||
|
|
|
||
|
|
else
|
||
|
|
line = line:sub(0, state.cx-1)..id..line:sub(state.cx)
|
||
|
|
end
|
||
|
|
state.cx = state.cx + 1
|
||
|
|
|
||
|
|
state.lines[state.cy] = line
|
||
|
|
|
||
|
|
elseif event == "key" then
|
||
|
|
id = keys.getName(id)
|
||
|
|
|
||
|
|
if id == "backspace" then
|
||
|
|
local line = state.lines[state.cy]
|
||
|
|
state.unsaved = true
|
||
|
|
if state.cx == 1 and state.cy > 1 then
|
||
|
|
local previous = table.remove(state.lines, state.cy - 1)
|
||
|
|
state.cy = state.cy - 1
|
||
|
|
state.cx = #previous + 1
|
||
|
|
line = previous .. line
|
||
|
|
else
|
||
|
|
if #line > 0 then
|
||
|
|
if state.cx > #line then
|
||
|
|
state.cx = state.cx - 1
|
||
|
|
line = line:sub(1, -2)
|
||
|
|
|
||
|
|
elseif state.cx > 1 then
|
||
|
|
line = line:sub(0, state.cx - 2) .. line:sub(state.cx)
|
||
|
|
state.cx = state.cx - 1
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
end
|
||
|
|
state.lines[state.cy] = line
|
||
|
|
|
||
|
|
elseif id == "enter" then
|
||
|
|
if state.cx == 1 then
|
||
|
|
table.insert(state.lines, state.cy, "")
|
||
|
|
elseif state.cx > #state.lines[state.cy] then
|
||
|
|
table.insert(state.lines, state.cy + 1, "")
|
||
|
|
else
|
||
|
|
local line = state.lines[state.cy]
|
||
|
|
local before, after = line:sub(0, state.cx - 1), line:sub(state.cx)
|
||
|
|
state.lines[state.cy] = before
|
||
|
|
table.insert(state.lines, state.cy + 1, after)
|
||
|
|
end
|
||
|
|
|
||
|
|
state.cy = state.cy + 1
|
||
|
|
state.cx = 1
|
||
|
|
|
||
|
|
elseif id == "up" then
|
||
|
|
if state.cy > 1 then
|
||
|
|
state.cy = state.cy - 1
|
||
|
|
if state.cy - state.scroll < scroll_offset then
|
||
|
|
state.scroll = math.max(0, state.cy - scroll_offset)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
state.cx = math.min(state.cx, #state.lines[state.cy] + 1)
|
||
|
|
|
||
|
|
elseif id == "down" then
|
||
|
|
if state.cy < #state.lines then
|
||
|
|
state.cy = state.cy + 1
|
||
|
|
|
||
|
|
if state.cy - state.scroll > h - scroll_offset then
|
||
|
|
state.scroll = math.max(0, math.min(#state.lines - h + 1,
|
||
|
|
state.cy - h + scroll_offset))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
state.cx = math.min(state.cx, #state.lines[state.cy] + 1)
|
||
|
|
|
||
|
|
elseif id == "left" then
|
||
|
|
if state.cx > 1 then
|
||
|
|
state.cx = state.cx - 1
|
||
|
|
end
|
||
|
|
|
||
|
|
elseif id == "right" then
|
||
|
|
if state.cx < #state.lines[state.cy] + 1 then
|
||
|
|
state.cx = state.cx + 1
|
||
|
|
end
|
||
|
|
|
||
|
|
elseif id == "leftCtrl" or id == "rightCtrl" then
|
||
|
|
state.status = "S:save E:exit"
|
||
|
|
menu = true
|
||
|
|
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
term.clear()
|
||
|
|
while run do
|
||
|
|
term.setCursorBlink(false)
|
||
|
|
redraw()
|
||
|
|
term.setCursorBlink(true)
|
||
|
|
if menu then
|
||
|
|
processMenuInput()
|
||
|
|
else
|
||
|
|
processInput()
|
||
|
|
end
|
||
|
|
end
|