mirror of
https://github.com/CCLeonOS/LeonOS.git
synced 2026-03-03 15:17:01 +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:
388
data/computercraft/lua/rom/startup/15_term.lua
Normal file
388
data/computercraft/lua/rom/startup/15_term.lua
Normal file
@@ -0,0 +1,388 @@
|
||||
-- some term things
|
||||
-- e.g. redirects, read()
|
||||
|
||||
local rc = ...
|
||||
|
||||
-- we need a couple of these
|
||||
local colors = require("colors")
|
||||
local native = require("term")
|
||||
local strings = require("cc.strings")
|
||||
local expect = require("cc.expect").expect
|
||||
|
||||
local term = {}
|
||||
package.loaded.term = term
|
||||
local thread = require("rc.thread")
|
||||
|
||||
local valid = {
|
||||
write = true,
|
||||
scroll = true,
|
||||
getCursorPos = true,
|
||||
setCursorPos = true,
|
||||
getCursorBlink = true,
|
||||
setCursorBlink = true,
|
||||
getSize = true,
|
||||
clear = true,
|
||||
clearLine = true,
|
||||
getTextColor = true,
|
||||
getTextColour = true,
|
||||
setTextColor = true,
|
||||
setTextColour = true,
|
||||
getBackgroundColor = true,
|
||||
getBackgroundColour = true,
|
||||
setBackgroundColor = true,
|
||||
setBackgroundColour = true,
|
||||
isColor = true,
|
||||
isColour = true,
|
||||
blit = true,
|
||||
setPaletteColor = true,
|
||||
setPaletteColour = true,
|
||||
getPaletteColor = true,
|
||||
getPaletteColour = true,
|
||||
|
||||
-- LeonOS-PC graphics mode settings
|
||||
setGraphicsMode = not not native.setGraphicsMode,
|
||||
getGraphicsMode = not not native.getGraphicsMode,
|
||||
drawPixels = not not native.drawPixels,
|
||||
getPixels = not not native.getPixels,
|
||||
setPixel = not not native.setPixel,
|
||||
getPixel = not not native.getPixel
|
||||
}
|
||||
|
||||
for k in pairs(valid) do
|
||||
term[k] = function(...)
|
||||
local redirect = thread.getTerm()
|
||||
if not redirect[k] then
|
||||
error("redirect object does not implement term."..k, 2)
|
||||
end
|
||||
|
||||
return redirect[k](...)
|
||||
end
|
||||
end
|
||||
|
||||
function term.current()
|
||||
return thread.getTerm()
|
||||
end
|
||||
|
||||
function term.native()
|
||||
return native
|
||||
end
|
||||
|
||||
function term.redirect(obj)
|
||||
expect(1, obj, "table")
|
||||
return thread.setTerm(obj)
|
||||
end
|
||||
|
||||
function term.at(x, y)
|
||||
term.setCursorPos(x, y)
|
||||
return term
|
||||
end
|
||||
|
||||
local keys = require("keys")
|
||||
|
||||
-- rc.write
|
||||
-- [[
|
||||
function rc.write(text)
|
||||
expect(1, text, "string")
|
||||
|
||||
local lines = 0
|
||||
local w, h = term.getSize()
|
||||
local x, y = term.getCursorPos()
|
||||
|
||||
local elements = strings.splitElements(text, w)
|
||||
|
||||
strings.wrappedWriteElements(elements, w, false, {
|
||||
newline = function()
|
||||
lines = lines + 1
|
||||
|
||||
x = 1
|
||||
if y >= h then
|
||||
term.scroll(1)
|
||||
else
|
||||
y = y + 1
|
||||
end
|
||||
|
||||
term.at(x, y)
|
||||
end,
|
||||
|
||||
append = function(newText)
|
||||
term.at(x, y).write(newText)
|
||||
x = x + #newText
|
||||
end,
|
||||
|
||||
getX = function()
|
||||
return x
|
||||
end
|
||||
})
|
||||
|
||||
return lines
|
||||
end
|
||||
|
||||
--]]
|
||||
|
||||
-- old write() used for redrawing in read()
|
||||
local function write(text)
|
||||
expect(1, text, "string")
|
||||
|
||||
local lines = 0
|
||||
local w, h = term.getSize()
|
||||
|
||||
local function inc_cy(cy)
|
||||
lines = lines + 1
|
||||
|
||||
if cy > h - 1 then
|
||||
term.scroll(1)
|
||||
return cy
|
||||
else
|
||||
return cy + 1
|
||||
end
|
||||
end
|
||||
|
||||
while #text > 0 do
|
||||
local nl = text:find("\n") or #text
|
||||
local chunk = text:sub(1, nl)
|
||||
text = text:sub(#chunk + 1)
|
||||
|
||||
local has_nl = chunk:sub(-1) == "\n"
|
||||
if has_nl then chunk = chunk:sub(1, -2) end
|
||||
|
||||
local cx, cy = term.getCursorPos()
|
||||
while #chunk > 0 do
|
||||
if cx > w then
|
||||
term.setCursorPos(1, inc_cy(cy))
|
||||
cx, cy = term.getCursorPos()
|
||||
end
|
||||
|
||||
local to_write = chunk:sub(1, w - cx + 1)
|
||||
term.write(to_write)
|
||||
|
||||
chunk = chunk:sub(#to_write + 1)
|
||||
cx, cy = term.getCursorPos()
|
||||
end
|
||||
|
||||
if has_nl then
|
||||
term.setCursorPos(1, inc_cy(cy))
|
||||
end
|
||||
end
|
||||
|
||||
return lines
|
||||
end--]]
|
||||
|
||||
rc.write = write
|
||||
|
||||
-- read
|
||||
local empty = {}
|
||||
function term.read(replace, history, complete, default)
|
||||
expect(1, replace, "string", "nil")
|
||||
expect(2, history, "table", "nil")
|
||||
expect(3, complete, "function", "nil")
|
||||
expect(4, default, "string", "nil")
|
||||
|
||||
if replace then replace = replace:sub(1, 1) end
|
||||
local hist = history or {}
|
||||
history = {}
|
||||
for i=1, #hist, 1 do
|
||||
history[i] = hist[i]
|
||||
end
|
||||
|
||||
local buffer = default or ""
|
||||
local prev_buf = buffer
|
||||
history[#history+1] = buffer
|
||||
|
||||
local hist_pos = #history
|
||||
local cursor_pos = 0
|
||||
|
||||
local stx, sty = term.getCursorPos()
|
||||
local w, h = term.getSize()
|
||||
|
||||
local dirty = false
|
||||
local completions = {}
|
||||
local comp_id = 0
|
||||
|
||||
local function clearCompletion()
|
||||
if completions[comp_id] then
|
||||
write((" "):rep(#completions[comp_id]))
|
||||
end
|
||||
end
|
||||
|
||||
local function full_redraw(force)
|
||||
if force or dirty then
|
||||
if complete and buffer ~= prev_buf then
|
||||
completions = complete(buffer) or empty
|
||||
comp_id = math.min(1, #completions)
|
||||
end
|
||||
prev_buf = buffer
|
||||
|
||||
term.setCursorPos(stx, sty)
|
||||
local text = buffer
|
||||
if replace then text = replace:rep(#text) end
|
||||
local ln = write(text)
|
||||
|
||||
if completions[comp_id] then
|
||||
local oldfg = term.getTextColor()
|
||||
local oldbg = term.getBackgroundColor()
|
||||
term.setTextColor(colors.white)
|
||||
term.setBackgroundColor(colors.gray)
|
||||
ln = ln + write(completions[comp_id])
|
||||
term.setTextColor(oldfg)
|
||||
term.setBackgroundColor(oldbg)
|
||||
else
|
||||
ln = ln + write(" ")
|
||||
end
|
||||
|
||||
if sty + ln > h then
|
||||
sty = sty - (sty + ln - h)
|
||||
end
|
||||
end
|
||||
|
||||
-- set cursor to the appropriate spot
|
||||
local cx, cy = stx, sty
|
||||
cx = cx + #buffer - cursor_pos-- + #(completions[comp_id] or "")
|
||||
while cx > w do
|
||||
cx = cx - w
|
||||
cy = cy + 1
|
||||
end
|
||||
term.setCursorPos(cx, cy)
|
||||
end
|
||||
|
||||
term.setCursorBlink(true)
|
||||
|
||||
while true do
|
||||
full_redraw()
|
||||
-- get input
|
||||
local evt, id = rc.pullEvent()
|
||||
|
||||
if evt == "char" then
|
||||
dirty = true
|
||||
clearCompletion()
|
||||
if cursor_pos == 0 then
|
||||
buffer = buffer .. id
|
||||
elseif cursor_pos == #buffer then
|
||||
buffer = id .. buffer
|
||||
else
|
||||
buffer = buffer:sub(0, -cursor_pos - 1)..id..buffer:sub(-cursor_pos)
|
||||
end
|
||||
|
||||
elseif evt == "paste" then
|
||||
dirty = true
|
||||
clearCompletion()
|
||||
if cursor_pos == 0 then
|
||||
buffer = buffer .. id
|
||||
elseif cursor_pos == #buffer then
|
||||
buffer = id .. buffer
|
||||
else
|
||||
buffer = buffer:sub(0, -cursor_pos - 1)..id..
|
||||
buffer:sub(-cursor_pos+(#id-1))
|
||||
end
|
||||
|
||||
elseif evt == "key" then
|
||||
id = keys.getName(id)
|
||||
|
||||
if id == "backspace" and #buffer > 0 then
|
||||
dirty = true
|
||||
if cursor_pos == 0 then
|
||||
buffer = buffer:sub(1, -2)
|
||||
clearCompletion()
|
||||
elseif cursor_pos < #buffer then
|
||||
buffer = buffer:sub(0, -cursor_pos - 2)..buffer:sub(-cursor_pos)
|
||||
end
|
||||
|
||||
elseif id == "delete" and cursor_pos > 0 then
|
||||
dirty = true
|
||||
|
||||
if cursor_pos == #buffer then
|
||||
buffer = buffer:sub(2)
|
||||
elseif cursor_pos == 1 then
|
||||
buffer = buffer:sub(1, -2)
|
||||
else
|
||||
buffer = buffer:sub(0, -cursor_pos - 1) .. buffer:sub(-cursor_pos + 1)
|
||||
end
|
||||
cursor_pos = cursor_pos - 1
|
||||
|
||||
elseif id == "up" then
|
||||
if #completions > 1 then
|
||||
dirty = true
|
||||
clearCompletion()
|
||||
if comp_id > 1 then
|
||||
comp_id = comp_id - 1
|
||||
else
|
||||
comp_id = #completions
|
||||
end
|
||||
|
||||
elseif hist_pos > 1 then
|
||||
cursor_pos = 0
|
||||
|
||||
history[hist_pos] = buffer
|
||||
hist_pos = hist_pos - 1
|
||||
|
||||
buffer = (" "):rep(#buffer)
|
||||
full_redraw(true)
|
||||
|
||||
buffer = history[hist_pos]
|
||||
dirty = true
|
||||
end
|
||||
|
||||
elseif id == "down" then
|
||||
if #completions > 1 then
|
||||
dirty = true
|
||||
clearCompletion()
|
||||
if comp_id < #completions then
|
||||
comp_id = comp_id + 1
|
||||
else
|
||||
comp_id = 1
|
||||
end
|
||||
|
||||
elseif hist_pos < #history then
|
||||
cursor_pos = 0
|
||||
|
||||
history[hist_pos] = buffer
|
||||
hist_pos = hist_pos + 1
|
||||
|
||||
buffer = (" "):rep(#buffer)
|
||||
full_redraw(true)
|
||||
|
||||
buffer = history[hist_pos]
|
||||
dirty = true
|
||||
end
|
||||
|
||||
elseif id == "left" then
|
||||
if cursor_pos < #buffer then
|
||||
clearCompletion()
|
||||
cursor_pos = cursor_pos + 1
|
||||
end
|
||||
|
||||
elseif id == "right" then
|
||||
if cursor_pos > 0 then
|
||||
cursor_pos = cursor_pos - 1
|
||||
|
||||
elseif comp_id > 0 then
|
||||
dirty = true
|
||||
buffer = buffer .. completions[comp_id]
|
||||
end
|
||||
|
||||
elseif id == "tab" then
|
||||
if comp_id > 0 then
|
||||
dirty = true
|
||||
buffer = buffer .. completions[comp_id]
|
||||
end
|
||||
|
||||
elseif id == "home" then
|
||||
cursor_pos = #buffer
|
||||
|
||||
elseif id == "end" then
|
||||
cursor_pos = 0
|
||||
|
||||
elseif id == "enter" then
|
||||
clearCompletion()
|
||||
write("\n")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
term.setCursorBlink(false)
|
||||
|
||||
return buffer
|
||||
end
|
||||
|
||||
rc.read = term.read
|
||||
setmetatable(term, {__index = native})
|
||||
Reference in New Issue
Block a user