mirror of
https://github.com/CCLeonOS/LeonOS.git
synced 2026-03-03 15:08:29 +00:00
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 和命令补全系统 - 多标签终端支持 - 设置管理系统
This commit is contained in:
308
data/computercraft/lua/rom/editors/advanced.lua
Normal file
308
data/computercraft/lua/rom/editors/advanced.lua
Normal file
@@ -0,0 +1,308 @@
|
||||
-- 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
|
||||
Reference in New Issue
Block a user