update
This commit is contained in:
parent
b9fa638633
commit
d8e4a92790
20
erasing.go
Normal file
20
erasing.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "github.com/c-bata/go-prompt-toolkit/prompt"
|
||||
|
||||
func main() {
|
||||
l := 20
|
||||
out := prompt.NewVT100Writer()
|
||||
for i := 0; i < l; i++ {
|
||||
out.CursorGoTo(i, 0)
|
||||
out.WriteStr("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
|
||||
}
|
||||
|
||||
|
||||
out.CursorGoTo(5, 10)
|
||||
out.EraseLine()
|
||||
|
||||
out.CursorGoTo(l, 0)
|
||||
out.Flush()
|
||||
return
|
||||
}
|
106
main.go
106
main.go
@ -3,18 +3,18 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/c-bata/go-prompt-toolkit/prompt"
|
||||
)
|
||||
|
||||
func enterAlternateScreen(fd int) {
|
||||
syscall.Write(fd, []byte{0x1b, 0x5b, 0x3f, 0x01, 0x00, 0x04, 0x09, 0x68, 0x1b, 0x5b, 0x48})
|
||||
}
|
||||
|
||||
func scroll(out *prompt.VT100Writer, lines int) {
|
||||
for i := 0; i < lines; i++ {
|
||||
out.ScrollDown()
|
||||
defer out.ScrollUp()
|
||||
}
|
||||
for i := 0; i < lines; i++ {
|
||||
out.ScrollUp()
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -23,8 +23,14 @@ func main() {
|
||||
in := prompt.NewVT100Parser()
|
||||
in.Setup()
|
||||
defer in.TearDown()
|
||||
defer fmt.Println("\nexited!")
|
||||
defer fmt.Println("\nGoodbye!")
|
||||
out := prompt.NewVT100Writer()
|
||||
|
||||
renderer := prompt.Render{
|
||||
Prefix: ">>> ",
|
||||
Out: out,
|
||||
}
|
||||
|
||||
out.SetTitle("はろー")
|
||||
scroll(out, 7)
|
||||
out.Flush()
|
||||
@ -32,68 +38,27 @@ func main() {
|
||||
bufCh := make(chan []byte, 128)
|
||||
go readBuffer(bufCh)
|
||||
|
||||
winSizeCh := make(chan *prompt.WinSize, 128)
|
||||
go updateWindowSize(in, winSizeCh)
|
||||
|
||||
buffer := prompt.NewBuffer()
|
||||
|
||||
for {
|
||||
b := <-bufCh
|
||||
if ac := in.GetASCIICode(b); ac == nil {
|
||||
out.EraseDown()
|
||||
out.WriteRaw(b)
|
||||
ac := in.GetASCIICode(b)
|
||||
if ac == nil {
|
||||
buffer.InsertText(string(b), false, true)
|
||||
} else if ac.Key == prompt.Enter || ac.Key == prompt.ControlJ {
|
||||
out.EraseDown()
|
||||
out.WriteStr(buffer.Document().TextAfterCursor())
|
||||
|
||||
out.WriteStr("\n>>> Your input: '")
|
||||
out.WriteStr(buffer.Text())
|
||||
out.WriteStr("' <<<\n")
|
||||
buffer = prompt.NewBuffer()
|
||||
} else if ac.Key == prompt.Left {
|
||||
l := buffer.CursorLeft(1)
|
||||
if l == 0 {
|
||||
continue
|
||||
}
|
||||
out.EraseLine()
|
||||
out.EraseDown()
|
||||
after := buffer.Document().CurrentLine()
|
||||
out.WriteStr(after)
|
||||
out.CursorBackward(len(after) - buffer.CursorPosition)
|
||||
} else if ac.Key == prompt.Right {
|
||||
l := buffer.CursorRight(1)
|
||||
if l == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
out.CursorForward(l)
|
||||
out.WriteRaw(b)
|
||||
out.EraseDown()
|
||||
after := buffer.Document().TextAfterCursor()
|
||||
out.WriteStr(after)
|
||||
} else if ac.Key == prompt.Backspace {
|
||||
deleted := buffer.DeleteBeforeCursor(1)
|
||||
if deleted == "" {
|
||||
continue
|
||||
}
|
||||
out.CursorBackward(1)
|
||||
out.EraseDown()
|
||||
|
||||
after := buffer.Document().TextAfterCursor()
|
||||
out.WriteStr(after)
|
||||
} else if ac.Key == prompt.Tab || ac.Key == prompt.ControlI {
|
||||
} else if ac.Key == prompt.BackTab {
|
||||
} else if ac.Key == prompt.Right {
|
||||
buffer.CursorRight(1)
|
||||
} else if ac.Key == prompt.ControlT {
|
||||
enterAlternateScreen(syscall.Stdout)
|
||||
} else if ac.Key == prompt.ControlC {
|
||||
out.EraseDown()
|
||||
out.ClearTitle()
|
||||
out.Flush()
|
||||
return
|
||||
} else if ac.Key == prompt.Up || ac.Key == prompt.Down {
|
||||
} else {
|
||||
out.WriteRaw(b)
|
||||
//buffer.InsertText(ac.Key.String(), false, true)
|
||||
prompt.InputHandler(ac, buffer, out)
|
||||
}
|
||||
|
||||
// Display completions
|
||||
@ -132,6 +97,8 @@ func main() {
|
||||
out.SetColor("default", "default")
|
||||
}
|
||||
|
||||
completions := []string{"select", "insert", "update", "where"}
|
||||
renderer.Render(buffer, completions)
|
||||
scroll(out, 4)
|
||||
out.Flush()
|
||||
}
|
||||
@ -146,3 +113,36 @@ func readBuffer(bufCh chan []byte) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateWindowSize(in *prompt.VT100Parser, winSizeCh chan *prompt.WinSize) {
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(
|
||||
sigCh,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGQUIT,
|
||||
syscall.SIGWINCH,
|
||||
)
|
||||
|
||||
for {
|
||||
s := <-sigCh
|
||||
switch s {
|
||||
// kill -SIGHUP XXXX
|
||||
case syscall.SIGHUP:
|
||||
|
||||
// kill -SIGINT XXXX or Ctrl+c
|
||||
case syscall.SIGINT:
|
||||
|
||||
// kill -SIGTERM XXXX
|
||||
case syscall.SIGTERM:
|
||||
|
||||
// kill -SIGQUIT XXXX
|
||||
case syscall.SIGQUIT:
|
||||
|
||||
case syscall.SIGWINCH:
|
||||
winSizeCh <- in.GetWinSize()
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
prompt/completions.go
Normal file
24
prompt/completions.go
Normal file
@ -0,0 +1,24 @@
|
||||
package prompt
|
||||
|
||||
type Completion struct {
|
||||
// The new string that will be inserted into document.
|
||||
text string
|
||||
// Position relative to the cursor position where the new text will start.
|
||||
startPosition int
|
||||
}
|
||||
|
||||
func (c *Completion) NewCompletionFromPosition(position int) *Completion {
|
||||
if position < c.startPosition {
|
||||
panic("position argument must be smaller than start position.")
|
||||
}
|
||||
|
||||
return &Completion{
|
||||
text: c.text[position - c.startPosition:],
|
||||
}
|
||||
}
|
||||
|
||||
func NewCompletion(text string) *Completion {
|
||||
return &Completion{
|
||||
text: text,
|
||||
}
|
||||
}
|
6
prompt/input.go
Normal file
6
prompt/input.go
Normal file
@ -0,0 +1,6 @@
|
||||
package prompt
|
||||
|
||||
type WinSize struct {
|
||||
Row uint16
|
||||
Col uint16
|
||||
}
|
63
prompt/key_binding.go
Normal file
63
prompt/key_binding.go
Normal file
@ -0,0 +1,63 @@
|
||||
package prompt
|
||||
|
||||
var InputHandler = defaultHandler
|
||||
|
||||
func defaultHandler(ac *ASCIICode, buffer *Buffer, out *VT100Writer) {
|
||||
switch ac.Key {
|
||||
case ControlJ: // this is equivalent with Enter Key.
|
||||
fallthrough
|
||||
case Enter:
|
||||
out.EraseDown()
|
||||
out.WriteStr(buffer.Document().TextAfterCursor())
|
||||
|
||||
out.WriteStr("\n>>> Your input: '")
|
||||
out.WriteStr(buffer.Text())
|
||||
out.WriteStr("' <<<\n")
|
||||
buffer = NewBuffer()
|
||||
case Left:
|
||||
l := buffer.CursorLeft(1)
|
||||
if l == 0 {
|
||||
return
|
||||
}
|
||||
out.EraseLine()
|
||||
out.EraseDown()
|
||||
after := buffer.Document().CurrentLine()
|
||||
out.WriteStr(after)
|
||||
out.CursorBackward(len(after) - buffer.CursorPosition)
|
||||
case Right:
|
||||
l := buffer.CursorRight(1)
|
||||
if l == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
out.CursorForward(l)
|
||||
out.WriteRaw(ac.ASCIICode)
|
||||
out.EraseDown()
|
||||
after := buffer.Document().TextAfterCursor()
|
||||
out.WriteStr(after)
|
||||
case Backspace:
|
||||
deleted := buffer.DeleteBeforeCursor(1)
|
||||
if deleted == "" {
|
||||
return
|
||||
}
|
||||
out.CursorBackward(1)
|
||||
out.EraseDown()
|
||||
|
||||
after := buffer.Document().TextAfterCursor()
|
||||
out.WriteStr(after)
|
||||
case ControlI: // this is equivalent with TabKey.
|
||||
fallthrough
|
||||
case Tab:
|
||||
break
|
||||
case ControlT:
|
||||
break
|
||||
return
|
||||
case Up:
|
||||
break
|
||||
case Down:
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
21
prompt/render.go
Normal file
21
prompt/render.go
Normal file
@ -0,0 +1,21 @@
|
||||
package prompt
|
||||
|
||||
type Render struct {
|
||||
Prefix string
|
||||
Out *VT100Writer
|
||||
row uint16
|
||||
col uint16 // sigwinchで送られてくる列数を常に見ながら、prefixのlengthとbufferのcursor positionを比べて、completionの表示位置をずらす
|
||||
}
|
||||
|
||||
func (r *Render) UpdateWinSize(ws WinSize) {
|
||||
r.row = ws.Row
|
||||
r.col = ws.Col
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Render) renderCompletion(words []string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Render) Render(buffer *Buffer, completions []string) {
|
||||
}
|
@ -53,7 +53,7 @@ func (t *VT100Parser) GetASCIICode(b []byte) *ASCIICode {
|
||||
}
|
||||
|
||||
// GetWinSize returns winsize struct which is the response of ioctl(2).
|
||||
func (t *VT100Parser) GetWinSize() (row, col uint16) {
|
||||
func (t *VT100Parser) GetWinSize() *WinSize {
|
||||
ws := &ioctlWinsize{}
|
||||
retCode, _, errno := syscall.Syscall(
|
||||
syscall.SYS_IOCTL,
|
||||
@ -64,7 +64,10 @@ func (t *VT100Parser) GetWinSize() (row, col uint16) {
|
||||
if int(retCode) == -1 {
|
||||
panic(errno)
|
||||
}
|
||||
return ws.Row, ws.Col
|
||||
return &WinSize{
|
||||
Row: ws.Row,
|
||||
Col: ws.Col,
|
||||
}
|
||||
}
|
||||
|
||||
var asciiSequences []*ASCIICode = []*ASCIICode{
|
||||
|
Loading…
Reference in New Issue
Block a user