Better display
This commit is contained in:
parent
93ede8d260
commit
f68970ea6f
1
go.mod
1
go.mod
|
@ -25,6 +25,7 @@ require (
|
||||||
github.com/muesli/reflow v0.3.0 // indirect
|
github.com/muesli/reflow v0.3.0 // indirect
|
||||||
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect
|
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/sahilm/fuzzy v0.1.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect
|
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
||||||
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed // indirect
|
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed // indirect
|
||||||
|
|
1
go.sum
1
go.sum
|
@ -79,6 +79,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
|
||||||
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
|
|
109
main.go
109
main.go
|
@ -5,7 +5,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/charmbracelet/bubbles/progress"
|
"github.com/charmbracelet/bubbles/progress"
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
|
"github.com/charmbracelet/bubbles/viewport"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/charmbracelet/wish"
|
"github.com/charmbracelet/wish"
|
||||||
bm "github.com/charmbracelet/wish/bubbletea"
|
bm "github.com/charmbracelet/wish/bubbletea"
|
||||||
lm "github.com/charmbracelet/wish/logging"
|
lm "github.com/charmbracelet/wish/logging"
|
||||||
|
@ -20,6 +22,20 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
titleStyle = func() lipgloss.Style {
|
||||||
|
b := lipgloss.RoundedBorder()
|
||||||
|
b.Right = "├"
|
||||||
|
return lipgloss.NewStyle().BorderStyle(b).Padding(0, 1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
infoStyle = func() lipgloss.Style {
|
||||||
|
b := lipgloss.RoundedBorder()
|
||||||
|
b.Left = "┤"
|
||||||
|
return titleStyle.Copy().BorderStyle(b)
|
||||||
|
}()
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Println("Welcome on Cemantics!")
|
log.Println("Welcome on Cemantics!")
|
||||||
|
|
||||||
|
@ -67,7 +83,6 @@ func teaHandler(s ssh.Session) (tea.Model, []tea.ProgramOption) {
|
||||||
ti.Focus()
|
ti.Focus()
|
||||||
ti.CharLimit = 26
|
ti.CharLimit = 26
|
||||||
ti.Width = 26
|
ti.Width = 26
|
||||||
|
|
||||||
m := model{
|
m := model{
|
||||||
textInput: ti,
|
textInput: ti,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -75,7 +90,7 @@ func teaHandler(s ssh.Session) (tea.Model, []tea.ProgramOption) {
|
||||||
words: []word{},
|
words: []word{},
|
||||||
progressBar: progress.New(progress.WithScaledGradient("#FF7CCB", "#FDFF8C")),
|
progressBar: progress.New(progress.WithScaledGradient("#FF7CCB", "#FDFF8C")),
|
||||||
}
|
}
|
||||||
return m, []tea.ProgramOption{tea.WithAltScreen()}
|
return m, []tea.ProgramOption{tea.WithAltScreen(), tea.WithMouseCellMotion()}
|
||||||
}
|
}
|
||||||
|
|
||||||
type errMsg error
|
type errMsg error
|
||||||
|
@ -87,13 +102,15 @@ type word struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type model struct {
|
type model struct {
|
||||||
textInput textinput.Model
|
ready bool
|
||||||
err error
|
err error
|
||||||
ip string
|
textInput textinput.Model
|
||||||
words []word
|
ip string
|
||||||
progressBar progress.Model
|
words []word
|
||||||
maxLength int
|
wordsViewport viewport.Model
|
||||||
lastWord string
|
progressBar progress.Model
|
||||||
|
maxLength int
|
||||||
|
lastWord string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m model) Init() tea.Cmd {
|
func (m model) Init() tea.Cmd {
|
||||||
|
@ -102,6 +119,7 @@ func (m model) Init() tea.Cmd {
|
||||||
|
|
||||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
var cmd tea.Cmd
|
var cmd tea.Cmd
|
||||||
|
var cmds []tea.Cmd
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
|
@ -111,20 +129,35 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
case tea.KeyCtrlC, tea.KeyEsc:
|
case tea.KeyCtrlC, tea.KeyEsc:
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
}
|
}
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
headerHeight := lipgloss.Height(m.headerView())
|
||||||
|
footerHeight := lipgloss.Height(m.footerView())
|
||||||
|
verticalMarginHeight := headerHeight + footerHeight
|
||||||
|
|
||||||
|
if !m.ready {
|
||||||
|
m.wordsViewport = viewport.New(msg.Width, msg.Height-verticalMarginHeight)
|
||||||
|
m.wordsViewport.YPosition = headerHeight
|
||||||
|
m.ready = true
|
||||||
|
} else {
|
||||||
|
m.wordsViewport.Width = msg.Width
|
||||||
|
m.wordsViewport.Height = msg.Height - verticalMarginHeight
|
||||||
|
}
|
||||||
|
|
||||||
// We handle errors just like any other message
|
|
||||||
case errMsg:
|
case errMsg:
|
||||||
m.err = msg
|
m.err = msg
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.wordsViewport, cmd = m.wordsViewport.Update(msg)
|
||||||
|
cmds = append(cmds, cmd)
|
||||||
m.textInput, cmd = m.textInput.Update(msg)
|
m.textInput, cmd = m.textInput.Update(msg)
|
||||||
return m, cmd
|
cmds = append(cmds, cmd)
|
||||||
|
|
||||||
|
return m, tea.Batch(cmds...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m model) InputWord() (model, tea.Cmd) {
|
func (m model) InputWord() (model, tea.Cmd) {
|
||||||
input := m.textInput.Value()
|
input := m.textInput.Value()
|
||||||
log.Printf("Chosen word: %s", input)
|
|
||||||
|
|
||||||
m.lastWord = input
|
m.lastWord = input
|
||||||
if len(input) > m.maxLength {
|
if len(input) > m.maxLength {
|
||||||
|
@ -132,7 +165,14 @@ func (m model) InputWord() (model, tea.Cmd) {
|
||||||
}
|
}
|
||||||
// TODO: Get distance and ranking from a file
|
// TODO: Get distance and ranking from a file
|
||||||
// TODO: Reorder the array
|
// TODO: Reorder the array
|
||||||
m.words = append(m.words, word{input, 200*rand.Float64() - 100, rand.Intn(1000)})
|
w := word{input, 200*rand.Float64() - 100, rand.Intn(1000)}
|
||||||
|
m.words = append(m.words, w)
|
||||||
|
|
||||||
|
var content string
|
||||||
|
for _, w := range m.words {
|
||||||
|
content += w.View(m)
|
||||||
|
}
|
||||||
|
m.wordsViewport.SetContent(content)
|
||||||
|
|
||||||
m.textInput.SetValue("")
|
m.textInput.SetValue("")
|
||||||
m.textInput.CursorStart()
|
m.textInput.CursorStart()
|
||||||
|
@ -178,23 +218,38 @@ func (w word) View(m model) string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m model) View() string {
|
func (m model) headerView() string {
|
||||||
|
var err string
|
||||||
|
|
||||||
|
if m.err != nil {
|
||||||
|
err = fmt.Sprintf("Erreur : %s", m.err)
|
||||||
|
}
|
||||||
|
|
||||||
msg := fmt.Sprintf(
|
msg := fmt.Sprintf(
|
||||||
"Veuillez choisir un mot :\n\n%s\n\n%s",
|
"Veuillez choisir un mot :\n\n%s\n\nDernier mot essayé : %s%s\n%s\n\n",
|
||||||
m.textInput.View(),
|
m.textInput.View(),
|
||||||
"(Esc pour quitter)",
|
m.lastWord,
|
||||||
) + "\n\n"
|
strings.Repeat(" ", 26),
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
|
||||||
if m.lastWord != "" {
|
title := titleStyle.Render("Mots précédents")
|
||||||
msg += fmt.Sprintf("Dernier mot essayé : %s\n\n", m.lastWord)
|
line := strings.Repeat("─", int(math.Max(0, float64(m.wordsViewport.Width-lipgloss.Width(title)))))
|
||||||
}
|
msg += lipgloss.JoinHorizontal(lipgloss.Center, title, line)
|
||||||
|
|
||||||
if len(m.words) > 0 {
|
|
||||||
msg += fmt.Sprintf("Liste des derniers mots :\n")
|
|
||||||
for _, w := range m.words {
|
|
||||||
msg += w.View(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m model) footerView() string {
|
||||||
|
info := infoStyle.Render(fmt.Sprintf("%3.f%%", m.wordsViewport.ScrollPercent()*100))
|
||||||
|
line := strings.Repeat("─", int(math.Max(0, float64(m.wordsViewport.Width-lipgloss.Width(info)))))
|
||||||
|
return lipgloss.JoinHorizontal(lipgloss.Center, line, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) View() string {
|
||||||
|
if !m.ready {
|
||||||
|
return "\n\tInitializing..."
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s\n%s\n%s", m.headerView(), m.wordsViewport.View(), m.footerView())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue