mirror of https://github.com/Hilbis/Hilbish
Compare commits
7 Commits
60f267260b
...
1f5ab90586
Author | SHA1 | Date |
---|---|---|
sammyette | 1f5ab90586 | |
sammyette | 4c6758c732 | |
sammyette | 11da2c0c45 | |
sammyette | 8b672f5b95 | |
sammyette | 0bb97a6f3b | |
sammyette | 713f24aa3e | |
sammyette | cbc5e81c9d |
|
@ -6,6 +6,7 @@
|
||||||
- `read()` method for retrieving input (so now the `in` sink of commanders is useful)
|
- `read()` method for retrieving input (so now the `in` sink of commanders is useful)
|
||||||
- `flush()` and `autoFlush()` related to flushing outputs
|
- `flush()` and `autoFlush()` related to flushing outputs
|
||||||
- `pipe` property to check if a sink with input is a pipe (like stdin)
|
- `pipe` property to check if a sink with input is a pipe (like stdin)
|
||||||
|
- Show indexes on cdr list
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Replaced `sed` in-place editing with `grep` and `mv` for compatibility with BSD utils
|
- Replaced `sed` in-place editing with `grep` and `mv` for compatibility with BSD utils
|
||||||
|
|
|
@ -23,7 +23,7 @@ Inserts text into the line.
|
||||||
|
|
||||||
### getChar() -> string
|
### getChar() -> string
|
||||||
Reads a keystroke from the user. This is in a format
|
Reads a keystroke from the user. This is in a format
|
||||||
of something like Ctrl-L.
|
of something like Ctrl-L..
|
||||||
|
|
||||||
### setVimRegister(register, text)
|
### setVimRegister(register, text)
|
||||||
Sets the vim register at `register` to hold the passed text.
|
Sets the vim register at `register` to hold the passed text.
|
||||||
|
|
|
@ -41,7 +41,7 @@ function hilbish.editor.getVimRegister(register) end
|
||||||
function hilbish.editor.insert(text) end
|
function hilbish.editor.insert(text) end
|
||||||
|
|
||||||
--- Reads a keystroke from the user. This is in a format
|
--- Reads a keystroke from the user. This is in a format
|
||||||
--- of something like Ctrl-L.
|
--- of something like Ctrl-L..
|
||||||
function hilbish.editor.getChar() end
|
function hilbish.editor.getChar() end
|
||||||
|
|
||||||
--- Sets the vim register at `register` to hold the passed text.
|
--- Sets the vim register at `register` to hold the passed text.
|
||||||
|
|
|
@ -10,7 +10,7 @@ cdr: change directory to one which has been recently visied
|
||||||
|
|
||||||
usage: cdr <index>
|
usage: cdr <index>
|
||||||
|
|
||||||
to get a list of recent directories, use {green}{underline}cdr list{reset}]])
|
to get a list of recent directories, use {green}cdr list{reset}]])
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -20,7 +20,10 @@ to get a list of recent directories, use {green}{underline}cdr list{reset}]])
|
||||||
sinks.out:writeln 'No directories have been visited.'
|
sinks.out:writeln 'No directories have been visited.'
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
sinks.out:writeln(table.concat(recentDirs, '\n'))
|
for idx, d in ipairs(dirs.recentDirs) do
|
||||||
|
if d:find(hilbish.home, 1, true) then d = fs.join('~', d:sub(hilbish.home:len() + 1)) end
|
||||||
|
sinks.out:writeln(lunacolors.format(string.format('{cyan}%d{reset} %s', idx, d)))
|
||||||
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,102 @@ local Page = require 'nature.greenhouse.page'
|
||||||
commander.register('greenhouse', function(args, sinks)
|
commander.register('greenhouse', function(args, sinks)
|
||||||
local gh = Greenhouse(sinks.out)
|
local gh = Greenhouse(sinks.out)
|
||||||
|
|
||||||
|
local buffer = ''
|
||||||
|
local display = ''
|
||||||
|
local command = false
|
||||||
|
local commands = {
|
||||||
|
q = function()
|
||||||
|
gh.keybinds['Ctrl-D'](gh)
|
||||||
|
end,
|
||||||
|
['goto'] = function(args)
|
||||||
|
if not args[1] then
|
||||||
|
return 'nuh uh'
|
||||||
|
end
|
||||||
|
gh:jump(tonumber(args[1]))
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
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.isSpecial then
|
||||||
|
offset = self.specialOffset
|
||||||
|
workingPage = self.specialPage
|
||||||
|
end
|
||||||
|
|
||||||
|
self.sink:write(ansikit.getCSI((self.region.height + 2) - self.start.. ';1', 'H'))
|
||||||
|
if not self.isSpecial 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 == '' and display or buffer)
|
||||||
|
end
|
||||||
|
function gh:input(c)
|
||||||
|
-- command handling
|
||||||
|
if c == ':' and not command then
|
||||||
|
command = true
|
||||||
|
end
|
||||||
|
if c == 'Escape' then
|
||||||
|
if command then
|
||||||
|
command = false
|
||||||
|
buffer = ''
|
||||||
|
else
|
||||||
|
if self.isSpecial then gh:special() end
|
||||||
|
end
|
||||||
|
elseif c == 'Backspace' then
|
||||||
|
buffer = buffer:sub(0, -2)
|
||||||
|
if buffer == '' then
|
||||||
|
command = false
|
||||||
|
else
|
||||||
|
goto update
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if command then
|
||||||
|
ansikit.showCursor()
|
||||||
|
if buffer:match '^:' then buffer = buffer .. c else buffer = c end
|
||||||
|
else
|
||||||
|
ansikit.hideCursor()
|
||||||
|
end
|
||||||
|
|
||||||
|
::update::
|
||||||
|
gh:update()
|
||||||
|
end
|
||||||
|
gh:resize()
|
||||||
|
|
||||||
|
gh:keybind('Enter', function(self)
|
||||||
|
if self.isSpecial then
|
||||||
|
self:jump(self.specialPageIdx)
|
||||||
|
self:special(true)
|
||||||
|
else
|
||||||
|
if buffer:len() < 2 then return end
|
||||||
|
|
||||||
|
local splitBuf = string.split(buffer, " ")
|
||||||
|
local command = commands[splitBuf[1]:sub(2)]
|
||||||
|
if command then
|
||||||
|
table.remove(splitBuf, 1)
|
||||||
|
buffer = command(splitBuf) or ''
|
||||||
|
end
|
||||||
|
self:update()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
if sinks['in'].pipe then
|
if sinks['in'].pipe then
|
||||||
local page = Page(sinks['in']:readAll())
|
local page = Page('', sinks['in']:readAll())
|
||||||
gh:addPage(page)
|
gh:addPage(page)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -20,7 +114,7 @@ commander.register('greenhouse', function(args, sinks)
|
||||||
sinks.err:writeln(string.format('could not open file %s', name))
|
sinks.err:writeln(string.format('could not open file %s', name))
|
||||||
end
|
end
|
||||||
|
|
||||||
local page = Page(f:read '*a')
|
local page = Page(name, f:read '*a')
|
||||||
gh:addPage(page)
|
gh:addPage(page)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
-- and flowerbook.
|
-- and flowerbook.
|
||||||
|
|
||||||
local ansikit = require 'ansikit'
|
local ansikit = require 'ansikit'
|
||||||
|
local lunacolors = require 'lunacolors'
|
||||||
local terminal = require 'terminal'
|
local terminal = require 'terminal'
|
||||||
|
local Page = require 'nature.greenhouse.page'
|
||||||
local Object = require 'nature.object'
|
local Object = require 'nature.object'
|
||||||
|
|
||||||
local Greenhouse = Object:extend()
|
local Greenhouse = Object:extend()
|
||||||
|
@ -14,10 +16,21 @@ function Greenhouse:new(sink)
|
||||||
local size = terminal.size()
|
local size = terminal.size()
|
||||||
self.region = size
|
self.region = size
|
||||||
self.start = 1
|
self.start = 1
|
||||||
self.offset = 1
|
self.offset = 1 -- vertical text offset
|
||||||
self.sink = sink
|
self.sink = sink
|
||||||
self.pages = {}
|
self.pages = {}
|
||||||
self.curPage = 1
|
self.curPage = 1
|
||||||
|
self.keybinds = {
|
||||||
|
['Up'] = function(self) self:scroll 'up' end,
|
||||||
|
['Down'] = function(self) self:scroll 'down' end,
|
||||||
|
['Ctrl-Left'] = self.previous,
|
||||||
|
['Ctrl-Right'] = self.next,
|
||||||
|
['Ctrl-N'] = function(self) self:toc(true) end,
|
||||||
|
}
|
||||||
|
self.isSpecial = false
|
||||||
|
self.specialPage = nil
|
||||||
|
self.specialPageIdx = 1
|
||||||
|
self.specialOffset = 1
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
@ -32,22 +45,39 @@ function Greenhouse:updateCurrentPage(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Greenhouse:draw()
|
function Greenhouse:draw()
|
||||||
local lines = self.pages[self.curPage].lines
|
local workingPage = self.pages[self.curPage]
|
||||||
|
local offset = self.offset
|
||||||
|
if self.isSpecial then
|
||||||
|
offset = self.specialOffset
|
||||||
|
workingPage = self.specialPage
|
||||||
|
end
|
||||||
|
|
||||||
|
local lines = workingPage.lines
|
||||||
self.sink:write(ansikit.getCSI(self.start .. ';1', 'H'))
|
self.sink:write(ansikit.getCSI(self.start .. ';1', 'H'))
|
||||||
self.sink:write(ansikit.getCSI(2, 'J'))
|
self.sink:write(ansikit.getCSI(2, 'J'))
|
||||||
|
|
||||||
-- the -2 negate is for the command and status line
|
-- 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
|
if i > #lines then break end
|
||||||
self.sink:writeln('\r' .. lines[i]:gsub('\t', ' '):sub(0, self.region.width - 2))
|
self.sink:writeln('\r' .. lines[i]:gsub('\t', ' '):sub(0, self.region.width - 2))
|
||||||
end
|
end
|
||||||
self.sink:write '\r'
|
self.sink:write '\r'
|
||||||
|
self:render()
|
||||||
|
end
|
||||||
|
|
||||||
self.sink:write(ansikit.getCSI(self.region.height - self.start.. ';1', 'H'))
|
function Greenhouse:render()
|
||||||
self.sink:writeln(string.format('\27[0mPage %d', self.curPage))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Greenhouse:scroll(direction)
|
function Greenhouse:scroll(direction)
|
||||||
|
if self.isSpecial 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 lines = self.pages[self.curPage].lines
|
||||||
|
|
||||||
local oldOffset = self.offset
|
local oldOffset = self.offset
|
||||||
|
@ -61,28 +91,96 @@ function Greenhouse:scroll(direction)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Greenhouse:update()
|
function Greenhouse:update()
|
||||||
local size = terminal.size()
|
self:resize()
|
||||||
self.region = size
|
if self.isSpecial then
|
||||||
|
self:special()
|
||||||
|
end
|
||||||
|
|
||||||
self:draw()
|
self:draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Greenhouse:next()
|
function Greenhouse:special()
|
||||||
local oldCurrent = self.curPage
|
self.isSpecial = not self.isSpecial
|
||||||
self.curPage = math.min(self.curPage + 1, #self.pages)
|
end
|
||||||
if self.curPage ~= oldCurrent then
|
|
||||||
|
function Greenhouse:toc(toggle)
|
||||||
|
if not self.isSpecial then
|
||||||
|
self.specialPageIdx = self.curPage
|
||||||
|
end
|
||||||
|
if toggle then self.isSpecial = not self.isSpecial 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.specialPageIdx then
|
||||||
|
title = lunacolors.invert(title)
|
||||||
|
end
|
||||||
|
|
||||||
|
tocText = tocText .. title .. '\n'
|
||||||
|
end
|
||||||
|
self.specialPage = Page('TOC', tocText)
|
||||||
|
self:draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Greenhouse:resize()
|
||||||
|
local size = terminal.size()
|
||||||
|
self.region = size
|
||||||
|
end
|
||||||
|
|
||||||
|
function Greenhouse:next(special)
|
||||||
|
local oldCurrent = special and self.specialPageIdx or self.curPage
|
||||||
|
local pageIdx = math.min(oldCurrent + 1, #self.pages)
|
||||||
|
|
||||||
|
if special then
|
||||||
|
self.specialPageIdx = pageIdx
|
||||||
|
else
|
||||||
|
self.curPage = pageIdx
|
||||||
|
end
|
||||||
|
|
||||||
|
if pageIdx ~= oldCurrent then
|
||||||
self.offset = 1
|
self.offset = 1
|
||||||
self:draw()
|
self:update()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Greenhouse:previous()
|
function Greenhouse:previous(special)
|
||||||
local oldCurrent = self.curPage
|
local oldCurrent = special and self.specialPageIdx or self.curPage
|
||||||
self.curPage = math.max(self.curPage - 1, 1)
|
local pageIdx = math.max(self.curPage - 1, 1)
|
||||||
if self.curPage ~= oldCurrent then
|
|
||||||
self.offset = 1
|
if special then
|
||||||
self:draw()
|
self.specialPageIdx = pageIdx
|
||||||
|
else
|
||||||
|
self.curPage = pageIdx
|
||||||
end
|
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:input(char)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Greenhouse:initUi()
|
function Greenhouse:initUi()
|
||||||
|
@ -104,25 +202,22 @@ function Greenhouse:initUi()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
ansikit.screenAlt()
|
ansikit.screenAlt()
|
||||||
|
ansikit.hideCursor()
|
||||||
ansikit.clear(true)
|
ansikit.clear(true)
|
||||||
self:draw()
|
self:draw()
|
||||||
|
|
||||||
hilbish.goro(function()
|
hilbish.goro(function()
|
||||||
while not done do
|
while not done do
|
||||||
local c = read()
|
local c = read()
|
||||||
if c == 'Ctrl-D' then
|
self:keybind('Ctrl-D', function()
|
||||||
done = true
|
done = true
|
||||||
end
|
end)
|
||||||
|
|
||||||
if c == 'Up' then
|
if self.keybinds[c] then
|
||||||
self:scroll 'up'
|
self.keybinds[c](self)
|
||||||
|
else
|
||||||
|
self:input(c)
|
||||||
end
|
end
|
||||||
if c == 'Down' then
|
|
||||||
self:scroll 'down'
|
|
||||||
end
|
|
||||||
|
|
||||||
if c == 'Ctrl-Right' then self:next() end
|
|
||||||
if c == 'Ctrl-Left' then self:previous() end
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
if c == 27 then
|
if c == 27 then
|
||||||
|
@ -161,6 +256,7 @@ function Greenhouse:initUi()
|
||||||
while not done do
|
while not done do
|
||||||
--
|
--
|
||||||
end
|
end
|
||||||
|
ansikit.showCursor()
|
||||||
ansikit.screenMain()
|
ansikit.screenMain()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,17 @@ local Object = require 'nature.object'
|
||||||
|
|
||||||
local Page = Object:extend()
|
local Page = Object:extend()
|
||||||
|
|
||||||
function Page:new(text)
|
function Page:new(title, text)
|
||||||
self:setText(text)
|
self:setText(text)
|
||||||
|
self.title = title or 'Page'
|
||||||
end
|
end
|
||||||
|
|
||||||
function Page:setText(text)
|
function Page:setText(text)
|
||||||
self.lines = string.split(text, '\n')
|
self.lines = string.split(text, '\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Page:setTitle(title)
|
||||||
|
self.title = title
|
||||||
|
end
|
||||||
|
|
||||||
return Page
|
return Page
|
||||||
|
|
|
@ -155,10 +155,8 @@ func (rl *Instance) ReadChar() string {
|
||||||
case charCtrlG: return "Ctrl-G"
|
case charCtrlG: return "Ctrl-G"
|
||||||
case charBackspace, charBackspace2: return "Backspace"
|
case charBackspace, charBackspace2: return "Backspace"
|
||||||
case charTab: return "Tab"
|
case charTab: return "Tab"
|
||||||
case charCtrlJ: return "Ctrl-J"
|
|
||||||
case charCtrlK: return "Ctrl-K"
|
case charCtrlK: return "Ctrl-K"
|
||||||
case charCtrlL: return "Ctrl-L"
|
case charCtrlL: return "Ctrl-L"
|
||||||
case charCtrlM: return "Ctrl-M"
|
|
||||||
case charCtrlN: return "Ctrl-N"
|
case charCtrlN: return "Ctrl-N"
|
||||||
case charCtrlO: return "Ctrl-O"
|
case charCtrlO: return "Ctrl-O"
|
||||||
case charCtrlP: return "Ctrl-P"
|
case charCtrlP: return "Ctrl-P"
|
||||||
|
@ -172,6 +170,8 @@ func (rl *Instance) ReadChar() string {
|
||||||
case charCtrlX: return "Ctrl-X"
|
case charCtrlX: return "Ctrl-X"
|
||||||
case charCtrlY: return "Ctrl-Y"
|
case charCtrlY: return "Ctrl-Y"
|
||||||
case charCtrlZ: return "Ctrl-Z"
|
case charCtrlZ: return "Ctrl-Z"
|
||||||
|
case '\r': fallthrough
|
||||||
|
case '\n': return "Enter"
|
||||||
case charEscape:
|
case charEscape:
|
||||||
switch s {
|
switch s {
|
||||||
case string(charEscape): return "Escape"
|
case string(charEscape): return "Escape"
|
||||||
|
@ -188,5 +188,5 @@ func (rl *Instance) ReadChar() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "???"
|
return s
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue