Files
LeonOS/data/computercraft/lua/rom/editors/advanced.lua
Leonmmcoset 90a901f58e feat: 初始提交 LeonOS 实现
添加 LeonOS 的基本实现,包括:
- 核心 API 模块(colors, disk, gps, keys, multishell, parallel, rednet, redstone, settings, vector)
- 命令行程序(about, alias, bg, clear, copy, delete, edit, fg, help, list, lua, mkdir, move, paint, peripherals, programs, reboot, set, shutdown, threads)
- 系统启动脚本和包管理
- 文档(README.md, LICENSE)
- 开发工具(devbin)和更新程序

实现功能:
- 完整的线程管理系统
- 兼容 ComputerCraft 的 API 设计
- 改进的 shell 和命令补全系统
- 多标签终端支持
- 设置管理系统
2025-08-31 16:54:18 +08:00

309 lines
6.7 KiB
Lua

-- A much better editor.
local rc = require("rc")
local keys = require("keys")
local term = require("term")
local colors = require("colors")
local settings = require("settings")
local textutils = require("textutils")
local args = {...}
local type_colors = {
separator = colors[settings.get("edit.color_separator") or "lightBlue"],
operator = colors[settings.get("edit.color_operator") or "lightGray"],
keyword = colors[settings.get("edit.color_keyword") or "orange"],
boolean = colors[settings.get("edit.color_boolean") or "purple"],
comment = colors[settings.get("edit.color_comment") or "gray"],
builtin = colors[settings.get("edit.color_global") or "lime"],
string = colors[settings.get("edit.color_string") or "red"],
number = colors[settings.get("edit.color_number") or "magenta"]
}
local lines = {}
local linesDraw = {}
local run, menu = true, false
local cx, cy = 1, 1
local scroll = 0
local hscroll = 0
local scroll_offset = settings.get("edit.scroll_offset") or 3
local scroll_increment = 0
local scroll_factor = settings.get("edit.scroll_factor") or 8
local unsaved, changed = false, true
local file = args[1] or ".new"
local status = "Press Ctrl for menu"
if args[1] then
local handle = io.open(args[1], "r")
if handle then
for line in handle:lines() do
lines[#lines+1] = line
end
handle:close()
end
end
if not lines[1] then lines[1] = "" end
local win = require("window").create(term.current(), 1, 1, term.getSize())
local function redraw()
local w, h = term.getSize()
-- this seems to provide a good responsiveness curve on my machine
scroll_increment = math.floor(h/scroll_factor)
win.reposition(1, 1, w, h)
win.setVisible(false)
for i=1, h - 1, 1 do
local line = linesDraw[i]
win.setCursorPos(1 - hscroll, i)
win.clearLine()
if line then
for t=1, #line, 1 do
local item = line[t]
if type(item) == "number" then
win.setTextColor(item)
else
win.write(item)
end
end
end
end
win.setCursorPos(1, h)
win.clearLine()
win.setTextColor(type_colors.accent or colors.yellow)
win.write(status)
win.setTextColor(colors.white)
win.setCursorPos(math.min(w, cx), cy - scroll)
win.setCursorBlink(true)
win.setVisible(true)
end
local syntax = require("edit.syntax")
.new("/rc/modules/main/edit/syntax/lua.lua")
local function rehighlight()
local line = {}
linesDraw = {}
local _, h = term.getSize()
local text = table.concat(lines, "\n", scroll+1,
math.min(#lines, scroll+h+1)) or ""
for token, ttype in syntax(text) do
if token == "\n" then
linesDraw[#linesDraw+1] = line
line = {}
else
repeat
local bit = token:find("\n")
local nl = not not bit
local chunk = token:sub(1, bit or #token)
token = token:sub(#chunk+1)
line[#line+1] = type_colors[ttype] or colors.white
line[#line+1] = chunk
if nl then
linesDraw[#linesDraw+1] = line
line = {}
end
until #token == 0
end
end
if #line > 0 then
linesDraw[#linesDraw+1] = line
end
end
local function save()
if file == ".new" then
local _, h = term.getSize()
term.setCursorPos(1, h)
textutils.coloredWrite(colors.yellow, "filename: ")
file = term.read()
end
local handle, err = io.open(file, "w")
if not handle then
status = err
else
for i=1, #lines, 1 do
handle:write(lines[i] .. "\n")
end
handle:close()
status = "Saved to " .. file
unsaved = false
end
end
local function processInput()
local event, id = rc.pullEvent()
local w, h = term.getSize()
if event == "char" then
local line = lines[cy]
unsaved = true
if cx > #line then
line = line .. id
elseif cx == 1 then
line = id .. line
else
line = line:sub(0, cx-1) .. id .. line:sub(cx)
end
cx = cx + 1
lines[cy] = line
changed = true
elseif event == "key" then
id = keys.getName(id)
if id == "backspace" then
local line = lines[cy]
unsaved = true
if cx == 1 and cy > 1 then
local previous = table.remove(lines, cy - 1)
cy = cy - 1
cx = #previous + 1
line = previous .. line
else
if #line > 0 then
if cx > #line then
cx = cx - 1
line = line:sub(1, -2)
elseif cx > 1 then
line = line:sub(0, cx - 2) .. line:sub(cx)
cx = cx - 1
end
end
end
lines[cy] = line
changed = true
elseif id == "enter" then
if cx == 1 then
table.insert(lines, cy, "")
elseif cx > #lines[cy] then
table.insert(lines, cy+1, "")
else
local line = lines[cy]
local before, after = line:sub(0, cx - 1), line:sub(cx)
lines[cy] = before
table.insert(lines, cy + 1, after)
end
cy = cy + 1
cx = 1
changed = true
elseif id == "up" then
if cy > 1 then
cy = cy - 1
if cy - scroll < scroll_offset then
local old_scroll = scroll
scroll = math.max(0, scroll - scroll_increment)
if scroll < old_scroll then
rehighlight()
end
end
end
cx = math.min(cx, #lines[cy] + 1)
elseif id == "down" then
if cy < #lines then
cy = math.min(#lines, cy + 1)
if cy - scroll > h - scroll_offset then
local old_scroll = scroll
scroll = math.max(0, math.min(#lines - h + 1,
scroll + scroll_increment))
if scroll > old_scroll then
rehighlight()
end
end
end
cx = math.min(cx, #lines[cy] + 1)
elseif id == "left" then
if cx > 1 then
cx = cx - 1
end
hscroll = math.max(0, cx - w)
elseif id == "right" then
if cx < #lines[cy] + 1 then
cx = cx + 1
end
hscroll = math.max(0, cx - w)
elseif id == "leftCtrl" or id == "rightCtrl" then
status = "S:save E:exit"
menu = true
end
end
end
local function processMenuInput()
local event, id = rc.pullEvent()
if event == "char" then
if id:lower() == "e" then
if unsaved and menu ~= 2 then
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
status = "Press Ctrl for menu"
menu = false
end
end
end
while run do
if changed then rehighlight() changed = false end
redraw()
if menu then
processMenuInput()
else
processInput()
end
end