Skip to content

Instantly share code, notes, and snippets.

@MCJack123
Last active August 31, 2022 02:32
Show Gist options
  • Save MCJack123/b5e069cdf65c1174f24fc113c0e1292b to your computer and use it in GitHub Desktop.
Save MCJack123/b5e069cdf65c1174f24fc113c0e1292b to your computer and use it in GitHub Desktop.
Better paged print for ComputerCraft using a less-style pager
-- CCPL license: https://github.com/cc-tweaked/CC-Tweaked/blob/mc-1.16.x/LICENSE
-- Note that this breaks help on vanilla CC (CC:T help still works)
textutils.pagedPrint = function(contents, freeLines)
freeLines = freeLines or 0
local foldLines = true
local lines = {}
local pos, hpos = 1, 1
local w, h = term.getSize()
local message = nil
h=h-1
local function readFile()
lines = {}
for line in string.gmatch(contents, "[^\n\r]+") do table.insert(lines, ({string.gsub(line, "\t", " ")})[1]) end
if foldLines and hpos == 1 then for i = 1, #lines do if #lines[i] > w then
table.insert(lines, i+1, string.sub(lines[i], w) or "")
lines[i] = string.sub(lines[i], 1, w - 1)
end end end
end
local function redrawScreen()
term.clear()
term.setCursorPos(1, 1)
term.setCursorBlink(false)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
for i = pos, pos + h - 1 do
if lines[i] ~= nil then term.write(string.sub(lines[i], hpos)) end
term.setCursorPos(1, i - pos + 2)
end
term.setCursorPos(1, h+1)
if message then term.blit(message, string.rep("f", #message), string.rep("0", #message))
elseif pos >= #lines - h then term.blit("(END)", "fffff", "00000")
else term.write(":") end
term.setCursorBlink(true)
end
local function readCommand(prompt, fg, bg)
term.setCursorPos(1, h+1)
term.clearLine()
term.blit(prompt, fg or string.rep("0", #prompt), bg or string.rep("f", #prompt))
local str = ""
local c = 1
while true do
term.setCursorPos(#prompt + 1, h + 1)
term.write(str .. string.rep(" ", w - #str - #prompt - 2))
term.setCursorPos(#prompt + c, h + 1)
term.setCursorBlink(true)
local ev, p1 = os.pullEvent()
if ev == "key" then
if p1 == keys.backspace then if str == "" then return nil elseif c > 1 then
str = string.sub(str, 1, c-2) .. string.sub(str, c)
c=c-1
end
elseif p1 == keys.left and c > 1 then c = c - 1
elseif p1 == keys.right and c < #str + 1 then c = c + 1
elseif p1 == keys.enter or p1 == keys["return"] then return str
end
elseif ev == "char" then
str = string.sub(str, 1, c-1) .. p1 .. string.sub(str, c)
c=c+1
end
end
end
local function flashScreen()
local br, bg, bb = term.getPaletteColor(colors.black)
term.setPaletteColor(colors.black, term.getPaletteColor(colors.lightGray))
sleep(0.1)
term.setPaletteColor(colors.black, term.getPaletteColor(colors.gray))
sleep(0.05)
term.setPaletteColor(colors.black, br, bg, bb)
sleep(0.05)
end
readFile()
if #lines < freeLines then return print(contents) end
local lastQuery = nil
while true do
redrawScreen()
local ev, p1, p2, p3 = os.pullEvent()
local oldMessage = message
message = nil
if ev == "key" then
if p1 == keys.left and hpos > w / 2 then hpos = hpos - w / 2
elseif p1 == keys.right then hpos = hpos + w / 2
elseif p1 == keys.up then if pos > 1 then pos = pos - 1 else flashScreen() end
elseif (p1 == keys.down or p1 == keys.enter or p1 == keys["return"]) then if pos < #lines - h then pos = pos + 1 else flashScreen() end
elseif p1 == keys.space then if pos < #lines - h then pos = pos + (pos < #lines - 2*h + 1 and h or (#lines - h) - pos) else flashScreen() end
end
elseif ev == "char" then
if p1 == "q" then break
elseif p1 == "f" then if pos < #lines - h then pos = pos + (pos < #lines - 2*h + 1 and h or (#lines - h) - pos) else flashScreen() end
elseif p1 == "b" then if pos > 1 then pos = pos - (pos > h + 1 and h or pos - 1) else flashScreen() end
elseif p1 == "d" then if pos < #lines - h then pos = pos + (pos < #lines - (1.5*h) + 1 and h / 2 or (#lines - h) - pos) else flashScreen() end
elseif p1 == "u" then if pos > 1 then pos = pos - (pos > (h / 2) + 1 and (h / 2) or pos - 1) else flashScreen() end
elseif p1 == "g" or p1 == "<" then pos = 1
elseif p1 == "G" or p1 == ">" then pos = #lines - h
elseif p1 == "e" or p1 == "j" then if pos < #lines - h then pos = pos + 1 else flashScreen() end
elseif p1 == "y" or p1 == "k" then if pos > 1 then pos = pos - 1 else flashScreen() end
elseif p1 == "K" or p1 == "Y" then pos = pos - 1
elseif p1 == "J" then pos = pos + 1
elseif p1 == "/" then
local query = readCommand("/")
if query == "" then query = lastQuery end
if query ~= nil then
lastQuery = query
local found = false
for i = pos + 1, #lines do if string.match(lines[i], query) then
pos = i
found = true
break
end end
if pos > #lines - h then pos = #lines - h end
if not found then message = "Pattern not found" end
end
elseif p1 == "?" then
local query = readCommand("?")
if query == "" then query = lastQuery end
if query ~= nil then
lastQuery = query
local found = false
for i = pos - 1, 1, -1 do if string.match(lines[i], query) then
pos = i
found = true
break
end end
if pos > #lines - h then pos = #lines - h end
if not found then message = "Pattern not found" end
end
elseif p1 == "n" then
local found = false
for i = pos + 1, #lines do if string.match(lines[i], lastQuery) then
pos = i
found = true
break
end end
if pos > #lines - h then pos = #lines - h end
if not found then message = "Pattern not found" end
elseif p1 == "N" then
local found = false
for i = pos - 1, 1, -1 do if string.match(lines[i], lastQuery) then
pos = i
found = true
break
end end
if pos > #lines - h then pos = #lines - h end
if not found then message = "Pattern not found" end
end
elseif ev == "term_resize" then
w, h = term.getSize()
h=h-1
readFile()
elseif ev == "mouse_scroll" then
if p1 == 1 and pos < #lines - h then pos = pos + 1
elseif p1 == -1 and pos > 1 then pos = pos - 1 end
else
message = oldMessage
end
end
term.clear()
term.setCursorPos(1, 1)
term.setTextColor(colors.white)
term.setBackgroundColor(colors.black)
return #lines
end
local function tabulateCommon( ... )
local retval = {""}
local tAll = { ... }
for k,v in ipairs( tAll ) do
if type( v ) ~= "number" and type( v ) ~= "table" then
error( "bad argument #"..k.." (expected number or table, got " .. type( v ) .. ")", 3 )
end
end
local w,h = term.getSize()
local nMaxLen = w / 8
for n, t in ipairs( tAll ) do
if type(t) == "table" then
for n, sItem in pairs(t) do
nMaxLen = math.max( string.len( sItem ) + 1, nMaxLen )
end
end
end
local nCols = math.floor( w / nMaxLen )
local nLines = 0
local function newLine()
nLines = nLines + 1
retval[nLines+1] = ""
end
local function drawCols( _t )
local nCol = 1
for n, s in ipairs( _t ) do
if nCol > nCols then
nCol = 1
newLine()
end
local cx = #retval[nLines+1]
cx = ((nCol - 1) * nMaxLen)
retval[nLines+1] = retval[nLines+1] .. string.rep(" ", cx - #retval[nLines+1]) .. s
nCol = nCol + 1
end
newLine()
end
for n, t in ipairs( tAll ) do
if type(t) == "table" then
if #t > 0 then
drawCols( t )
end
elseif type(t) == "number" then
--term.setTextColor( t )
end
end
return retval
end
textutils.pagedTabulate = function(...) textutils.pagedPrint(table.concat(tabulateCommon(...), "\n")) end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment