mirror of
https://github.com/CCLeonOS/LeonOS.git
synced 2026-03-03 15:17:01 +00:00
添加 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 和命令补全系统 - 多标签终端支持 - 设置管理系统
389 lines
8.3 KiB
Lua
389 lines
8.3 KiB
Lua
-- 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})
|