Skip to content

Instantly share code, notes, and snippets.

@CoderPuppy
Last active August 26, 2015 22:48
Show Gist options
  • Select an option

  • Save CoderPuppy/28cd1e266d626a09d757 to your computer and use it in GitHub Desktop.

Select an option

Save CoderPuppy/28cd1e266d626a09d757 to your computer and use it in GitHub Desktop.
CC Tutorial

all the pages go in db/pages/ (eg. db/pages/Redstone (API))

type text
[Tutorial 1]
next Tutorial 2
type text
tutorial 1
prev Tutorial 1
next Tutorial 3
type text
hi
prev Tutorial 2
type text
tutorial 2
local width, height = term.getSize()
local down = {}
local bar
local curPage, prevPage
local history, futury = {}, {}
local loadpage
local content = window.create(term.current(), 1, 1, width, height - 1, true)
-- function term.setBackgroundColor() end
-- function term.setTextColor() end
local function _switchPage(page)
curPage = page
local prev = term.redirect(bar.window)
bar.updatePage()
bar.updateMiddle()
term.redirect(prev)
end
local function backPage()
if #history > 0 then
futury[#futury + 1] = curPage.title
curPage = loadpage(table.remove(history, #history))
end
end
local function fwdPage()
if #futury > 0 then
history[#history + 1] = curPage.title
curPage = loadpage(table.remove(futury, #futury))
end
end
local function switchPage(page)
history[#history + 1] = curPage.title
futury = {}
curPage = loadpage(page)
end
local function ser(v)
if type(v) == 'table' then
local kv = false
for k, v in pairs(v) do
if type(k) ~= 'number' then
kv = true
break
end
end
if kv then
local entries = {}
for k, v in pairs(v) do
entries[#entries + 1] = '[' .. ser(k) .. '] = ' .. ser(v) .. ';'
end
entries = table.concat(entries, '\n')
local t = {}
for line in entries:gmatch('[^\n\r]*$') do
t[#t + 1] = '\t' .. line
end
entries = table.concat(t, '\n')
if entries == '' then
return '{}'
else
return '{\n' .. s .. '\n}'
end
else
local entries = {}
for i, v in ipairs(v) do
entries[i] = ser(v)
end
return '{' .. table.concat(entries, ', ') .. '}'
end
else
return textutils.serialize(v)
end
end
function loadpage(name)
local f = fs.open('db/pages/' .. name, 'r')
if not f then
local page = {}
page.notfound = true
page.title = 'Not Found'
page.prev = curPage.title
function page.render()
local title = 'Not Found: ' .. name
term.setTextColor(colors.red)
term.setCursorPos(math.floor((term.getSize()) / 2 - #title / 2), 2)
term.write(title)
end
function page.update()
end
return page
end
local data = {}
local line
while true do
line = f.readLine()
if line == '' then
break
else
local key, val = line:match('([^ \t]+)[ \t]+(.+)')
data[key:lower()] = val
end
end
local page = {}
page.title = name
page.type = data.type
page.next = data.next
page.prev = data.prev
if data.type:lower() == 'text' then
local pl, tbl
while true do
pl = {}
tbl = nil
line = f.readLine()
if line == nil then
break
else
local prev
local line_ = line:match('^|[ \t]*(.*)')
if line_ then
line = line_
tbl = {'table'}
end
while #line > 0 and line ~= prev do
prev = line
local part
repeat
local title, line_ = line:match('^%[([^%]]+)%](.*)')
if title then
part = {'link', title, title}
line = line_
break
end
local name, title, line_ = line:match('^%(([^%)]+)%)%[([^%]]+)%](.*)')
if name then
part = {'link', name, title}
line = line_
break
end
local text, line_ = line:match('^([^%(%[|]+)(.*)')
if text then
part = {'text', text}
line = line_
break
end
local text, line_ = line:match('^%%(.)(.*)')
if text then
part = {'text', text}
line = line_
break
end
until true
if part then
pl[#pl + 1] = part
end
local line_ = line:match('^|(.*)')
if line_ then
line = line_
tbl = tbl or {'table'}
tbl[#tbl + 1] = pl
pl = {}
end
end
if tbl then
if #pl > 0 then
tbl[#tbl + 1] = pl
end
page[#page + 1] = {tbl}
else
page[#page + 1] = pl
end
end
end
local op = setmetatable({}, { __index = function(t, k)
t[k] = {}
return t[k]
end })
function op.text.width(el)
return #el[2]
end
function op.text.render(el, width)
term.setTextColor(colors.white)
term.write(el[2]:sub(1, width))
end
function op.text.click(el, x) end
function op.link.width(el)
return #el[2]
end
function op.link.render(el, width)
term.setTextColor(colors.lightBlue)
term.write(el[2])
end
function op.link.click(el, x)
switchPage(el[3])
end
local scroll = 0
function page.render()
local width, height = term.getSize()
for i = 1, height do
if page[scroll + i] then
term.setCursorPos(1, i)
for _, el in ipairs(page[scroll + i]) do
local cx, cy = term.getCursorPos()
op[el[1]].render(el, width - cx + 1)
term.setCursorPos(cx + op[el[1]].width(el), cy)
end
end
end
end
function page.update(e, ...)
if e == 'mouse_click' then
local mx = select(2, ...)
local line = page[select(3, ...) + scroll]
if line then
for _, el in ipairs(line) do
local ew = op[el[1]].width(el)
if mx <= ew then
op[el[1]].click(el, mx)
break
end
mx = mx - ew
end
end
end
-- print(e, ...)
end
else
error('invalid page type: ' .. data.type)
end
f.close()
return page
end
bar = {
window = window.create(term.current(), 1, 1, width, height, true);
}
function bar.middle()
local text = curPage.title
if bar.search ~= nil then
text = bar.search
end
if #text > width - 7 then
local over = #text - (width - 7)
text = text:sub(over + 1)
end
return text
end
function bar.render()
term.setCursorPos(1, height)
term.setBackgroundColor(colors.gray)
term.write((' '):rep(width))
term.setCursorPos(width, height)
term.setBackgroundColor(colors.red)
term.write('X')
end
function bar.updatePage()
term.setCursorPos(1, height)
term.setBackgroundColor(#history > 0 and colors.lightBlue or colors.lightGray)
term.write('<')
term.setCursorPos(3, height)
term.setBackgroundColor(curPage.prev and colors.lightBlue or colors.lightGray)
term.write('<')
term.setCursorPos(width - 3, height)
term.setBackgroundColor(curPage.next and colors.lightBlue or colors.lightGray)
term.write('>')
term.setCursorPos(width - 1, height)
term.setBackgroundColor(#futury > 0 and colors.lightBlue or colors.lightGray)
term.write('>')
end
function bar.updateSearchSugs()
bar.searchPat = bar.search
local opts = {}
for _, file in ipairs(fs.find('db/pages/' .. bar.search .. '*')) do
file = file:sub(10)
if file:sub(1, 1) ~= '.' then
opts[#opts + 1] = file
end
end
bar.searchSugs = opts
end
function bar.updateMiddle()
term.setCursorPos(4, height)
term.setBackgroundColor(colors.gray)
term.write((' '):rep(width - 7))
local text = bar.middle()
if bar.search ~= nil then
local prev = term.redirect(content)
content.redraw()
term.redirect(prev)
local opts = bar.searchSugs
local y = height - 1
for _, opt in ipairs(opts) do
term.setCursorPos(4, y)
term.setBackgroundColor(colors.gray)
term.setTextColor(colors.white)
term.write(bar.searchPat)
term.setTextColor(colors.lightGray)
term.write(opt:sub(#bar.searchPat + 1))
term.write((" "):rep(width - 7 - #opt))
y = y - 1
end
end
term.setCursorPos(bar.search == nil and math.ceil(width / 2 - #text / 2) or 4, height)
term.setTextColor(colors.white)
term.setBackgroundColor(bar.search == nil and colors.blue or (fs.exists('db/pages/' .. bar.search) and colors.lightBlue or colors.red))
term.write(text)
end
function bar.update(e, ...)
if e == 'mouse_click' then
local btn, x, y = ...
local middle = bar.middle()
local tx = math.floor(width / 2 - #curPage.title / 2)
if y == height and x >= tx and x < tx + #middle then
if bar.search == nil or btn == 2 then
bar.search = ''
end
bar.updateSearchSugs()
bar.updateMiddle()
elseif y == height and x == 3 and curPage.prev then
switchPage(curPage.prev)
elseif y == height and x == 1 and #history > 0 then
backPage()
elseif y == height and x == width - 3 and curPage.next then
switchPage(curPage.next)
elseif y == height and x == width - 1 and #futury > 0 then
fwdPage()
elseif y == height and x == width then
term.setCursorPos(1, 1)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
error('', 0)
end
elseif e == 'char' and bar.search ~= nil then
bar.search = bar.search .. (...)
bar.updateSearchSugs()
bar.updateMiddle()
elseif e == 'key' and bar.search ~= nil then
if (...) == keys.backspace then
if down[keys.leftAlt] or down[keys.rightAlt] then
bar.search = ''
elseif down[keys.leftCtrl] or down[keys.rightCtrl] then
bar.search = bar.search:gsub('[^ \t!@#%$%%%^&*%(%)%[%]{}\\|:;\'"/%?<>,%.%+_%-`~]+$', '')
else
bar.search = bar.search:sub(1, -2)
end
bar.updateSearchSugs()
bar.updateMiddle()
elseif (...) == 1 then
bar.search = nil
bar.updateMiddle()
elseif (...) == keys.enter then
switchPage(bar.search)
bar.search = nil
elseif (...) == keys.up then
if #bar.search > 0 then
bar.searchSugs[#bar.searchSugs + 1] = bar.search
end
bar.search = table.remove(bar.searchSugs, 1)
bar.updateMiddle()
elseif (...) == keys.down then
if #bar.search > 0 then
table.insert(bar.searchSugs, 1, bar.search)
end
bar.search = table.remove(bar.searchSugs, #bar.searchSugs)
bar.updateMiddle()
end
elseif e == 'key' then
if (...) == keys.left and (down[keys.leftAlt] or down[keys.rightAlt]) and curPage.prev then
switchPage(curPage.prev)
elseif (...) == keys.right and (down[keys.leftAlt] or down[keys.rightAlt]) and curPage.next then
switchPage(curPage.next)
end
end
end
curPage = loadpage('Redstone (API)')
term.clear()
prev = term.redirect(bar.window)
bar.render()
term.redirect(prev)
local prev
while true do
if curPage ~= prevPage then
prev = term.redirect(content)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
curPage.render()
term.redirect(prev)
prev = term.redirect(bar.window)
bar.updatePage()
bar.updateMiddle()
term.redirect(prev)
prevPage = curPage
end
local e = {os.pullEvent()}
if e[1] == 'key' then
down[e[2]] = true
elseif e[1] == 'key_up' then
down[e[2]] = false
end
if (e[1] ~= 'key' and e[1] ~= 'key_up' and e[1] ~= 'char') or bar.search == nil then
prev = term.redirect(content)
curPage.update(unpack(e))
term.redirect(prev)
end
prev = term.redirect(bar.window)
bar.update(unpack(e))
term.redirect(prev)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment