Skip to content

Commit 3b33b6c

Browse files
authored
Merge branch 'main' into feature/auto-reconnect
2 parents 6601319 + c06bb13 commit 3b33b6c

File tree

1 file changed

+70
-61
lines changed

1 file changed

+70
-61
lines changed

main.go

Lines changed: 70 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,16 @@ const (
200200
promptListView
201201
)
202202

203+
type focusedPanel int
204+
205+
const (
206+
mainPanelFocus focusedPanel = iota
207+
debugPanelFocus
208+
)
209+
203210
type AppModel struct {
204211
state viewState
212+
focusedPanel focusedPanel
205213
ctx context.Context
206214
session *mcp.ClientSession
207215
toolList list.Model
@@ -314,6 +322,7 @@ func initialModel(ctx context.Context, session *mcp.ClientSession) *AppModel {
314322

315323
return &AppModel{
316324
state: toolSelectionView,
325+
focusedPanel: mainPanelFocus,
317326
ctx: ctx,
318327
session: session,
319328
toolList: toolList,
@@ -365,9 +374,17 @@ func (m AppModel) Init() tea.Cmd {
365374

366375
func (m *AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
367376
var cmd tea.Cmd
368-
var cmds []tea.Cmd
369377

370378
switch msg := msg.(type) {
379+
case tea.WindowSizeMsg:
380+
m.width = msg.Width
381+
m.height = msg.Height
382+
debugPanelWidth := m.width / 3
383+
m.debugViewport.Width = debugPanelWidth - 2
384+
m.debugViewport.Height = m.height - 2
385+
m.debugViewport, cmd = m.debugViewport.Update(msg)
386+
return m, cmd
387+
371388
case toolResult:
372389
if msg.err != nil {
373390
m.err = msg.err
@@ -378,6 +395,8 @@ func (m *AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
378395
}
379396
m.logf("Result:\n========\n%s", msg.result)
380397
m.result = msg.result
398+
return m, nil
399+
381400
case resourceResult:
382401
if msg.err != nil {
383402
m.err = msg.err
@@ -386,13 +405,22 @@ func (m *AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
386405
if verbose {
387406
m.logf("Resource result received")
388407
}
389-
m.logf("Result:\n========\n%s", msg.result)
390408
m.resourceResult = msg.result
409+
return m, nil
410+
391411
case tea.KeyMsg:
392412
if verbose {
393413
m.logf("Key pressed: %s", msg.String())
394414
}
415+
// Global key bindings that work regardless of focus
395416
switch msg.Type {
417+
case tea.KeyTab:
418+
if m.focusedPanel == mainPanelFocus {
419+
m.focusedPanel = debugPanelFocus
420+
} else {
421+
m.focusedPanel = mainPanelFocus
422+
}
423+
return m, nil
396424
case tea.KeyEsc:
397425
if m.state == resourceDetailView {
398426
m.state = resourceListView
@@ -403,54 +431,29 @@ func (m *AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
403431
case tea.KeyCtrlC:
404432
return m, tea.Quit
405433
}
434+
}
406435

407-
switch m.state {
408-
case toolSelectionView:
409-
var model tea.Model
410-
model, cmd = m.updateToolSelectionView(msg)
411-
cmds = append(cmds, cmd)
412-
m.debugViewport, cmd = m.debugViewport.Update(msg)
413-
cmds = append(cmds, cmd)
414-
return model, tea.Batch(cmds...)
415-
case resourceListView:
416-
var model tea.Model
417-
model, cmd = m.updateResourceListView(msg)
418-
cmds = append(cmds, cmd)
419-
m.debugViewport, cmd = m.debugViewport.Update(msg)
420-
cmds = append(cmds, cmd)
421-
return model, tea.Batch(cmds...)
422-
case promptListView:
423-
var model tea.Model
424-
model, cmd = m.updatePromptListView(msg)
425-
cmds = append(cmds, cmd)
426-
m.debugViewport, cmd = m.debugViewport.Update(msg)
427-
cmds = append(cmds, cmd)
428-
return model, tea.Batch(cmds...)
429-
case argumentInputView:
430-
var model tea.Model
431-
model, cmd = m.updateArgumentInputView(msg)
432-
cmds = append(cmds, cmd)
433-
m.debugViewport, cmd = m.debugViewport.Update(msg)
434-
cmds = append(cmds, cmd)
435-
return model, tea.Batch(cmds...)
436-
case resourceDetailView:
437-
m.debugViewport, cmd = m.debugViewport.Update(msg)
438-
cmds = append(cmds, cmd)
439-
return m, tea.Batch(cmds...)
440-
}
441-
442-
case tea.WindowSizeMsg:
443-
m.width = msg.Width
444-
m.height = msg.Height
445-
debugWidth := m.width / 3
446-
m.debugViewport.Width = debugWidth
447-
m.debugViewport.Height = m.height - 2
436+
// Delegate message to the focused panel
437+
if m.focusedPanel == debugPanelFocus {
438+
m.debugViewport, cmd = m.debugViewport.Update(msg)
439+
return m, cmd
448440
}
449441

450-
m.debugViewport, cmd = m.debugViewport.Update(msg)
451-
cmds = append(cmds, cmd)
442+
// Main panel has focus, delegate to the active view
443+
switch m.state {
444+
case toolSelectionView:
445+
return m.updateToolSelectionView(msg)
446+
case resourceListView:
447+
return m.updateResourceListView(msg)
448+
case promptListView:
449+
return m.updatePromptListView(msg)
450+
case argumentInputView:
451+
return m.updateArgumentInputView(msg)
452+
case resourceDetailView:
453+
return m, nil
454+
}
452455

453-
return m, tea.Batch(cmds...)
456+
return m, nil
454457
}
455458

456459
func (m *AppModel) updateToolSelectionView(msg tea.Msg) (tea.Model, tea.Cmd) {
@@ -590,19 +593,19 @@ func (m AppModel) View() string {
590593
return fmt.Sprintf("Error: %v\n\nPress ctrl+c to quit.", m.err)
591594
}
592595

593-
mainWidth := m.width / 3
594-
//debugWidth := m.width - mainWidth
596+
debugPanelWidth := m.width / 3
597+
mainPanelWidth := m.width - debugPanelWidth
595598

596599
var mainContent strings.Builder
597600
switch m.state {
598601
case toolSelectionView:
599-
m.toolList.SetSize(mainWidth-2, m.height-2)
602+
m.toolList.SetSize(mainPanelWidth-2, m.height-2)
600603
mainContent.WriteString(m.toolList.View())
601604
case resourceListView:
602-
m.resourceList.SetSize(mainWidth-2, m.height-2)
605+
m.resourceList.SetSize(mainPanelWidth-2, m.height-2)
603606
mainContent.WriteString(m.resourceList.View())
604607
case promptListView:
605-
m.promptList.SetSize(mainWidth-2, m.height-2)
608+
m.promptList.SetSize(mainPanelWidth-2, m.height-2)
606609
mainContent.WriteString(m.promptList.View())
607610
case resourceDetailView:
608611
var b strings.Builder
@@ -623,17 +626,24 @@ func (m AppModel) View() string {
623626
mainContent.WriteString(b.String())
624627
}
625628

626-
mainPanel := lipgloss.NewStyle().
629+
mainPanelStyle := lipgloss.NewStyle().
627630
Border(lipgloss.RoundedBorder()).
628-
Width(mainWidth).
629-
Height(m.height - 2).
630-
Render(mainContent.String())
631+
Width(mainPanelWidth - 2).
632+
Height(m.height - 2)
631633

632-
debugPanel := lipgloss.NewStyle().
634+
debugPanelStyle := lipgloss.NewStyle().
633635
Border(lipgloss.RoundedBorder()).
634-
Width(m.debugViewport.Width).
635-
Height(m.debugViewport.Height).
636-
Render(m.debugViewport.View())
636+
Width(debugPanelWidth - 2).
637+
Height(m.debugViewport.Height)
638+
639+
if m.focusedPanel == mainPanelFocus {
640+
mainPanelStyle = mainPanelStyle.BorderForeground(lipgloss.Color("228")) // Yellow
641+
} else {
642+
debugPanelStyle = debugPanelStyle.BorderForeground(lipgloss.Color("228")) // Yellow
643+
}
644+
645+
mainPanel := mainPanelStyle.Render(mainContent.String())
646+
debugPanel := debugPanelStyle.Render(m.debugViewport.View())
637647

638648
return lipgloss.JoinHorizontal(lipgloss.Top, mainPanel, debugPanel)
639649
}
@@ -782,7 +792,7 @@ func handleSession(ctx context.Context, session *mcp.ClientSession) error {
782792
defer f.Close()
783793
}
784794
model := initialModel(ctx, session)
785-
p := tea.NewProgram(model, tea.WithAltScreen())
795+
p := tea.NewProgram(model, tea.WithAltScreen(), tea.WithMouseCellMotion())
786796
finalModel, err := p.Run()
787797
if err != nil {
788798
return fmt.Errorf("error running program: %w", err)
@@ -791,7 +801,6 @@ func handleSession(ctx context.Context, session *mcp.ClientSession) error {
791801
appModel, ok := finalModel.(*AppModel)
792802
if !ok {
793803
return fmt.Errorf("unexpected model type: %T", finalModel)
794-
}
795804

796805
return appModel.err
797806
}

0 commit comments

Comments
 (0)