Skip to content
This repository was archived by the owner on Sep 18, 2025. It is now read-only.

Commit b364394

Browse files
committed
initial chat refactor
wip
1 parent af838d1 commit b364394

13 files changed

Lines changed: 1667 additions & 315 deletions

File tree

internal/diff/diff.go

Lines changed: 9 additions & 237 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
package diff
22

33
import (
4-
"bytes"
54
"fmt"
65
"image/color"
7-
"io"
86
"regexp"
97
"strconv"
108
"strings"
119

12-
"github.com/alecthomas/chroma/v2"
13-
"github.com/alecthomas/chroma/v2/formatters"
14-
"github.com/alecthomas/chroma/v2/lexers"
15-
"github.com/alecthomas/chroma/v2/styles"
1610
"github.com/aymanbagabas/go-udiff"
1711
"github.com/charmbracelet/lipgloss/v2"
1812
"github.com/charmbracelet/x/ansi"
1913
"github.com/opencode-ai/opencode/internal/config"
14+
"github.com/opencode-ai/opencode/internal/highlight"
2015
"github.com/opencode-ai/opencode/internal/tui/theme"
2116
"github.com/sergi/go-diff/diffmatchpatch"
2217
)
@@ -322,229 +317,18 @@ func pairLines(lines []DiffLine) []linePair {
322317
// -------------------------------------------------------------------------
323318
// Syntax Highlighting
324319
// -------------------------------------------------------------------------
325-
326-
// SyntaxHighlight applies syntax highlighting to text based on file extension
327-
func SyntaxHighlight(w io.Writer, source, fileName, formatter string, bg color.Color) error {
328-
t := theme.CurrentTheme()
329-
330-
// Determine the language lexer to use
331-
l := lexers.Match(fileName)
332-
if l == nil {
333-
l = lexers.Analyse(source)
334-
}
335-
if l == nil {
336-
l = lexers.Fallback
337-
}
338-
l = chroma.Coalesce(l)
339-
340-
// Get the formatter
341-
f := formatters.Get(formatter)
342-
if f == nil {
343-
f = formatters.Fallback
344-
}
345-
346-
// Dynamic theme based on current theme values
347-
syntaxThemeXml := fmt.Sprintf(`
348-
<style name="opencode-theme">
349-
<!-- Base colors -->
350-
<entry type="Background" style="bg:%s"/>
351-
<entry type="Text" style="%s"/>
352-
<entry type="Other" style="%s"/>
353-
<entry type="Error" style="%s"/>
354-
<!-- Keywords -->
355-
<entry type="Keyword" style="%s"/>
356-
<entry type="KeywordConstant" style="%s"/>
357-
<entry type="KeywordDeclaration" style="%s"/>
358-
<entry type="KeywordNamespace" style="%s"/>
359-
<entry type="KeywordPseudo" style="%s"/>
360-
<entry type="KeywordReserved" style="%s"/>
361-
<entry type="KeywordType" style="%s"/>
362-
<!-- Names -->
363-
<entry type="Name" style="%s"/>
364-
<entry type="NameAttribute" style="%s"/>
365-
<entry type="NameBuiltin" style="%s"/>
366-
<entry type="NameBuiltinPseudo" style="%s"/>
367-
<entry type="NameClass" style="%s"/>
368-
<entry type="NameConstant" style="%s"/>
369-
<entry type="NameDecorator" style="%s"/>
370-
<entry type="NameEntity" style="%s"/>
371-
<entry type="NameException" style="%s"/>
372-
<entry type="NameFunction" style="%s"/>
373-
<entry type="NameLabel" style="%s"/>
374-
<entry type="NameNamespace" style="%s"/>
375-
<entry type="NameOther" style="%s"/>
376-
<entry type="NameTag" style="%s"/>
377-
<entry type="NameVariable" style="%s"/>
378-
<entry type="NameVariableClass" style="%s"/>
379-
<entry type="NameVariableGlobal" style="%s"/>
380-
<entry type="NameVariableInstance" style="%s"/>
381-
<!-- Literals -->
382-
<entry type="Literal" style="%s"/>
383-
<entry type="LiteralDate" style="%s"/>
384-
<entry type="LiteralString" style="%s"/>
385-
<entry type="LiteralStringBacktick" style="%s"/>
386-
<entry type="LiteralStringChar" style="%s"/>
387-
<entry type="LiteralStringDoc" style="%s"/>
388-
<entry type="LiteralStringDouble" style="%s"/>
389-
<entry type="LiteralStringEscape" style="%s"/>
390-
<entry type="LiteralStringHeredoc" style="%s"/>
391-
<entry type="LiteralStringInterpol" style="%s"/>
392-
<entry type="LiteralStringOther" style="%s"/>
393-
<entry type="LiteralStringRegex" style="%s"/>
394-
<entry type="LiteralStringSingle" style="%s"/>
395-
<entry type="LiteralStringSymbol" style="%s"/>
396-
<!-- Numbers -->
397-
<entry type="LiteralNumber" style="%s"/>
398-
<entry type="LiteralNumberBin" style="%s"/>
399-
<entry type="LiteralNumberFloat" style="%s"/>
400-
<entry type="LiteralNumberHex" style="%s"/>
401-
<entry type="LiteralNumberInteger" style="%s"/>
402-
<entry type="LiteralNumberIntegerLong" style="%s"/>
403-
<entry type="LiteralNumberOct" style="%s"/>
404-
<!-- Operators -->
405-
<entry type="Operator" style="%s"/>
406-
<entry type="OperatorWord" style="%s"/>
407-
<entry type="Punctuation" style="%s"/>
408-
<!-- Comments -->
409-
<entry type="Comment" style="%s"/>
410-
<entry type="CommentHashbang" style="%s"/>
411-
<entry type="CommentMultiline" style="%s"/>
412-
<entry type="CommentSingle" style="%s"/>
413-
<entry type="CommentSpecial" style="%s"/>
414-
<entry type="CommentPreproc" style="%s"/>
415-
<!-- Generic styles -->
416-
<entry type="Generic" style="%s"/>
417-
<entry type="GenericDeleted" style="%s"/>
418-
<entry type="GenericEmph" style="italic %s"/>
419-
<entry type="GenericError" style="%s"/>
420-
<entry type="GenericHeading" style="bold %s"/>
421-
<entry type="GenericInserted" style="%s"/>
422-
<entry type="GenericOutput" style="%s"/>
423-
<entry type="GenericPrompt" style="%s"/>
424-
<entry type="GenericStrong" style="bold %s"/>
425-
<entry type="GenericSubheading" style="bold %s"/>
426-
<entry type="GenericTraceback" style="%s"/>
427-
<entry type="GenericUnderline" style="underline"/>
428-
<entry type="TextWhitespace" style="%s"/>
429-
</style>
430-
`,
431-
getColor(t.Background()), // Background
432-
getColor(t.Text()), // Text
433-
getColor(t.Text()), // Other
434-
getColor(t.Error()), // Error
435-
436-
getColor(t.SyntaxKeyword()), // Keyword
437-
getColor(t.SyntaxKeyword()), // KeywordConstant
438-
getColor(t.SyntaxKeyword()), // KeywordDeclaration
439-
getColor(t.SyntaxKeyword()), // KeywordNamespace
440-
getColor(t.SyntaxKeyword()), // KeywordPseudo
441-
getColor(t.SyntaxKeyword()), // KeywordReserved
442-
getColor(t.SyntaxType()), // KeywordType
443-
444-
getColor(t.Text()), // Name
445-
getColor(t.SyntaxVariable()), // NameAttribute
446-
getColor(t.SyntaxType()), // NameBuiltin
447-
getColor(t.SyntaxVariable()), // NameBuiltinPseudo
448-
getColor(t.SyntaxType()), // NameClass
449-
getColor(t.SyntaxVariable()), // NameConstant
450-
getColor(t.SyntaxFunction()), // NameDecorator
451-
getColor(t.SyntaxVariable()), // NameEntity
452-
getColor(t.SyntaxType()), // NameException
453-
getColor(t.SyntaxFunction()), // NameFunction
454-
getColor(t.Text()), // NameLabel
455-
getColor(t.SyntaxType()), // NameNamespace
456-
getColor(t.SyntaxVariable()), // NameOther
457-
getColor(t.SyntaxKeyword()), // NameTag
458-
getColor(t.SyntaxVariable()), // NameVariable
459-
getColor(t.SyntaxVariable()), // NameVariableClass
460-
getColor(t.SyntaxVariable()), // NameVariableGlobal
461-
getColor(t.SyntaxVariable()), // NameVariableInstance
462-
463-
getColor(t.SyntaxString()), // Literal
464-
getColor(t.SyntaxString()), // LiteralDate
465-
getColor(t.SyntaxString()), // LiteralString
466-
getColor(t.SyntaxString()), // LiteralStringBacktick
467-
getColor(t.SyntaxString()), // LiteralStringChar
468-
getColor(t.SyntaxString()), // LiteralStringDoc
469-
getColor(t.SyntaxString()), // LiteralStringDouble
470-
getColor(t.SyntaxString()), // LiteralStringEscape
471-
getColor(t.SyntaxString()), // LiteralStringHeredoc
472-
getColor(t.SyntaxString()), // LiteralStringInterpol
473-
getColor(t.SyntaxString()), // LiteralStringOther
474-
getColor(t.SyntaxString()), // LiteralStringRegex
475-
getColor(t.SyntaxString()), // LiteralStringSingle
476-
getColor(t.SyntaxString()), // LiteralStringSymbol
477-
478-
getColor(t.SyntaxNumber()), // LiteralNumber
479-
getColor(t.SyntaxNumber()), // LiteralNumberBin
480-
getColor(t.SyntaxNumber()), // LiteralNumberFloat
481-
getColor(t.SyntaxNumber()), // LiteralNumberHex
482-
getColor(t.SyntaxNumber()), // LiteralNumberInteger
483-
getColor(t.SyntaxNumber()), // LiteralNumberIntegerLong
484-
getColor(t.SyntaxNumber()), // LiteralNumberOct
485-
486-
getColor(t.SyntaxOperator()), // Operator
487-
getColor(t.SyntaxKeyword()), // OperatorWord
488-
getColor(t.SyntaxPunctuation()), // Punctuation
489-
490-
getColor(t.SyntaxComment()), // Comment
491-
getColor(t.SyntaxComment()), // CommentHashbang
492-
getColor(t.SyntaxComment()), // CommentMultiline
493-
getColor(t.SyntaxComment()), // CommentSingle
494-
getColor(t.SyntaxComment()), // CommentSpecial
495-
getColor(t.SyntaxKeyword()), // CommentPreproc
496-
497-
getColor(t.Text()), // Generic
498-
getColor(t.Error()), // GenericDeleted
499-
getColor(t.Text()), // GenericEmph
500-
getColor(t.Error()), // GenericError
501-
getColor(t.Text()), // GenericHeading
502-
getColor(t.Success()), // GenericInserted
503-
getColor(t.TextMuted()), // GenericOutput
504-
getColor(t.Text()), // GenericPrompt
505-
getColor(t.Text()), // GenericStrong
506-
getColor(t.Text()), // GenericSubheading
507-
getColor(t.Error()), // GenericTraceback
508-
getColor(t.Text()), // TextWhitespace
509-
)
510-
511-
r := strings.NewReader(syntaxThemeXml)
512-
style := chroma.MustNewXMLStyle(r)
513-
514-
// Modify the style to use the provided background
515-
s, err := style.Builder().Transform(
516-
func(t chroma.StyleEntry) chroma.StyleEntry {
517-
r, g, b, _ := bg.RGBA()
518-
t.Background = chroma.NewColour(uint8(r>>8), uint8(g>>8), uint8(b>>8))
519-
return t
520-
},
521-
).Build()
522-
if err != nil {
523-
s = styles.Fallback
524-
}
525-
526-
// Tokenize and format
527-
it, err := l.Tokenise(nil, source)
528-
if err != nil {
529-
return err
530-
}
531-
532-
return f.Format(w, s, it)
533-
}
534-
535320
func getColor(c color.Color) string {
536321
rgba := color.RGBAModel.Convert(c).(color.RGBA)
537322
return fmt.Sprintf("#%02x%02x%02x", rgba.R, rgba.G, rgba.B)
538323
}
539324

540325
// highlightLine applies syntax highlighting to a single line
541326
func highlightLine(fileName string, line string, bg color.Color) string {
542-
var buf bytes.Buffer
543-
err := SyntaxHighlight(&buf, line, fileName, "terminal16m", bg)
327+
highlighted, err := highlight.SyntaxHighlight(line, fileName, bg)
544328
if err != nil {
545329
return line
546330
}
547-
return buf.String()
331+
return highlighted
548332
}
549333

550334
// createStyles generates the lipgloss styles needed for rendering diffs
@@ -561,18 +345,6 @@ func createStyles(t theme.Theme) (removedLineStyle, addedLineStyle, contextLineS
561345
// Rendering Functions
562346
// -------------------------------------------------------------------------
563347

564-
func lipglossToHex(color color.Color) string {
565-
r, g, b, a := color.RGBA()
566-
567-
// Scale uint32 values (0-65535) to uint8 (0-255).
568-
r8 := uint8(r >> 8)
569-
g8 := uint8(g >> 8)
570-
b8 := uint8(b >> 8)
571-
a8 := uint8(a >> 8)
572-
573-
return fmt.Sprintf("#%02x%02x%02x%02x", r8, g8, b8, a8)
574-
}
575-
576348
// applyHighlighting applies intra-line highlighting to a piece of text
577349
func applyHighlighting(content string, segments []Segment, segmentType LineType, highlightBg color.Color) string {
578350
// Find all ANSI sequences in the content
@@ -614,7 +386,7 @@ func applyHighlighting(content string, segments []Segment, segmentType LineType,
614386

615387
// Get the appropriate color based on terminal background
616388
bgColor := lipgloss.Color(getColor(highlightBg))
617-
fgColor := lipgloss.Color(getColor(theme.CurrentTheme().Background()))
389+
// fgColor := lipgloss.Color(getColor(theme.CurrentTheme().Background()))
618390

619391
for i := 0; i < len(content); {
620392
// Check if we're at an ANSI sequence
@@ -651,15 +423,15 @@ func applyHighlighting(content string, segments []Segment, segmentType LineType,
651423
currentStyle := ansiSequences[currentPos]
652424

653425
// Apply foreground and background highlight
654-
sb.WriteString("\x1b[38;2;")
655-
r, g, b, _ := fgColor.RGBA()
656-
sb.WriteString(fmt.Sprintf("%d;%d;%dm", r>>8, g>>8, b>>8))
426+
// sb.WriteString("\x1b[38;2;")
427+
// r, g, b, _ := fgColor.RGBA()
428+
// sb.WriteString(fmt.Sprintf("%d;%d;%dm", r>>8, g>>8, b>>8))
657429
sb.WriteString("\x1b[48;2;")
658-
r, g, b, _ = bgColor.RGBA()
430+
r, g, b, _ := bgColor.RGBA()
659431
sb.WriteString(fmt.Sprintf("%d;%d;%dm", r>>8, g>>8, b>>8))
660432
sb.WriteString(char)
661433
// Reset foreground and background
662-
sb.WriteString("\x1b[39m")
434+
// sb.WriteString("\x1b[39m")
663435

664436
// Reapply the original ANSI sequence
665437
sb.WriteString(currentStyle)

0 commit comments

Comments
 (0)