Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local computer = require("computer")
- local event = require("event")
- local keyboard = require("keyboard")
- local text = require("text")
- local unicode = require("unicode")
- local term = {}
- local cursorX, cursorY = 1, 1
- local cursorBlink = nil
- local colourTab = {}
- colourTab[0],colourTab[1],colourTab[2],colourTab[3],colourTab[4],colourTab[5],colourTab[6],colourTab[7],colourTab[8],colourTab[9],colourTab["A"],colourTab["B"],colourTab["C"],colourTab["D"],colourTab["E"],colourTab["F"]=0xFFFFFF,0x000000,0x00007F,0x009300,0xFF0000,0x7F0000,0x9C009C,0xFC7F00,0xFFFF00,0x00FC00,0x009393,0x00FFFF,0x0000FC,0xFF00FF,0x7F7F7F,0xD2D2D2
- local function toggleBlink()
- if term.isAvailable() then
- cursorBlink.state = not cursorBlink.state
- if cursorBlink.state then
- cursorBlink.alt = component.gpu.get(cursorX, cursorY)
- component.gpu.set(cursorX, cursorY, unicode.char(0x2588)) -- solid block
- else
- component.gpu.set(cursorX, cursorY, cursorBlink.alt)
- end
- end
- end
- -------------------------------------------------------------------------------
- function term.clear()
- if term.isAvailable() then
- local w, h = component.gpu.getResolution()
- component.gpu.fill(1, 1, w, h, " ")
- end
- cursorX, cursorY = 1, 1
- end
- function term.clearLine()
- if term.isAvailable() then
- local w = component.gpu.getResolution()
- component.gpu.fill(1, cursorY, w, 1, " ")
- end
- cursorX = 1
- end
- function term.getCursor()
- return cursorX, cursorY
- end
- function term.setCursor(col, row)
- checkArg(1, col, "number")
- checkArg(2, row, "number")
- if cursorBlink and cursorBlink.state then
- toggleBlink()
- end
- cursorX = math.floor(col)
- cursorY = math.floor(row)
- end
- function term.getCursorBlink()
- return cursorBlink ~= nil
- end
- function term.setCursorBlink(enabled)
- checkArg(1, enabled, "boolean")
- if enabled then
- if not cursorBlink then
- cursorBlink = {}
- cursorBlink.id = event.timer(0.5, toggleBlink, math.huge)
- cursorBlink.state = false
- elseif not cursorBlink.state then
- toggleBlink()
- end
- elseif cursorBlink then
- event.cancel(cursorBlink.id)
- if cursorBlink.state then
- toggleBlink()
- end
- cursorBlink = nil
- end
- end
- function term.isAvailable()
- return component.isAvailable("gpu") and component.isAvailable("screen")
- end
- function term.read(history)
- checkArg(1, history, "table", "nil")
- history = history or {}
- table.insert(history, "")
- local offset = term.getCursor() - 1
- local scrollX, scrollY = 0, #history - 1
- local function getCursor()
- local cx, cy = term.getCursor()
- return cx - offset + scrollX, 1 + scrollY
- end
- local function line()
- local cbx, cby = getCursor()
- return history[cby]
- end
- local function setCursor(nbx, nby)
- local w, h = component.gpu.getResolution()
- local cx, cy = term.getCursor()
- scrollY = nby - 1
- nbx = math.max(1, math.min(unicode.len(history[nby]) + 1, nbx))
- local ncx = nbx + offset - scrollX
- if ncx > w then
- local sx = nbx - (w - offset)
- local dx = math.abs(scrollX - sx)
- scrollX = sx
- component.gpu.copy(1 + offset + dx, cy, w - offset - dx, 1, -dx, 0)
- local str = unicode.sub(history[nby], nbx - (dx - 1), nbx)
- str = text.padRight(str, dx)
- component.gpu.set(1 + math.max(offset, w - dx), cy, unicode.sub(str, 1 + math.max(0, dx - (w - offset))))
- elseif ncx < 1 + offset then
- local sx = nbx - 1
- local dx = math.abs(scrollX - sx)
- scrollX = sx
- component.gpu.copy(1 + offset, cy, w - offset - dx, 1, dx, 0)
- local str = unicode.sub(history[nby], nbx, nbx + dx)
- --str = text.padRight(str, dx)
- component.gpu.set(1 + offset, cy, str)
- end
- term.setCursor(nbx - scrollX + offset, cy)
- end
- local function copyIfNecessary()
- local cbx, cby = getCursor()
- if cby ~= #history then
- history[#history] = line()
- setCursor(cbx, #history)
- end
- end
- local function redraw()
- local cx, cy = term.getCursor()
- local bx, by = 1 + scrollX, 1 + scrollY
- local w, h = component.gpu.getResolution()
- local l = w - offset
- local str = unicode.sub(history[by], bx, bx + l)
- str = text.padRight(str, l)
- component.gpu.set(1 + offset, cy, str)
- end
- local function home()
- local cbx, cby = getCursor()
- setCursor(1, cby)
- end
- local function ende()
- local cbx, cby = getCursor()
- setCursor(unicode.len(line()) + 1, cby)
- end
- local function left()
- local cbx, cby = getCursor()
- if cbx > 1 then
- setCursor(cbx - 1, cby)
- return true -- for backspace
- end
- end
- local function right(n)
- n = n or 1
- local cbx, cby = getCursor()
- local be = unicode.len(line()) + 1
- if cbx < be then
- setCursor(math.min(be, cbx + n), cby)
- end
- end
- local function up()
- local cbx, cby = getCursor()
- if cby > 1 then
- setCursor(1, cby - 1)
- redraw()
- ende()
- end
- end
- local function down()
- local cbx, cby = getCursor()
- if cby < #history then
- setCursor(1, cby + 1)
- redraw()
- ende()
- end
- end
- local function delete()
- copyIfNecessary()
- local cbx, cby = getCursor()
- if cbx <= unicode.len(line()) then
- history[cby] = unicode.sub(line(), 1, cbx - 1) ..
- unicode.sub(line(), cbx + 1)
- local cx, cy = term.getCursor()
- local w, h = component.gpu.getResolution()
- component.gpu.copy(cx + 1, cy, w - cx, 1, -1, 0)
- local br = cbx + (w - cx)
- local char = unicode.sub(line(), br, br)
- if not char or unicode.len(char) == 0 then
- char = " "
- end
- component.gpu.set(w, cy, char)
- end
- end
- local function insert(value)
- copyIfNecessary()
- local cx, cy = term.getCursor()
- local cbx, cby = getCursor()
- local w, h = component.gpu.getResolution()
- history[cby] = unicode.sub(line(), 1, cbx - 1) ..
- value ..
- unicode.sub(line(), cbx)
- local len = unicode.len(value)
- local n = w - (cx - 1) - len
- if n > 0 then
- component.gpu.copy(cx, cy, n, 1, len, 0)
- end
- component.gpu.set(cx, cy, value)
- right(len)
- end
- local function onKeyDown(char, code)
- term.setCursorBlink(false)
- if code == keyboard.keys.back then
- if left() then delete() end
- elseif code == keyboard.keys.delete then
- delete()
- elseif code == keyboard.keys.left then
- left()
- elseif code == keyboard.keys.right then
- right()
- elseif code == keyboard.keys.home then
- home()
- elseif code == keyboard.keys["end"] then
- ende()
- elseif code == keyboard.keys.up then
- up()
- elseif code == keyboard.keys.down then
- down()
- elseif code == keyboard.keys.enter then
- local cbx, cby = getCursor()
- if cby ~= #history then -- bring entry to front
- history[#history] = line()
- table.remove(history, cby)
- end
- return true, history[#history] .. "\n"
- elseif keyboard.isControlDown() and code == keyboard.keys.d then
- if line() == "" then
- history[#history] = ""
- return true, nil
- end
- elseif keyboard.isControlDown() and code == keyboard.keys.c then
- history[#history] = ""
- return true, nil
- elseif not keyboard.isControl(char) then
- insert(unicode.char(char))
- end
- term.setCursorBlink(true)
- term.setCursorBlink(true) -- force toggle to caret
- end
- local function onClipboard(value)
- copyIfNecessary()
- term.setCursorBlink(false)
- local cbx, cby = getCursor()
- local l = value:find("\n", 1, true)
- if l then
- history[cby] = unicode.sub(line(), 1, cbx - 1)
- redraw()
- insert(unicode.sub(value, 1, l - 1))
- return true, line() .. "\n"
- else
- insert(value)
- term.setCursorBlink(true)
- term.setCursorBlink(true) -- force toggle to caret
- end
- end
- local function cleanup()
- if history[#history] == "" then
- table.remove(history)
- end
- term.setCursorBlink(false)
- if term.getCursor() > 1 then
- print()
- end
- end
- term.setCursorBlink(true)
- while term.isAvailable() do
- local ocx, ocy = getCursor()
- local ok, name, address, charOrValue, code = pcall(event.pull)
- if not ok then
- cleanup()
- error("interrupted", 0)
- end
- local ncx, ncy = getCursor()
- if ocx ~= ncx or ocy ~= ncy then
- cleanup()
- return "" -- soft fail the read if someone messes with the term
- end
- if term.isAvailable() and -- may have changed since pull
- type(address) == "string" and
- component.isPrimary(address)
- then
- local done, result
- if name == "key_down" then
- done, result = onKeyDown(charOrValue, code)
- elseif name == "clipboard" then
- done, result = onClipboard(charOrValue)
- end
- if done then
- cleanup()
- return result
- end
- end
- end
- cleanup()
- return nil -- fail the read if term becomes unavailable
- end
- function term.write(value, wrap)
- wrap = true
- if not term.isAvailable() then
- return
- end
- value = tostring(value)
- if unicode.len(value) == 0 then
- return
- end
- do
- local noBell = value:gsub("\a", "")
- if #noBell ~= #value then
- value = noBell
- computer.beep()
- end
- end
- value = text.detab(value)
- local w, h = component.gpu.getResolution()
- if not w then
- return -- gpu lost its screen but the signal wasn't processed yet.
- end
- local blink = term.getCursorBlink()
- term.setCursorBlink(false)
- local ltab = {}
- for i = 1, value:len() do
- local c = value:sub(i,i)
- table.insert(ltab,c)
- end
- local ti = 1
- repeat
- if cursorX > w then
- cursorX, cursorY = 1, cursorY+1
- end
- if ltab[ti] == "%" and ltab[ti+1] == "C" and ltab[ti+3] == "," then
- if tonumber(ti+2) ~= nil then
- component.gpu.setForeground(tonumber(colourTab[ti+2]))
- else
- component.gpu.setForeground(colourTab[ti+2])
- end
- if tonumber(ti+4) ~= nil then
- component.gpu.setBackground(tonumber(colourTab[ti+4]))
- else
- component.gpu.setBackground(colourTab[ti+4])
- end
- ti=ti+5
- elseif ltab[ti] == "%" and ltab[ti+1] == "C" then
- if tonumber(ti+2) ~= nil then
- component.gpu.setForeground(tonumber(colourTab[ti+2]))
- else
- component.gpu.setForeground(colourTab[ti+2])
- end
- ti=ti+3
- end
- component.gpu.set(cursorX,cursorY,ltab[ti])
- ti = ti + 1
- cursorX = cursorX + 1
- until ti == #ltab
- term.setCursorBlink(blink)
- end
- -------------------------------------------------------------------------------
- return term
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement