feat: add getChar function to editor interface

this is a simple command that returns a single key from the user.
this can be used to read keystrokes in an interactive program
like how greenhouse (the pager) does it
pull/240/head
sammyette 2023-07-09 16:27:11 -04:00
parent 4a3ceed39c
commit b6315639b2
Signed by: sammyette
GPG Key ID: 904FC49417B44DCD
4 changed files with 79 additions and 6 deletions

View File

@ -16,6 +16,7 @@ func editorLoader(rtm *rt.Runtime) *rt.Table {
"setVimRegister": {editorSetRegister, 1, false}, "setVimRegister": {editorSetRegister, 1, false},
"getVimRegister": {editorGetRegister, 2, false}, "getVimRegister": {editorGetRegister, 2, false},
"getLine": {editorGetLine, 0, false}, "getLine": {editorGetLine, 0, false},
"readChar": {editorReadChar, 0, false},
} }
mod := rt.NewTable() mod := rt.NewTable()
@ -94,3 +95,13 @@ func editorGetLine(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
} }
// #interface editor
// getChar() -> string
// Reads a keystroke from the user. This is in a format
// of something like Ctrl-L..
func editorReadChar(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
buf := lr.rl.ReadChar()
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
}

View File

@ -60,7 +60,7 @@ Available sections: ]] .. table.concat(modules, ', ')
return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.md', ''))) return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.md', '')))
end) end)
if #moddocs ~= 0 then if #moddocs ~= 0 then
funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ') funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ') .. '\nLMAO'
end end
local valsStr = funcdocs:match '%-%-%-\n([^%-%-%-]+)\n' local valsStr = funcdocs:match '%-%-%-\n([^%-%-%-]+)\n'

View File

@ -110,10 +110,21 @@ function Greenhouse:initUi()
hilbish.goro(function() hilbish.goro(function()
while not done do while not done do
local c = read() local c = read()
if c == 3 then if c == 'Ctrl-D' then
done = true done = true
end end
if c == 'Up' then
self:scroll 'up'
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
local c1 = read() local c1 = read()
if c1 == 91 then if c1 == 91 then
@ -141,8 +152,7 @@ function Greenhouse:initUi()
end end
goto continue goto continue
end end
print('\nchar:') ]]--
print(c)
::continue:: ::continue::
end end
@ -157,10 +167,10 @@ end
function read() function read()
terminal.saveState() terminal.saveState()
terminal.setRaw() terminal.setRaw()
local c = io.read(1) local c = hilbish.editor.readChar()
terminal.restoreState() terminal.restoreState()
return c:byte() return c
end end
return Greenhouse return Greenhouse

View File

@ -1,5 +1,7 @@
package readline package readline
import "os"
// Character codes // Character codes
const ( const (
charCtrlA = iota + 1 charCtrlA = iota + 1
@ -134,3 +136,53 @@ const (
const ( const (
seqCtermFg255 = "\033[48;5;255m" seqCtermFg255 = "\033[48;5;255m"
) )
// TODO: return whether its actually a sequence or not
// remedies the edge case of someone literally typing Ctrl-A for example.
func (rl *Instance) ReadChar() string {
b := make([]byte, 1024)
i, _ := os.Stdin.Read(b)
r := []rune(string(b))
s := string(r[:i])
switch b[0] {
case charCtrlA: return "Ctrl-A"
case charCtrlB: return "Ctrl-B"
case charCtrlC: return "Ctrl-C"
case charEOF: return "Ctrl-D"
case charCtrlE: return "Ctrl-E"
case charCtrlF: return "Ctrl-F"
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"
case charCtrlQ: return "Ctrl-Q"
case charCtrlR: return "Ctrl-R"
case charCtrlS: return "Ctrl-S"
case charCtrlT: return "Ctrl-T"
case charCtrlU: return "Ctrl-U"
case charCtrlV: return "Ctrl-V"
case charCtrlW: return "Ctrl-W"
case charCtrlX: return "Ctrl-X"
case charCtrlY: return "Ctrl-Y"
case charCtrlZ: return "Ctrl-Z"
case charEscape:
switch s {
case string(charEscape): return "Escape"
case seqUp: return "Up"
case seqDown: return "Down"
case seqBackwards: return "Left"
case seqForwards: return "Right"
case seqCtrlLeftArrow: return "Ctrl-Left"
case seqCtrlRightArrow: return "Ctrl-Right"
}
}
return "???"
}