Posted 08 March 2015 - 03:00 AM
ive tried it in the past, got it working, but just barely. how can i make a proper scroll bar, only if the text{} table is too large for the screen?
local args={...}
local filename=args[1]
--if no valid arg specified, just open myself
if not filename or not fs.exists(filename) or fs.isDir(filename) then
print("usage:\nscroll <filename>")
return
end
local scrWidth,scrHeight=term.getSize()
local scrollRedir={}
do
local width, height=scrWidth-2,2
local curX, curY=1,1
local lines={"",""}
local hasScrollBar=false
function scrollRedir.write(text)
lines[curY]=lines[curY]..text
curX=curX+#text
end
function scrollRedir.getCursorPos()
return curX, curY
end
function scrollRedir.getSize()
return width, #lines
end
function scrollRedir.scroll(amt)
--amt will always be 1. Just grow the buffer one line.
lines[#lines+1]=""
curY=curY+1
curX=1
end
function scrollRedir.setCursorPos(x,y)
curX=x
curY=y
end
function scrollRedir.isColor()
--if you want these to support color, that becomes more of a thing.
return false;
end
scrollRedir.isColour=scrollRedir.isColor
--we just ignore these
function scrollRedir.setTextColor() end
function scrollRedir.setTextColour() end
function scrollRedir.setBackgroundColor() end
function scrollRedir.setBackgroundColour() end
function scrollRedir.setCursorBlink() end
function scrollRedir.clearLine()
lines[curY]=""
end
function scrollRedir.clear()
lines={"",""}
curY=1
curX=1
end
function scrollRedir.getHasScrollBar() return hasScrollBar end
function scrollRedir.setHasScrollBar(state)
hasScrollBar=state
if hasScrollBar then
width=scrWidth-1
else
width=scrWidth
end
end
function scrollRedir.getNumLines() return #lines end
function scrollRedir.draw(startRow)
term.setTextColor(colors.white)
term.setBackgroundColor(colors.black)
for y=1,scrHeight do
term.setCursorPos(1,y)
term.clearLine()
term.write(lines[y+startRow-1] or "")
end
if hasScrollBar then
term.setTextColor(colors.black)
term.setBackgroundColor(colors.white)
term.setCursorPos(scrWidth,1)
term.write("^")
term.setCursorPos(scrWidth,scrHeight)
term.write("v")
--calculate bar height
local barHeight=math.max(1,math.floor(scrHeight*scrHeight/#lines))
--and the position
local barPos
if startRow==1 then
barPos=2
elseif startRow+scrHeight-1 == #lines then
barPos=(scrHeight-barHeight)
else
local min, max=3,scrHeight-barHeight-2
barPos=min+math.floor(startRow/(#lines-scrHeight-1)*(max-min+1)+.5)
end
for y=2,scrHeight-1 do
term.setCursorPos(scrWidth,y)
if y>=barPos and y<barPos+barHeight then
term.write("=")
else
term.write("|")
end
end
end
end
function scrollRedir.cropLast()
lines[#lines]=nil
end
end
local text={}
local approxLines=0
do
local file=io.open(filename,"r")
for line in file:lines() do
text[#text+1]=line
approxLines=approxLines + (math.ceil(#line/scrWidth))
end
file:close()
end
local prevRedir=term.current()
local needsScrollBar=true
if approxLines<=scrHeight then
--try without scrollbar
term.redirect(scrollRedir)
for i=1,#text do
print(text)
end
--trim the last line, which was just made blank because of newline
scrollRedir.cropLast()
term.redirect(prevRedir)
local w,h=scrollRedir.getSize()
if h<=scrHeight then
needsScrollBar=false
else
scrollRedir.clear()
end
end
if needsScrollBar then
scrollRedir.setHasScrollBar(true)
term.redirect(scrollRedir)
for i=1,#text do
print(text[i])
end
scrollRedir.cropLast()
term.redirect(prevRedir)
end
local scrollPos=1
local maxScroll=scrollRedir.getNumLines()-scrHeight+1
if not scrollRedir.getHasScrollBar() then
maxScroll=1
end
while true do
scrollRedir.draw(scrollPos)
local e={os.pullEvent()}
if e[1]=="key" then
if e[2]==keys.down then
scrollPos=math.min(scrollPos+1,maxScroll)
elseif e[2]==keys.up then
scrollPos=math.max(scrollPos-1,1)
elseif e[2]==keys.pageDown then
scrollPos=math.min(scrollPos+scrHeight,maxScroll)
elseif e[2]==keys.pageUp then
scrollPos=math.max(scrollPos-scrHeight,1)
elseif e[2]==keys.home then
scrollPos=1
elseif e[2]==keys["end"] then
scrollPos=maxScroll
elseif e[2]==keys.leftCtrl then
break
end
end
end