Files

230 lines
5.1 KiB
Lua
Raw Permalink Normal View History

-- 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