@@ -4,7 +4,7 @@ import (
"charm.land/lipgloss/v2"
"github.com/charmbracelet/crush/internal/agent"
"github.com/charmbracelet/crush/internal/ui/common"
- uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/ultraviolet/layout"
)
// selectedLargeModel returns the currently selected large language model from
@@ -31,7 +31,7 @@ func (m *UI) landingView() string {
parts = append(parts, "", m.modelInfo(width))
infoSection := lipgloss.JoinVertical(lipgloss.Left, parts...)
- _, remainingHeightArea := uv.SplitVertical(m.layout.main, uv.Fixed(lipgloss.Height(infoSection)+1))
+ _, remainingHeightArea := layout.SplitVertical(m.layout.main, layout.Fixed(lipgloss.Height(infoSection)+1))
mcpLspSectionWidth := min(30, (width-1)/2)
@@ -8,6 +8,7 @@ import (
"github.com/charmbracelet/crush/internal/ui/common"
"github.com/charmbracelet/crush/internal/ui/logo"
uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/ultraviolet/layout"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
@@ -134,7 +135,7 @@ func (m *UI) drawSidebar(scr uv.Screen, area uv.Rectangle) {
blocks...,
)
- _, remainingHeightArea := uv.SplitVertical(m.layout.sidebar, uv.Fixed(lipgloss.Height(sidebarHeader)))
+ _, remainingHeightArea := layout.SplitVertical(m.layout.sidebar, layout.Fixed(lipgloss.Height(sidebarHeader)))
remainingHeight := remainingHeightArea.Dy() - 10
maxFiles, maxLSPs, maxMCPs := getDynamicHeightLimits(remainingHeight)
@@ -47,6 +47,7 @@ import (
"github.com/charmbracelet/crush/internal/ui/util"
"github.com/charmbracelet/crush/internal/version"
uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/ultraviolet/layout"
"github.com/charmbracelet/ultraviolet/screen"
"github.com/charmbracelet/x/editor"
)
@@ -135,7 +136,7 @@ type UI struct {
// The width and height of the terminal in cells.
width int
height int
- layout layout
+ layout uiLayout
isTransparent bool
@@ -2235,7 +2236,7 @@ func (m *UI) updateSize() {
// generateLayout calculates the layout rectangles for all UI components based
// on the current UI state and terminal dimensions.
-func (m *UI) generateLayout(w, h int) layout {
+func (m *UI) generateLayout(w, h int) uiLayout {
// The screen area we're working with
area := image.Rect(0, 0, w, h)
@@ -2256,7 +2257,7 @@ func (m *UI) generateLayout(w, h int) layout {
}
// Add app margins
- appRect, helpRect := uv.SplitVertical(area, uv.Fixed(area.Dy()-helpHeight))
+ appRect, helpRect := layout.SplitVertical(area, layout.Fixed(area.Dy()-helpHeight))
appRect.Min.Y += 1
appRect.Max.Y -= 1
helpRect.Min.Y -= 1
@@ -2269,7 +2270,7 @@ func (m *UI) generateLayout(w, h int) layout {
appRect.Max.X -= 1
}
- layout := layout{
+ uiLayout := uiLayout{
area: area,
status: helpRect,
}
@@ -2285,9 +2286,9 @@ func (m *UI) generateLayout(w, h int) layout {
// ------
// help
- headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(landingHeaderHeight))
- layout.header = headerRect
- layout.main = mainRect
+ headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(landingHeaderHeight))
+ uiLayout.header = headerRect
+ uiLayout.main = mainRect
case uiLanding:
// Layout
@@ -2299,14 +2300,14 @@ func (m *UI) generateLayout(w, h int) layout {
// editor
// ------
// help
- headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(landingHeaderHeight))
- mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
+ headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(landingHeaderHeight))
+ mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
// Remove extra padding from editor (but keep it for header and main)
editorRect.Min.X -= 1
editorRect.Max.X += 1
- layout.header = headerRect
- layout.main = mainRect
- layout.editor = editorRect
+ uiLayout.header = headerRect
+ uiLayout.main = mainRect
+ uiLayout.editor = editorRect
case uiChat:
if m.isCompact {
@@ -2320,28 +2321,28 @@ func (m *UI) generateLayout(w, h int) layout {
// ------
// help
const compactHeaderHeight = 1
- headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(compactHeaderHeight))
+ headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(compactHeaderHeight))
detailsHeight := min(sessionDetailsMaxHeight, area.Dy()-1) // One row for the header
- sessionDetailsArea, _ := uv.SplitVertical(appRect, uv.Fixed(detailsHeight))
- layout.sessionDetails = sessionDetailsArea
- layout.sessionDetails.Min.Y += compactHeaderHeight // adjust for header
+ sessionDetailsArea, _ := layout.SplitVertical(appRect, layout.Fixed(detailsHeight))
+ uiLayout.sessionDetails = sessionDetailsArea
+ uiLayout.sessionDetails.Min.Y += compactHeaderHeight // adjust for header
// Add one line gap between header and main content
mainRect.Min.Y += 1
- mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
+ mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
mainRect.Max.X -= 1 // Add padding right
- layout.header = headerRect
+ uiLayout.header = headerRect
pillsHeight := m.pillsAreaHeight()
if pillsHeight > 0 {
pillsHeight = min(pillsHeight, mainRect.Dy())
- chatRect, pillsRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-pillsHeight))
- layout.main = chatRect
- layout.pills = pillsRect
+ chatRect, pillsRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-pillsHeight))
+ uiLayout.main = chatRect
+ uiLayout.pills = pillsRect
} else {
- layout.main = mainRect
+ uiLayout.main = mainRect
}
// Add bottom margin to main
- layout.main.Max.Y -= 1
- layout.editor = editorRect
+ uiLayout.main.Max.Y -= 1
+ uiLayout.editor = editorRect
} else {
// Layout
//
@@ -2352,40 +2353,40 @@ func (m *UI) generateLayout(w, h int) layout {
// ----------
// help
- mainRect, sideRect := uv.SplitHorizontal(appRect, uv.Fixed(appRect.Dx()-sidebarWidth))
+ mainRect, sideRect := layout.SplitHorizontal(appRect, layout.Fixed(appRect.Dx()-sidebarWidth))
// Add padding left
sideRect.Min.X += 1
- mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
+ mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
mainRect.Max.X -= 1 // Add padding right
- layout.sidebar = sideRect
+ uiLayout.sidebar = sideRect
pillsHeight := m.pillsAreaHeight()
if pillsHeight > 0 {
pillsHeight = min(pillsHeight, mainRect.Dy())
- chatRect, pillsRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-pillsHeight))
- layout.main = chatRect
- layout.pills = pillsRect
+ chatRect, pillsRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-pillsHeight))
+ uiLayout.main = chatRect
+ uiLayout.pills = pillsRect
} else {
- layout.main = mainRect
+ uiLayout.main = mainRect
}
// Add bottom margin to main
- layout.main.Max.Y -= 1
- layout.editor = editorRect
+ uiLayout.main.Max.Y -= 1
+ uiLayout.editor = editorRect
}
}
- if !layout.editor.Empty() {
+ if !uiLayout.editor.Empty() {
// Add editor margins 1 top and bottom
if len(m.attachments.List()) == 0 {
- layout.editor.Min.Y += 1
+ uiLayout.editor.Min.Y += 1
}
- layout.editor.Max.Y -= 1
+ uiLayout.editor.Max.Y -= 1
}
- return layout
+ return uiLayout
}
-// layout defines the positioning of UI elements.
-type layout struct {
+// uiLayout defines the positioning of UI elements.
+type uiLayout struct {
// area is the overall available area.
area uv.Rectangle