1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
package main
import (
"fmt"
"io"
"os"
"os/exec"
"github.com/gdamore/tcell"
"github.com/hinshun/vt10x"
"github.com/kr/pty"
)
func main() {
err := goterm()
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}
func goterm() error {
cmd := exec.Command(os.Getenv("SHELL"), "-i")
ptm, err := pty.Start(cmd)
if err != nil {
return err
}
// f, err := os.OpenFile("debug.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
// if err != nil {
// return err
// }
// state := vt10x.State{
// DebugLogger: log.New(f, "", log.LstdFlags),
// }
var state vt10x.State
term, err := vt10x.Create(&state, ptm)
if err != nil {
return err
}
defer term.Close()
s, err := tcell.NewScreen()
if err != nil {
return err
}
defer s.Fini()
err = s.Init()
if err != nil {
return err
}
width, height := s.Size()
vt10x.ResizePty(ptm, width, height)
term.Resize(width, height)
endc := make(chan bool)
updatec := make(chan struct{}, 1)
go func() {
defer close(endc)
for {
err := term.Parse()
if err != nil {
fmt.Fprintln(os.Stderr, err)
break
}
select {
case updatec <- struct{}{}:
default:
}
}
}()
go func() {
io.Copy(ptm, os.Stdin)
}()
eventc := make(chan tcell.Event, 4)
go func() {
for {
eventc <- s.PollEvent()
}
}()
for {
select {
case event := <-eventc:
switch ev := event.(type) {
case *tcell.EventResize:
width, height = ev.Size()
vt10x.ResizePty(ptm, width, height)
term.Resize(width, height)
s.Sync()
}
case <-endc:
return nil
case <-updatec:
update(s, &state, width, height)
}
}
}
func update(s tcell.Screen, state *vt10x.State, w, h int) {
state.Lock()
defer state.Unlock()
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
c, fg, bg := state.Cell(x, y)
style := tcell.StyleDefault
if fg != vt10x.DefaultFG {
style = style.Foreground(tcell.Color(fg))
}
if bg != vt10x.DefaultBG {
style = style.Background(tcell.Color(bg))
}
s.SetContent(x, y, c, nil, style)
}
}
if state.CursorVisible() {
curx, cury := state.Cursor()
s.ShowCursor(curx, cury)
} else {
s.HideCursor()
}
s.Show()
}
|