on main help sign in
cleanup nested tool rendering
commita23e1a37530978103a4eba7f7f5ce4a59cf0f768 authorKujtim Hoxha <kujtimii.h@gmail.com> dateSat 24 May 2025, 17:30 (1 year ago) parent9a69a31
4 files changed+38−29
internal/tui/components/chat/list.go+10−4 internal/tui/components/chat/messages/renderer.go+8−3 internal/tui/components/chat/messages/tool.go+4−9 internal/tui/components/core/list/keys.go+16−13
internal/tui/components/chat/list.go+10−4
@@ -46,13 +46,19 @@ type messageListCmp struct {
4646// and reverse ordering (newest messages at bottom).
4747func NewMessagesListCmp(app *app.App) MessageListCmp {
4848 defaultKeymaps := list.DefaultKeymap()
49− defaultKeymaps.NDown.SetEnabled(false)
50− defaultKeymaps.NUp.SetEnabled(false)
49+ defaultKeymaps.Up.SetEnabled(false)
50+ defaultKeymaps.Down.SetEnabled(false)
51+ defaultKeymaps.NDown = key.NewBinding(
52+ key.WithKeys("ctrl+j"),
53+ )
54+ defaultKeymaps.NUp = key.NewBinding(
55+ key.WithKeys("ctrl+k"),
56+ )
5157 defaultKeymaps.Home = key.NewBinding(
52− key.WithKeys("ctrl+g"),
58+ key.WithKeys("ctrl+shift+up"),
5359 )
5460 defaultKeymaps.End = key.NewBinding(
55− key.WithKeys("ctrl+G"),
61+ key.WithKeys("ctrl+shift+down"),
5662 )
5763 return &messageListCmp{
5864 app: app,
internal/tui/components/chat/messages/renderer.go+8−3
@@ -7,6 +7,7 @@ import (
77 "time"
88
99 "github.com/charmbracelet/lipgloss/v2"
10+ "github.com/charmbracelet/lipgloss/v2/tree"
1011 "github.com/charmbracelet/x/ansi"
1112 "github.com/opencode-ai/opencode/internal/config"
1213 "github.com/opencode-ai/opencode/internal/diff"
@@ -93,7 +94,7 @@ func (pb *paramBuilder) build() []string {
9394func (br baseRenderer) renderWithParams(v *toolCallCmp, toolName string, args []string, contentRenderer func() string) string {
9495 width := v.textWidth()
9596 if v.isNested {
96− width -= 3 // Adjust for nested tool call indentation
97+ width -= 4 // Adjust for nested tool call indentation
9798 }
9899 header := makeHeader(toolName, width, args...)
99100 if v.isNested {
@@ -495,11 +496,15 @@ func (tr agentRenderer) Render(v *toolCallCmp) string {
495496 args := newParamBuilder().addMain(prompt).build()
496497
497498 header := makeHeader("Task", v.textWidth(), args...)
498− parts := []string{header}
499+ t := tree.Root(header)
500+
499501 for _, call := range v.nestedToolCalls {
500− parts = append(parts, call.View())
502+ t.Child(call.View())
501503 }
502504
505+ parts := []string{
506+ t.Enumerator(tree.RoundedEnumerator).String(),
507+ }
503508 if v.result.ToolCallID == "" {
504509 v.spinning = true
505510 parts = append(parts, v.anim.View())
internal/tui/components/chat/messages/tool.go+4−9
@@ -138,18 +138,16 @@ func (m *toolCallCmp) View() string {
138138 box := m.style()
139139
140140 if !m.call.Finished && !m.cancelled {
141+ if m.isNested {
142+ return box.Render(m.renderPending())
143+ }
141144 return box.PaddingLeft(1).Render(m.renderPending())
142145 }
143146
144147 r := registry.lookup(m.call.Name)
145148
146149 if m.isNested {
147− return box.Render(
148− lipgloss.JoinHorizontal(lipgloss.Left,
149− " └ ",
150− r.Render(m),
151− ),
152− )
150+ return box.Render(r.Render(m))
153151 }
154152 return box.PaddingLeft(1).Render(r.Render(m))
155153}
@@ -212,9 +210,6 @@ func (m *toolCallCmp) SetIsNested(isNested bool) {
212210
213211// renderPending displays the tool name with a loading animation for pending tool calls
214212func (m *toolCallCmp) renderPending() string {
215− if m.isNested {
216− return fmt.Sprintf("└ %s: %s", prettifyToolName(m.call.Name), m.anim.View())
217− }
218213 return fmt.Sprintf("%s: %s", prettifyToolName(m.call.Name), m.anim.View())
219214}
220215
internal/tui/components/core/list/keys.go+16−13
@@ -1,6 +1,9 @@
11package list
22
3−import "github.com/charmbracelet/bubbles/v2/key"
3+import (
4+ "github.com/charmbracelet/bubbles/v2/key"
5+ "github.com/opencode-ai/opencode/internal/tui/layout"
6+)
47
58type KeyMap struct {
69 Down,
@@ -12,8 +15,7 @@ type KeyMap struct {
1215 HalfPageDown,
1316 HalfPageUp,
1417 Home,
15− End,
16− Submit key.Binding
18+ End key.Binding
1719}
1820
1921func DefaultKeymap() KeyMap {
@@ -48,23 +50,24 @@ func DefaultKeymap() KeyMap {
4850 End: key.NewBinding(
4951 key.WithKeys("shift+g", "end"),
5052 ),
51− Submit: key.NewBinding(
52− key.WithKeys("enter", "space"),
53− key.WithHelp("enter/space", "select"),
54− ),
5553 }
5654}
5755
5856// FullHelp implements help.KeyMap.
59−func (k KeyMap) FullHelp() [][]key.Binding { return nil }
57+func (k KeyMap) FullHelp() [][]key.Binding {
58+ m := [][]key.Binding{}
59+ slice := layout.KeyMapToSlice(k)
60+ for i := 0; i < len(slice); i += 4 {
61+ end := min(i+4, len(slice))
62+ m = append(m, slice[i:end])
63+ }
64+ return m
65+}
6066
6167// ShortHelp implements help.KeyMap.
6268func (k KeyMap) ShortHelp() []key.Binding {
6369 return []key.Binding{
64− key.NewBinding(
65− key.WithKeys("up", "down"),
66− key.WithHelp("↓↑", "navigate"),
67− ),
68− k.Submit,
70+ k.Up,
71+ k.Down,
6972 }
7073}