diff --git a/ui/model.go b/ui/model.go index 40d98be..f6fd95b 100644 --- a/ui/model.go +++ b/ui/model.go @@ -10,17 +10,19 @@ import ( type Model struct { currentFile string - cursor int text string - width int - height int - lineCount int - bridge *bridge.Bridge + textLines int + width int + height int + + bridge *bridge.Bridge listenBridge chan string - messages []string - viewport viewport.Model + messages []string + stdoutOutput viewport.Model + codeViewer viewport.Model + cursor int breakpoints map[string][]int } @@ -28,18 +30,23 @@ type Model struct { func NewModel(b *bridge.Bridge, file string, text string) Model { c := b.Subscribe() - vp := viewport.New(0, 0) + stdoutOutput := viewport.New(0, 0) + codeViewer := viewport.New(0, 0) return Model{ - currentFile: file, - text: text, - cursor: 0, - lineCount: len(strings.Split(text, "\n")), + currentFile: file, + text: text, + textLines: len(strings.Split(text, "\n")), + bridge: b, - breakpoints: make(map[string][]int), listenBridge: c, - messages: make([]string, 0), - viewport: vp, + + breakpoints: make(map[string][]int), + messages: make([]string, 0), + + cursor: 0, + codeViewer: codeViewer, + stdoutOutput: stdoutOutput, } } diff --git a/ui/update.go b/ui/update.go index c400aa1..c429f39 100644 --- a/ui/update.go +++ b/ui/update.go @@ -1,6 +1,8 @@ package ui import ( + "strings" + tea "github.com/charmbracelet/bubbletea" ) @@ -9,31 +11,54 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.KeyMsg: return m.HandleKeyMsg(msg) case tea.WindowSizeMsg: - m.width = msg.Width - m.height = msg.Height + return m.UpdateWindowSize(msg) case StdoutMsg: m.messages = append(m.messages, string(msg)) + m.stdoutOutput.SetContent(strings.Join(m.messages, "")) + m.stdoutOutput.GotoBottom() return m, ListenBridge(m.listenBridge) } return m, nil } +func (m Model) UpdateWindowSize(msg tea.WindowSizeMsg) (tea.Model, tea.Cmd) { + m.width = msg.Width + m.height = msg.Height + + editorHeight := msg.Height * 70 / 100 + outputHeight := msg.Height - editorHeight - 4 + + m.codeViewer.Width = msg.Width + m.codeViewer.Height = editorHeight + + m.stdoutOutput.Width = msg.Width + m.stdoutOutput.Height = outputHeight + + m.stdoutOutput.SetContent(strings.Join(m.messages, "")) + + return m, nil +} + func (m Model) HandleKeyMsg(key tea.KeyMsg) (tea.Model, tea.Cmd) { switch key.String() { case "q", "ctrl+c": return m, tea.Quit case "k": - m.cursor = clamp(0, m.height, m.cursor-1) + m.codeViewer.ScrollUp(1) + m.cursor = max(0, m.cursor-1) case "j": - m.cursor = clamp(0, min(m.height, m.lineCount-1), m.cursor+1) + m.codeViewer.ScrollUp(1) + m.cursor = min(m.textLines-1, m.cursor+1) case "b": - m.bridge.Breakpoint(m.currentFile, m.cursor) + lineNumber := m.cursor + 1 + + m.bridge.Breakpoint(m.currentFile, lineNumber) if file, ok := m.breakpoints[m.currentFile]; ok { - m.breakpoints[m.currentFile] = append(file, m.cursor+1) + m.breakpoints[m.currentFile] = append(file, lineNumber) } else { m.breakpoints[m.currentFile] = []int{ - m.cursor + 1, + lineNumber, } } case "c": @@ -42,9 +67,3 @@ func (m Model) HandleKeyMsg(key tea.KeyMsg) (tea.Model, tea.Cmd) { return m, nil } - -func clamp(minimum, maximum, val int) int { - val = max(minimum, val) - val = min(maximum, val) - return val -} diff --git a/ui/view.go b/ui/view.go index e318356..448fd56 100644 --- a/ui/view.go +++ b/ui/view.go @@ -12,7 +12,7 @@ import ( "github.com/charmbracelet/lipgloss" ) -var panelStyle = lipgloss.NewStyle().Border(lipgloss.NormalBorder()) +var panelStyle = lipgloss.NewStyle().Border(lipgloss.NormalBorder()).Padding(0, 1) func (m Model) View() string { var buf bytes.Buffer @@ -27,7 +27,6 @@ func (m Model) View() string { lines := strings.Split(buf.String(), "\n") breakpoints := m.breakpoints[m.currentFile] - for i, line := range lines { breakpoint := " " cursor := " " @@ -42,15 +41,17 @@ func (m Model) View() string { fmt.Fprintf(&out, "%-4d%s%s %s\n", i+1, breakpoint, cursor, line) } - frameW, frameH := panelStyle.GetFrameSize() - topHeight := m.height * 70 / 100 + m.codeViewer.SetContent(out.String()) - code := panelStyle.Width(m.width - frameW).Height(topHeight - frameH).Render(out.String()) - m.viewport.Height = m.height - (topHeight + frameH) - m.viewport.Width = m.width - frameW - m.viewport.SetContent(strings.Join(m.messages, "")) - m.viewport.GotoBottom() - output := panelStyle.Width(m.viewport.Width).Height(m.viewport.Height).Render(m.viewport.View()) + hFrame, wFrame := panelStyle.GetFrameSize() + topPanel := panelStyle. + Height(m.codeViewer.Height - hFrame). + Width(m.codeViewer.Width - wFrame). + Render(m.codeViewer.View()) - return lipgloss.JoinVertical(lipgloss.Top, code, output) + bottomPanel := panelStyle.Height(m.stdoutOutput.Height - hFrame). + Width(m.stdoutOutput.Width - wFrame). + Render(m.stdoutOutput.View()) + + return lipgloss.JoinVertical(lipgloss.Top, topPanel, bottomPanel) }