Skip to content

Commit

Permalink
fix(talk): fix rendering of tabs.
Browse files Browse the repository at this point in the history
  • Loading branch information
tartavull committed Oct 8, 2023
1 parent ad0e950 commit bfa6c00
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 47 deletions.
120 changes: 89 additions & 31 deletions talk/auto/auto.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package auto

import (
"fmt"
"log"
"io/ioutil"
"strings"
"os"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/bubbles/textarea"
"github.com/charmbracelet/bubbles/cursor"
"github.com/mitchellh/go-wordwrap"
"github.com/charmbracelet/bubbles/viewport"
"github.com/charmbracelet/lipgloss"
Expand All @@ -26,9 +24,11 @@ const (
)

type Auto struct {
common common.Common
common *common.Common
styles common.Styles
picked pane
tabs *tabs.Tabs
panes []tea.Model

textarea textarea.Model
state State
Expand All @@ -41,21 +41,26 @@ type Auto struct {
height int
}

func New(c common.Common, s common.Styles) *Auto {
func New(c *common.Common, s common.Styles) *Auto {
a := &Auto{
common: c,
textarea: textarea.New(),
styles: s,
tabs: tabs.New(c, []string{"chat", "history"}),
picked: paneChat,
viewport: viewport.New(0, 0),
tabs: InitTabs(c),
panes: []tea.Model{
nil,
nil,
},
}
a.viewport.YPosition = 0

a.textarea.Placeholder = ">"
a.textarea.ShowLineNumbers = false
a.textarea.Focus()

data, err := ioutil.ReadFile("chat/llm_1.json")
data, err := os.ReadFile("chat/llm_1.json")
if err != nil {
log.Fatal(err)
}
Expand All @@ -67,20 +72,65 @@ func New(c common.Common, s common.Styles) *Auto {
return a
}

func (a *Auto) Init() tea.Cmd {
return nil
}

type pane int

const (
paneChat pane = iota
paneHistory
paneLast
)

func (p pane) String() string {
return []string{
"Chat",
"History",
}[p]
}

func InitTabs(c *common.Common) *tabs.Tabs {
ts := make([]string, paneLast)
for i, b := range []pane{paneChat, paneHistory} {
ts[i] = b.String()
}
t := tabs.New(c, ts)
return t
}

func (a *Auto) Focus() tea.Cmd {
return textarea.Blink
}

func (a *Auto) SetSize(width, height int) {
a.width = width
a.height = height
a.common.SetSize(width, height)
a.textarea.SetWidth(width)
a.textarea.MaxHeight = height / 2
a.viewport.Width = width
a.viewport.Height = height
}

func (a *Auto) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
cmds := make([]tea.Cmd, 0)
switch msg := msg.(type) {
case tabs.ActiveTabMsg:
a.picked = pane(msg)
}
model, cmd := a.tabs.Update(msg)
cmds = append(cmds, cmd)
a.tabs = model.(*tabs.Tabs)

/*
model, cmd = a.panes[a.picked].Update(msg)
cmds = append(cmds, cmd)
a.panes[a.picked] = model
*/
return a, tea.Batch(cmds...)
}

/*
func (a *Auto) Update(msg tea.Msg) (*Auto, tea.Cmd) {
var cmd tea.Cmd
cmds := make([]tea.Cmd, 0)
Expand Down Expand Up @@ -120,38 +170,46 @@ func (a *Auto) Update(msg tea.Msg) (*Auto, tea.Cmd) {
}
return a, tea.Batch(cmds...)
}
*/

func (a *Auto) wrap(in string) string {
return wordwrap.WrapString(in, uint(a.textarea.Width()/2))
}

func (a *Auto) View() string {
// FIXME use string builder
view := a.styles.Logo.Render(" Alfredo ")
view += "\n\n"
view += a.tabs.View()
view += "\n\n"
view += a.styles.ContextTag.String() + " " + a.styles.Context.Render(a.wrap(a.Response.Context))
view += "\n\n"
view += a.styles.GoalTag.String() + " " + a.styles.Goal.Render(a.wrap(a.Response.Goal))
view += "\n\n"
var builder strings.Builder

builder.WriteString(a.styles.Logo.Render(" Alfredo "))
builder.WriteString("\n\n")
builder.WriteString(a.tabs.View())
builder.WriteString("\n\n")
builder.WriteString(a.styles.ContextTag.String() + " " + a.styles.Context.Render(a.wrap(a.Response.Context)))
/*
builder.WriteString("\n\n")
builder.WriteString(a.styles.GoalTag.String() + " " + a.styles.Goal.Render(a.wrap(a.Response.Goal)))
builder.WriteString("\n\n")
if a.state == stateAnswering {
if len(a.outputs) < len(a.Response.Commands) {
var styledCmds []string
for _, cmd := range a.Response.Commands {
styledCmds = append(styledCmds, fmt.Sprintf("$ %s", a.wrap(cmd)))
}
styledCmdStr := strings.Join(styledCmds, "\n")
view += a.styles.Command.Render(styledCmdStr) + "\n\n"
view += a.styles.Comment.Render("Press y to execute all commands or esc to exit")
var styledCmds []string
for _, cmd := range a.Response.Commands {
styledCmds = append(styledCmds, fmt.Sprintf("$ %s", a.wrap(cmd)))
}
styledCmdStr := strings.Join(styledCmds, "\n")
builder.WriteString(a.styles.Command.Render(styledCmdStr) + "\n\n")
builder.WriteString(a.styles.Comment.Render("Press y to execute all commands or esc to exit"))
} else if len(a.answers) < len(a.Response.Questions) {
question := a.Response.Questions[len(a.answers)]
view += a.styles.QuestionTag.String() + " " + a.styles.Question.Render(a.wrap(question))
view += "\n\n"
view += a.textarea.View()
view += "\n"
view += a.styles.Comment.Render(fmt.Sprintf("Question %d of %d: press ctrl+d to submit answer", len(a.answers)+1, len(a.Response.Questions)))
builder.WriteString(a.styles.QuestionTag.String() + " " + a.styles.Question.Render(a.wrap(question)))
builder.WriteString("\n\n")
builder.WriteString(a.textarea.View())
builder.WriteString("\n")
builder.WriteString(a.styles.Comment.Render(fmt.Sprintf("Question %d of %d: press ctrl+d to submit answer", len(a.answers)+1, len(a.Response.Questions))))
}
}
return lipgloss.Place(a.width, a.height, lipgloss.Left, lipgloss.Top, a.styles.App.Render(view))
*/

// Use String method to get the final string
view := builder.String()
return lipgloss.Place(a.common.Width, a.common.Height, lipgloss.Left, lipgloss.Top, a.styles.App.Render(view))
}
15 changes: 15 additions & 0 deletions talk/common/styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ type Styles struct {
TabInactive Style
TabActive Style
TabSeparator Style

TopLevelNormalTab Style
TopLevelActiveTab Style
TopLevelActiveTabDot Style
}

func MakeStyles(r *Renderer) (s Styles) {
Expand Down Expand Up @@ -107,5 +111,16 @@ func MakeStyles(r *Renderer) (s Styles) {
SetString("│").
Padding(0, 1).
Foreground(Color("238"))


s.TopLevelNormalTab = NewStyle().
MarginRight(2)

s.TopLevelActiveTab = s.TopLevelNormalTab.Copy().
Foreground(Color("36"))

s.TopLevelActiveTabDot = NewStyle().
Foreground(Color("36"))

return s
}
8 changes: 8 additions & 0 deletions talk/components/chat/chat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package chat

type Chat struct {
}

func New() *Chat {
return &Chat{}
}
23 changes: 10 additions & 13 deletions talk/components/tabs/tabs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type ActiveTabMsg int

// Tabs is bubbletea component that displays a list of tabs.
type Tabs struct {
common common.Common
common *common.Common
tabs []string
activeTab int
TabSeparator lipgloss.Style
Expand All @@ -27,7 +27,7 @@ type Tabs struct {
}

// New creates a new Tabs component.
func New(c common.Common, tabs []string) *Tabs {
func New(c *common.Common, tabs []string) *Tabs {
r := &Tabs{
common: c,
tabs: tabs,
Expand Down Expand Up @@ -86,28 +86,25 @@ func (t *Tabs) View() string {
s := strings.Builder{}
sep := t.TabSeparator
for i, tab := range t.tabs {
style := t.TabInactive.Copy()
prefix := " "
style := t.TabInactive
prefix := " "
if i == t.activeTab {
style = t.TabActive.Copy()
prefix = t.TabDot.Render("• ")
style = t.TabActive
prefix = t.TabDot.Render(" • ")
}
if t.UseDot {
s.WriteString(prefix)
}
s.WriteString(
t.common.Zone.Mark(
tab,
style.Render(tab),
),
)
s.WriteString(style.Render(tab))
if i != len(t.tabs)-1 {
s.WriteString(sep.String())
}
}

out := s.String()
return lipgloss.NewStyle().
MaxWidth(t.common.Width).
Render(s.String())
Render(out)
}

func (t *Tabs) activeTabCmd() tea.Msg {
Expand Down
6 changes: 3 additions & 3 deletions talk/mods.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func newMods(r *lipgloss.Renderer) *Mods {
state: stateStart,
renderer: r,
styles: s,
auto: auto.New(c, s),
auto: auto.New(&c, s),
}

}
Expand Down Expand Up @@ -121,9 +121,9 @@ func (m *Mods) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
}
if m.Config.Auto {
var cmd tea.Cmd
m.state = stateAuto
m.auto, cmd = m.auto.Update(msg)
model, cmd := m.auto.Update(msg)
m.auto = model.(*auto.Auto)
return m, cmd
}
if m.state == stateConfigLoaded || m.state == stateCompletion {
Expand Down

0 comments on commit bfa6c00

Please sign in to comment.