Skip to content

Instantly share code, notes, and snippets.

@Vftdan
Last active August 5, 2025 19:38
Show Gist options
  • Select an option

  • Save Vftdan/980a1974db655c707d3d54ccab88776d to your computer and use it in GitHub Desktop.

Select an option

Save Vftdan/980a1974db655c707d3d54ccab88776d to your computer and use it in GitHub Desktop.
Suspends ComputerCraft program after each written screenful
local parentTerm
local linesFed = 0
local eventQueue = {}
local consumeQueue = true
local skipKeyUp = {}
local function getChar()
-- If the wrapped program received key event,
-- we should not consume its corresponding char event
local hadKeyDown = false
while true do
consumeQueue = false
local ev = table.pack(os.pullEvent())
consumeQueue = true
if hadKeyDown and ev[1] == "char" then
return table.unpack(ev, 2, ev.n)
elseif ev[1] == "key" then
hadKeyDown = true
if not ev[3] and ev[2] then
skipKeyUp[ev[2]] = true
end
else
table.insert(eventQueue, ev)
end
end
end
local function makeProxyFunction(name)
return function(...)
return parentTerm[name](...)
end
end
local termProxy = {
getSize = function()
local w, h = parentTerm.getSize()
return w, h - 1
end,
scroll = function(n)
local w, h = parentTerm.getSize()
if linesFed + n >= h - 1 then
local amount = h - 2 - linesFed
if amount < 0 then
amount = 0
end
if amount > 0 then
parentTerm.scroll(amount)
end
n = n - amount
linesFed = 0
local savedCursor = {parentTerm.getCursorPos()}
parentTerm.setCursorPos(1, h)
parentTerm.clearLine()
parentTerm.write(("-- MORE --"):sub(1, w))
getChar()
parentTerm.clearLine()
parentTerm.setCursorPos(table.unpack(savedCursor))
end
parentTerm.scroll(n)
linesFed = linesFed + n
if linesFed < 0 then
linesFed = 0
end
end,
}
for k in pairs(term.native()) do
if termProxy[k] == nil then
termProxy[k] = makeProxyFunction(k)
end
end
local args = {...}
local co = coroutine.create(function()
shell.run(table.unpack(args))
end)
local x, y = term.getCursorPos()
term.scroll(1)
term.setCursorPos(x, y - 1)
local wantEvent = nil
while coroutine.status(co) ~= "dead" do
local ok
local ev = nil
if consumeQueue then
ev = table.remove(eventQueue, 1)
end
if wantEvent ~= nil and ev and wantEvent ~= ev[1] then
ev = nil
end
while not ev do
ev = table.pack(os.pullEvent(wantEvent))
if ev[1] == "key" and ev[3] then
if ev[2] and skipKeyUp[ev[2]] then
skipKeyUp[ev[2]] = nil
ev[3] = false
end
elseif ev[1] == "key_up" then
if ev[2] and skipKeyUp[ev[2]] then
skipKeyUp[ev[2]] = nil
ev = nil
end
end
end
parentTerm = term.current()
term.redirect(termProxy)
ok, wantEvent = coroutine.resume(co, table.unpack(ev, 1, ev.n))
term.redirect(parentTerm)
if not ok then
printError(wantEvent)
break
end
end
-- vim: ts=4 et
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment