mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-21 01:34:22 +01:00
feat: better assistant message visual
This commit is contained in:
@@ -23,17 +23,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type blockRenderer struct {
|
type blockRenderer struct {
|
||||||
textColor compat.AdaptiveColor
|
textColor compat.AdaptiveColor
|
||||||
border bool
|
backgroundColor compat.AdaptiveColor
|
||||||
borderColor *compat.AdaptiveColor
|
border bool
|
||||||
borderLeft bool
|
borderColor *compat.AdaptiveColor
|
||||||
borderRight bool
|
borderLeft bool
|
||||||
paddingTop int
|
borderRight bool
|
||||||
paddingBottom int
|
paddingTop int
|
||||||
paddingLeft int
|
paddingBottom int
|
||||||
paddingRight int
|
paddingLeft int
|
||||||
marginTop int
|
paddingRight int
|
||||||
marginBottom int
|
marginTop int
|
||||||
|
marginBottom int
|
||||||
}
|
}
|
||||||
|
|
||||||
type renderingOption func(*blockRenderer)
|
type renderingOption func(*blockRenderer)
|
||||||
@@ -44,6 +45,12 @@ func WithTextColor(color compat.AdaptiveColor) renderingOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithBackgroundColor(color compat.AdaptiveColor) renderingOption {
|
||||||
|
return func(c *blockRenderer) {
|
||||||
|
c.backgroundColor = color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func WithNoBorder() renderingOption {
|
func WithNoBorder() renderingOption {
|
||||||
return func(c *blockRenderer) {
|
return func(c *blockRenderer) {
|
||||||
c.border = false
|
c.border = false
|
||||||
@@ -132,14 +139,15 @@ func renderContentBlock(
|
|||||||
) string {
|
) string {
|
||||||
t := theme.CurrentTheme()
|
t := theme.CurrentTheme()
|
||||||
renderer := &blockRenderer{
|
renderer := &blockRenderer{
|
||||||
textColor: t.TextMuted(),
|
textColor: t.TextMuted(),
|
||||||
border: true,
|
backgroundColor: t.BackgroundPanel(),
|
||||||
borderLeft: true,
|
border: true,
|
||||||
borderRight: false,
|
borderLeft: true,
|
||||||
paddingTop: 1,
|
borderRight: false,
|
||||||
paddingBottom: 1,
|
paddingTop: 1,
|
||||||
paddingLeft: 2,
|
paddingBottom: 1,
|
||||||
paddingRight: 2,
|
paddingLeft: 2,
|
||||||
|
paddingRight: 2,
|
||||||
}
|
}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
option(renderer)
|
option(renderer)
|
||||||
@@ -152,7 +160,7 @@ func renderContentBlock(
|
|||||||
|
|
||||||
style := styles.NewStyle().
|
style := styles.NewStyle().
|
||||||
Foreground(renderer.textColor).
|
Foreground(renderer.textColor).
|
||||||
Background(t.BackgroundPanel()).
|
Background(renderer.backgroundColor).
|
||||||
PaddingTop(renderer.paddingTop).
|
PaddingTop(renderer.paddingTop).
|
||||||
PaddingBottom(renderer.paddingBottom).
|
PaddingBottom(renderer.paddingBottom).
|
||||||
PaddingLeft(renderer.paddingLeft).
|
PaddingLeft(renderer.paddingLeft).
|
||||||
@@ -211,7 +219,7 @@ func renderText(
|
|||||||
switch casted := message.(type) {
|
switch casted := message.(type) {
|
||||||
case opencode.AssistantMessage:
|
case opencode.AssistantMessage:
|
||||||
ts = time.UnixMilli(int64(casted.Time.Created))
|
ts = time.UnixMilli(int64(casted.Time.Created))
|
||||||
content = util.ToMarkdown(text, width, backgroundColor)
|
content = util.ToMarkdown(text, width+2, t.Background())
|
||||||
case opencode.UserMessage:
|
case opencode.UserMessage:
|
||||||
ts = time.UnixMilli(int64(casted.Time.Created))
|
ts = time.UnixMilli(int64(casted.Time.Created))
|
||||||
base := styles.NewStyle().Foreground(t.Text()).Background(backgroundColor)
|
base := styles.NewStyle().Foreground(t.Text()).Background(backgroundColor)
|
||||||
@@ -286,14 +294,14 @@ func renderText(
|
|||||||
width,
|
width,
|
||||||
WithTextColor(t.Text()),
|
WithTextColor(t.Text()),
|
||||||
WithBorderColor(t.Secondary()),
|
WithBorderColor(t.Secondary()),
|
||||||
WithBorderRight(),
|
|
||||||
)
|
)
|
||||||
case opencode.AssistantMessage:
|
case opencode.AssistantMessage:
|
||||||
return renderContentBlock(
|
return renderContentBlock(
|
||||||
app,
|
app,
|
||||||
content,
|
content,
|
||||||
width,
|
width+2,
|
||||||
WithBorderColor(t.Accent()),
|
WithNoBorder(),
|
||||||
|
WithBackgroundColor(t.Background()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
package util
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/charmbracelet/lipgloss/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PreventHyphenBreaks replaces regular hyphens with non-breaking hyphens to prevent
|
|
||||||
// sparse word breaks in hyphenated terms like "claude-code-action".
|
|
||||||
// This improves readability by keeping hyphenated words together.
|
|
||||||
// Only preserves hyphens within words, not markdown syntax like bullet points.
|
|
||||||
func PreventHyphenBreaks(text string) string {
|
|
||||||
// Use regex to match hyphens that are between word characters
|
|
||||||
// This preserves hyphens in words like "claude-code-action" but not in "- [ ]"
|
|
||||||
re := regexp.MustCompile(`(\w)-(\w)`)
|
|
||||||
return re.ReplaceAllString(text, "$1\u2011$2")
|
|
||||||
}
|
|
||||||
|
|
||||||
// RestoreHyphens converts non-breaking hyphens back to regular hyphens.
|
|
||||||
// This should be called after text processing (like word wrapping) is complete.
|
|
||||||
func RestoreHyphens(text string) string {
|
|
||||||
return strings.ReplaceAll(text, "\u2011", "-")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessTextWithHyphens applies hyphen preservation to text during processing.
|
|
||||||
// It wraps the provided processFunc with hyphen handling.
|
|
||||||
func ProcessTextWithHyphens(text string, processFunc func(string) string) string {
|
|
||||||
preserved := PreventHyphenBreaks(text)
|
|
||||||
processed := processFunc(preserved)
|
|
||||||
return RestoreHyphens(processed)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMessageContainerFrame calculates the actual horizontal frame size
|
|
||||||
// (padding + borders) for message containers based on current theme.
|
|
||||||
func GetMessageContainerFrame() int {
|
|
||||||
style := lipgloss.NewStyle().
|
|
||||||
BorderStyle(lipgloss.ThickBorder()).
|
|
||||||
BorderLeft(true).
|
|
||||||
BorderRight(true).
|
|
||||||
PaddingLeft(2).
|
|
||||||
PaddingRight(2)
|
|
||||||
return style.GetHorizontalFrameSize()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMarkdownContainerFrame calculates the actual horizontal frame size
|
|
||||||
// for markdown containers based on current theme.
|
|
||||||
func GetMarkdownContainerFrame() int {
|
|
||||||
// Markdown containers use the same styling as message containers
|
|
||||||
return GetMessageContainerFrame()
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user