147 lines
2.9 KiB
Go
147 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
tcellterm "git.sr.ht/~rockorager/tcell-term"
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/gdamore/tcell/v2/views"
|
|
)
|
|
|
|
type model struct {
|
|
term *tcellterm.VT
|
|
s tcell.Screen
|
|
termView views.View
|
|
title *views.TextBar
|
|
titleView views.View
|
|
result *views.TextArea
|
|
resultView views.View
|
|
}
|
|
|
|
func newModel() *model {
|
|
var err error
|
|
m := &model{}
|
|
m.s, err = tcell.NewScreen()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
if err = m.s.Init(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
m.s.EnablePaste()
|
|
w, _ := m.s.Size()
|
|
|
|
m.title = views.NewTextBar()
|
|
m.title.SetCenter(
|
|
"nixpl",
|
|
tcell.StyleDefault.Foreground(tcell.ColorBlue).
|
|
Bold(true).
|
|
Underline(true),
|
|
)
|
|
|
|
m.titleView = views.NewViewPort(m.s, 0, 0, -1, 2)
|
|
m.title.SetView(m.titleView)
|
|
|
|
m.termView = views.NewViewPort(m.s, 0, 2, w/2, -1)
|
|
m.term = tcellterm.New()
|
|
m.term.SetSurface(m.termView)
|
|
m.term.Attach(m.HandleEvent)
|
|
|
|
m.resultView = views.NewViewPort(m.s, w/2, 2, w/2, -1)
|
|
m.result = views.NewTextArea()
|
|
m.result.SetView(m.resultView)
|
|
|
|
m.s.EnableMouse()
|
|
|
|
return m
|
|
}
|
|
|
|
// Update is the main event handler. It should only be called by the main thread
|
|
func (m *model) Update(ev tcell.Event) {
|
|
switch ev := ev.(type) {
|
|
case *tcell.EventKey:
|
|
switch ev.Key() {
|
|
case tcell.KeyCtrlC:
|
|
m.term.Close()
|
|
m.s.Fini()
|
|
return
|
|
}
|
|
if m.term != nil {
|
|
m.term.HandleEvent(ev)
|
|
}
|
|
m.term.Draw()
|
|
m.result.Draw()
|
|
m.s.Show()
|
|
case *tcell.EventResize:
|
|
w, _ := m.s.Size()
|
|
if m.term != nil {
|
|
m.termView.Resize(0, 2, w/2, -1)
|
|
m.term.Resize(m.termView.Size())
|
|
}
|
|
m.titleView.Resize(0, 0, -1, 2)
|
|
m.title.Resize()
|
|
m.resultView.Resize(w/2, 2, w/2, -1)
|
|
m.result.Resize()
|
|
m.title.Draw()
|
|
m.term.Draw()
|
|
m.result.Draw()
|
|
m.s.Sync()
|
|
return
|
|
case *tcellterm.EventRedraw:
|
|
m.term.Draw()
|
|
m.title.Draw()
|
|
m.result.Draw()
|
|
|
|
row, col, style, vis := m.term.Cursor()
|
|
if vis {
|
|
m.s.SetCursorStyle(style)
|
|
m.s.ShowCursor(col, row+2)
|
|
|
|
} else {
|
|
m.s.HideCursor()
|
|
}
|
|
m.s.Show()
|
|
return
|
|
case *tcellterm.EventClosed:
|
|
m.s.Clear()
|
|
m.s.Fini()
|
|
return
|
|
case *tcell.EventPaste:
|
|
m.term.HandleEvent(ev)
|
|
return
|
|
case *tcell.EventMouse:
|
|
// Translate the coordinates to our global coordinates (y-2)
|
|
x, y := ev.Position()
|
|
if y-2 < 0 {
|
|
// Event is outside our view
|
|
return
|
|
}
|
|
e := tcell.NewEventMouse(x, y-2, ev.Buttons(), ev.Modifiers())
|
|
m.term.HandleEvent(e)
|
|
return
|
|
case *tcellterm.EventMouseMode:
|
|
m.s.EnableMouse(ev.Flags()...)
|
|
case *tcellterm.EventPanic:
|
|
m.s.Clear()
|
|
m.s.Fini()
|
|
fmt.Println(ev.Error)
|
|
}
|
|
return
|
|
}
|
|
|
|
// HandleEvent is used to handle events from underlying widgets. Any events
|
|
// which redraw must be executed in the main goroutine by posting the event back
|
|
// to tcell
|
|
func (m *model) HandleEvent(ev tcell.Event) {
|
|
m.s.PostEvent(ev)
|
|
}
|
|
|
|
func (m *model) UpdateResult(result string) {
|
|
m.result.SetContent(result)
|
|
m.result.Draw()
|
|
m.s.Sync()
|
|
}
|