Files
LeonOS/data/computercraft/lua/rom/startup/15_term.lua

389 lines
8.3 KiB
Lua
Raw Normal View History

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