mirror of https://github.com/Hilbis/Hilbish
feat: add table of contents to pager
another change in this commit is having a separate render function for the greenhouse caller to handle ui this means there isnt a hardcoded space at the bottom to display command and status linepull/240/head
parent
713f24aa3e
commit
0bb97a6f3b
|
@ -8,9 +8,45 @@ local Page = require 'nature.greenhouse.page'
|
|||
|
||||
commander.register('greenhouse', function(args, sinks)
|
||||
local gh = Greenhouse(sinks.out)
|
||||
function gh:resize()
|
||||
local size = terminal.size()
|
||||
self.region = {
|
||||
width = size.width,
|
||||
height = size.height - 2
|
||||
}
|
||||
end
|
||||
local oldDraw = gh.draw
|
||||
function gh:draw()
|
||||
oldDraw(self)
|
||||
local workingPage = self.pages[self.curPage]
|
||||
local offset = self.offset
|
||||
if self.isToc then
|
||||
offset = self.tocOffset
|
||||
workingPage = self.tocPage
|
||||
end
|
||||
|
||||
self.sink:write(ansikit.getCSI((self.region.height + 2) - self.start.. ';1', 'H'))
|
||||
if not self.isToc then
|
||||
self.sink:write(string.format('\27[0mPage %d', self.curPage))
|
||||
if workingPage.title ~= '' then
|
||||
self.sink:writeln(' — ' .. workingPage.title)
|
||||
else
|
||||
self.sink:writeln('')
|
||||
end
|
||||
end
|
||||
self.sink:write(buffer)
|
||||
end
|
||||
gh:resize()
|
||||
|
||||
gh:keybind('Enter', function(self)
|
||||
if self.isToc then
|
||||
self:jump(self.tocPageIdx)
|
||||
self:toc(true)
|
||||
end
|
||||
end)
|
||||
|
||||
if sinks['in'].pipe then
|
||||
local page = Page(sinks['in']:readAll())
|
||||
local page = Page('', sinks['in']:readAll())
|
||||
gh:addPage(page)
|
||||
end
|
||||
|
||||
|
@ -20,7 +56,7 @@ commander.register('greenhouse', function(args, sinks)
|
|||
sinks.err:writeln(string.format('could not open file %s', name))
|
||||
end
|
||||
|
||||
local page = Page(f:read '*a')
|
||||
local page = Page(name, f:read '*a')
|
||||
gh:addPage(page)
|
||||
end
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
-- and flowerbook.
|
||||
|
||||
local ansikit = require 'ansikit'
|
||||
local lunacolors = require 'lunacolors'
|
||||
local terminal = require 'terminal'
|
||||
local Page = require 'nature.greenhouse.page'
|
||||
local Object = require 'nature.object'
|
||||
|
||||
local Greenhouse = Object:extend()
|
||||
|
@ -14,7 +16,7 @@ function Greenhouse:new(sink)
|
|||
local size = terminal.size()
|
||||
self.region = size
|
||||
self.start = 1
|
||||
self.offset = 1
|
||||
self.offset = 1 -- vertical text offset
|
||||
self.sink = sink
|
||||
self.pages = {}
|
||||
self.curPage = 1
|
||||
|
@ -22,8 +24,13 @@ function Greenhouse:new(sink)
|
|||
['Up'] = function(self) self:scroll 'up' end,
|
||||
['Down'] = function(self) self:scroll 'down' end,
|
||||
['Ctrl-Left'] = self.previous,
|
||||
['Ctrl-Right'] = self.next
|
||||
['Ctrl-Right'] = self.next,
|
||||
['Ctrl-N'] = function(self) self:toc(true) end,
|
||||
}
|
||||
self.isToc = false
|
||||
self.tocPage = nil
|
||||
self.tocPageIdx = 1
|
||||
self.tocOffset = 1
|
||||
|
||||
return self
|
||||
end
|
||||
|
@ -38,22 +45,39 @@ function Greenhouse:updateCurrentPage(text)
|
|||
end
|
||||
|
||||
function Greenhouse:draw()
|
||||
local lines = self.pages[self.curPage].lines
|
||||
local workingPage = self.pages[self.curPage]
|
||||
local offset = self.offset
|
||||
if self.isToc then
|
||||
offset = self.tocOffset
|
||||
workingPage = self.tocPage
|
||||
end
|
||||
|
||||
local lines = workingPage.lines
|
||||
self.sink:write(ansikit.getCSI(self.start .. ';1', 'H'))
|
||||
self.sink:write(ansikit.getCSI(2, 'J'))
|
||||
|
||||
-- the -2 negate is for the command and status line
|
||||
for i = self.offset, self.offset + (self.region.height - self.start) - 2 do
|
||||
for i = offset, offset + (self.region.height - self.start) do
|
||||
if i > #lines then break end
|
||||
self.sink:writeln('\r' .. lines[i]:gsub('\t', ' '):sub(0, self.region.width - 2))
|
||||
end
|
||||
self.sink:write '\r'
|
||||
self:render()
|
||||
end
|
||||
|
||||
self.sink:write(ansikit.getCSI(self.region.height - self.start.. ';1', 'H'))
|
||||
self.sink:writeln(string.format('\27[0mPage %d', self.curPage))
|
||||
function Greenhouse:render()
|
||||
end
|
||||
|
||||
function Greenhouse:scroll(direction)
|
||||
if self.isToc then
|
||||
if direction == 'down' then
|
||||
self:next(true)
|
||||
elseif direction == 'up' then
|
||||
self:previous(true)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local lines = self.pages[self.curPage].lines
|
||||
|
||||
local oldOffset = self.offset
|
||||
|
@ -67,34 +91,91 @@ function Greenhouse:scroll(direction)
|
|||
end
|
||||
|
||||
function Greenhouse:update()
|
||||
local size = terminal.size()
|
||||
self.region = size
|
||||
self:resize()
|
||||
if self.isToc then
|
||||
self:toc()
|
||||
end
|
||||
|
||||
self:draw()
|
||||
end
|
||||
|
||||
function Greenhouse:next()
|
||||
local oldCurrent = self.curPage
|
||||
self.curPage = math.min(self.curPage + 1, #self.pages)
|
||||
if self.curPage ~= oldCurrent then
|
||||
function Greenhouse:resize()
|
||||
local size = terminal.size()
|
||||
self.region = size
|
||||
end
|
||||
|
||||
function Greenhouse:next(toc)
|
||||
local oldCurrent = toc and self.tocPageIdx or self.curPage
|
||||
local pageIdx = math.min(oldCurrent + 1, #self.pages)
|
||||
|
||||
if toc then
|
||||
self.tocPageIdx = pageIdx
|
||||
else
|
||||
self.curPage = pageIdx
|
||||
end
|
||||
|
||||
if pageIdx ~= oldCurrent then
|
||||
self.offset = 1
|
||||
self:draw()
|
||||
self:update()
|
||||
end
|
||||
end
|
||||
|
||||
function Greenhouse:previous()
|
||||
local oldCurrent = self.curPage
|
||||
self.curPage = math.max(self.curPage - 1, 1)
|
||||
if self.curPage ~= oldCurrent then
|
||||
self.offset = 1
|
||||
self:draw()
|
||||
function Greenhouse:previous(toc)
|
||||
local oldCurrent = toc and self.tocPageIdx or self.curPage
|
||||
local pageIdx = math.max(self.curPage - 1, 1)
|
||||
|
||||
if toc then
|
||||
self.tocPageIdx = pageIdx
|
||||
else
|
||||
self.curPage = pageIdx
|
||||
end
|
||||
|
||||
if pageIdx ~= oldCurrent then
|
||||
self.offset = 1
|
||||
self:update()
|
||||
end
|
||||
end
|
||||
|
||||
function Greenhouse:jump(idx)
|
||||
if idx ~= self.curPage then
|
||||
self.offset = 1
|
||||
end
|
||||
self.curPage = idx
|
||||
self:update()
|
||||
end
|
||||
|
||||
function Greenhouse:keybind(key, callback)
|
||||
self.keybinds[key] = callback
|
||||
end
|
||||
|
||||
function Greenhouse:toc(toggle)
|
||||
if not self.isToc then
|
||||
self.tocPageIdx = self.curPage
|
||||
end
|
||||
if toggle then self.isToc = not self.isToc end
|
||||
-- Generate a special page for our table of contents
|
||||
local tocText = string.format([[
|
||||
%s
|
||||
|
||||
]], lunacolors.cyan(lunacolors.bold '―― Table of Contents ――'))
|
||||
|
||||
local genericPageCount = 1
|
||||
for i, page in ipairs(self.pages) do
|
||||
local title = page.title
|
||||
if title == 'Page' then
|
||||
title = 'Page #' .. genericPageCount
|
||||
genericPageCount = genericPageCount + 1
|
||||
end
|
||||
if i == self.tocPageIdx then
|
||||
title = lunacolors.invert(title)
|
||||
end
|
||||
|
||||
tocText = tocText .. title .. '\n'
|
||||
end
|
||||
self.tocPage = Page('TOC', tocText)
|
||||
self:draw()
|
||||
end
|
||||
|
||||
function Greenhouse:initUi()
|
||||
local ansikit = require 'ansikit'
|
||||
local bait = require 'bait'
|
||||
|
|
|
@ -2,12 +2,17 @@ local Object = require 'nature.object'
|
|||
|
||||
local Page = Object:extend()
|
||||
|
||||
function Page:new(text)
|
||||
function Page:new(title, text)
|
||||
self:setText(text)
|
||||
self.title = title or 'Page'
|
||||
end
|
||||
|
||||
function Page:setText(text)
|
||||
self.lines = string.split(text, '\n')
|
||||
end
|
||||
|
||||
function Page:setTitle(title)
|
||||
self.title = title
|
||||
end
|
||||
|
||||
return Page
|
||||
|
|
|
@ -155,10 +155,8 @@ func (rl *Instance) ReadChar() string {
|
|||
case charCtrlG: return "Ctrl-G"
|
||||
case charBackspace, charBackspace2: return "Backspace"
|
||||
case charTab: return "Tab"
|
||||
case charCtrlJ: return "Ctrl-J"
|
||||
case charCtrlK: return "Ctrl-K"
|
||||
case charCtrlL: return "Ctrl-L"
|
||||
case charCtrlM: return "Ctrl-M"
|
||||
case charCtrlN: return "Ctrl-N"
|
||||
case charCtrlO: return "Ctrl-O"
|
||||
case charCtrlP: return "Ctrl-P"
|
||||
|
@ -172,6 +170,8 @@ func (rl *Instance) ReadChar() string {
|
|||
case charCtrlX: return "Ctrl-X"
|
||||
case charCtrlY: return "Ctrl-Y"
|
||||
case charCtrlZ: return "Ctrl-Z"
|
||||
case '\r': fallthrough
|
||||
case '\n': return "Enter"
|
||||
case charEscape:
|
||||
switch s {
|
||||
case string(charEscape): return "Escape"
|
||||
|
|
Loading…
Reference in New Issue