11package diff
22
33import (
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-
535320func 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
541326func 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
577349func 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