forked from Mirrors/bubbletea
feat: add event-logger example
A simple event logger that displays the most recent window-size, mouse, and key events triggered by Bubble Tea.
This commit is contained in:
parent
b8ef6f85ea
commit
87a54bef6d
|
@ -0,0 +1,158 @@
|
|||
package main
|
||||
|
||||
// An event logger that displays tea window-size, key, and mouse events.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
var (
|
||||
typeStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#04B575"))
|
||||
msgStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#DDDDDD"))
|
||||
timeStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#FF06B7"))
|
||||
tooltipStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#333333"))
|
||||
)
|
||||
|
||||
func main() {
|
||||
p := tea.NewProgram(&model{lastEvent: time.Now()},
|
||||
tea.WithAltScreen(),
|
||||
tea.WithMouseAllMotion(),
|
||||
)
|
||||
if _, err := p.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
type event struct {
|
||||
timestamp time.Time
|
||||
msg tea.Msg
|
||||
}
|
||||
|
||||
type model struct {
|
||||
width int
|
||||
height int
|
||||
|
||||
lastEvent time.Time
|
||||
lastMouseEvent tea.MouseEvent
|
||||
|
||||
events []event
|
||||
}
|
||||
|
||||
func (m *model) Init() tea.Cmd {
|
||||
return tick
|
||||
}
|
||||
|
||||
func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "ctrl+c":
|
||||
return m, tea.Quit
|
||||
}
|
||||
|
||||
case tea.MouseMsg:
|
||||
m.lastMouseEvent = tea.MouseEvent(msg)
|
||||
|
||||
if m.lastMouseEvent.Type == tea.MouseMotion {
|
||||
// don't log motion events as it becomes spamy
|
||||
return m, nil
|
||||
}
|
||||
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
m.height = msg.Height
|
||||
|
||||
case tickMsg:
|
||||
return m, tick
|
||||
}
|
||||
|
||||
m.lastEvent = time.Now()
|
||||
m.events = append(m.events, event{
|
||||
timestamp: time.Now(),
|
||||
msg: msg,
|
||||
})
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m model) View() string {
|
||||
if m.width == 0 || m.height == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
h := m.height - 3
|
||||
evs := m.events
|
||||
if m.height > 0 && len(evs) > h {
|
||||
evs = evs[len(evs)-h:]
|
||||
}
|
||||
|
||||
var s string
|
||||
for _, event := range evs {
|
||||
s += fmt.Sprintf("[%s] %s\n",
|
||||
timeStyle.Render(event.timestamp.Format("15:04:05")),
|
||||
msgView(event.msg),
|
||||
)
|
||||
}
|
||||
|
||||
lastEvent := fmt.Sprintf("Waiting for event... (last %s)", humanize.Time(m.lastEvent))
|
||||
cursor := fmt.Sprintf("X: %d, Y: %d", m.lastMouseEvent.X, m.lastMouseEvent.Y)
|
||||
|
||||
return fmt.Sprintf("%s\n%s%s\n%s",
|
||||
lipgloss.NewStyle().Height(h+1).Render(s),
|
||||
lipgloss.NewStyle().Width(m.width-16).Render(lastEvent),
|
||||
lipgloss.NewStyle().Width(16).Align(lipgloss.Right).Render(cursor),
|
||||
tooltipStyle.Render("Press Ctrl+C to quit"),
|
||||
)
|
||||
}
|
||||
|
||||
func msgView(msg tea.Msg) string {
|
||||
switch ev := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
return fmt.Sprintf("%s %s",
|
||||
typeStyle.Render("KeyMsg"),
|
||||
msgStyle.Render(
|
||||
fmt.Sprintf("%s (alt: %t)",
|
||||
ev.String(),
|
||||
ev.Alt,
|
||||
),
|
||||
),
|
||||
)
|
||||
case tea.MouseMsg:
|
||||
return fmt.Sprintf("%s %s",
|
||||
typeStyle.Render("MouseMsg"),
|
||||
msgStyle.Render(
|
||||
fmt.Sprintf("X: %d, Y: %d, type: %s",
|
||||
ev.X,
|
||||
ev.Y,
|
||||
tea.MouseEvent(ev),
|
||||
),
|
||||
),
|
||||
)
|
||||
case tea.WindowSizeMsg:
|
||||
return fmt.Sprintf("%s %s",
|
||||
typeStyle.Render("WindowSizeMsg"),
|
||||
msgStyle.Render(
|
||||
fmt.Sprintf("%d x %d",
|
||||
ev.Width,
|
||||
ev.Height,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
default:
|
||||
return "Unknown event"
|
||||
}
|
||||
}
|
||||
|
||||
type tickMsg time.Time
|
||||
|
||||
func tick() tea.Msg {
|
||||
time.Sleep(time.Second)
|
||||
return tickMsg{}
|
||||
}
|
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/charmbracelet/bubbletea v0.22.0
|
||||
github.com/charmbracelet/glamour v0.5.0
|
||||
github.com/charmbracelet/lipgloss v0.6.0
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||
github.com/mattn/go-isatty v0.0.16
|
||||
|
|
|
@ -22,6 +22,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 h1:VRIbnDWRmAh5yBdz+J6yFMF5vso1It6vn+WmM/5l7MA=
|
||||
github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776/go.mod h1:9wvnDu3YOfxzWM9Cst40msBF1C2UdQgDv962oTxSuMs=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
|
|
Loading…
Reference in New Issue