package main import ( "bytes" "fmt" "path/filepath" "regexp" "strconv" "strings" "github.com/alecthomas/chroma/v2/quick" ) const reviewContextLines = 3 var codeHighlightTheme = "github-dark" var colorEnabled = true var hunkHeaderPattern = regexp.MustCompile(`^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@`) type highlightedDiffLine struct { gutter string code string selected bool } type parsedDiffLine struct { raw string oldLine int newLine int header bool notice bool selected bool } func highlightDiff(path, hunk string, startLine, endLine int, side string) []highlightedDiffLine { if hunk == "" { return []highlightedDiffLine{{code: "(GitHub did not return a diff hunk)"}} } if endLine <= 0 { endLine = startLine } if startLine <= 0 { startLine = endLine } if startLine > endLine { startLine, endLine = endLine, startLine } parsed := parseDiff(hunk, startLine, endLine, side) visible := reviewedWindow(parsed) padding := commonIndent(visible) lexer := lexerForPath(path) out := make([]highlightedDiffLine, 0, len(visible)) for _, line := range visible { if line.raw == "⋯" { code := "⋯" if colorEnabled { code = "\x1b[38;5;245m⋯\x1b[0m" } out = append(out, highlightedDiffLine{code: code}) continue } if line.notice { code := line.raw if colorEnabled { code = "\x1b[38;5;245m" + line.raw + "\x1b[0m" } out = append(out, highlightedDiffLine{code: code}) continue } if line.header { code := line.raw if colorEnabled { code = "\x1b[38;5;141m" + line.raw + "\x1b[0m" } out = append(out, highlightedDiffLine{code: code}) continue } out = append(out, renderDiffLine(lexer, line, padding)) } return out } func parseDiff(hunk string, startLine, endLine int, side string) []parsedDiffLine { oldLine, newLine := 0, 0 lines := make([]parsedDiffLine, 0, strings.Count(hunk, "\n")+1) for _, raw := range strings.Split(hunk, "\n") { if match := hunkHeaderPattern.FindStringSubmatch(raw); match != nil { oldLine, _ = strconv.Atoi(match[1]) newLine, _ = strconv.Atoi(match[2]) lines = append(lines, parsedDiffLine{raw: raw, header: true}) continue } line := parsedDiffLine{raw: raw} switch { case strings.HasPrefix(raw, "+"): line.newLine = newLine newLine++ case strings.HasPrefix(raw, "-"): line.oldLine = oldLine oldLine++ case strings.HasPrefix(raw, `\`): // "\ No newline at end of file" has no source coordinate. default: line.oldLine, line.newLine = oldLine, newLine oldLine++ newLine++ } coordinate := line.newLine if side == "LEFT" { coordinate = line.oldLine } line.selected = coordinate > 0 && coordinate >= startLine && coordinate <= endLine lines = append(lines, line) } return lines } func reviewedWindow(lines []parsedDiffLine) []parsedDiffLine { first, last := -1, -1 for i, line := range lines { if line.selected { if first == -1 { first = i } last = i } } if first == -1 { out := make([]parsedDiffLine, 0, 2) for _, line := range lines { if line.header { out = append(out, line) break } } return append(out, parsedDiffLine{ raw: "(original reviewed lines unavailable in GitHub's historical diff)", notice: true, }) } start := max(0, first-reviewContextLines) end := min(len(lines), last+reviewContextLines+1) header := -1 for i := first; i >= 0; i-- { if lines[i].header { header = i break } } out := make([]parsedDiffLine, 0, end-start+3) if header >= 0 && header < start { out = append(out, lines[header]) } if start > 0 && start != header { out = append(out, parsedDiffLine{raw: "⋯"}) } out = append(out, lines[start:end]...) if end < len(lines) { out = append(out, parsedDiffLine{raw: "⋯"}) } return out } func renderDiffLine(lexer string, line parsedDiffLine, padding int) highlightedDiffLine { marker, source := " ", line.raw lineNumber := "" markerStyle := "\x1b[38;5;245m" switch { case strings.HasPrefix(line.raw, "+"): marker, source = "+", strings.TrimPrefix(line.raw, "+") lineNumber = coordinateText(line.newLine) markerStyle = "\x1b[38;5;114m" case strings.HasPrefix(line.raw, "-"): marker, source = "-", strings.TrimPrefix(line.raw, "-") lineNumber = coordinateText(line.oldLine) markerStyle = "\x1b[38;5;203m" default: source = strings.TrimPrefix(line.raw, " ") lineNumber = coordinateText(line.newLine) if lineNumber == "" { lineNumber = coordinateText(line.oldLine) } } source = strings.ReplaceAll(source, "\t", " ") source = trimIndent(source, padding) gutter := fmt.Sprintf("%5s %s ", lineNumber, marker) if colorEnabled { gutter = fmt.Sprintf( "\x1b[38;5;245m%5s\x1b[0m %s%s\x1b[0m ", lineNumber, markerStyle, marker, ) } return highlightedDiffLine{ gutter: gutter, code: highlightedSource(lexer, source), selected: line.selected, } } func commonIndent(lines []parsedDiffLine) int { padding := -1 for _, line := range lines { if line.header || line.notice || line.raw == "⋯" || strings.HasPrefix(line.raw, `\`) { continue } source := line.raw if strings.HasPrefix(source, "+") || strings.HasPrefix(source, "-") || strings.HasPrefix(source, " ") { source = source[1:] } source = strings.ReplaceAll(source, "\t", " ") if strings.TrimSpace(source) == "" { continue } indent := len(source) - len(strings.TrimLeft(source, " ")) if padding == -1 || indent < padding { padding = indent } } return max(0, padding) } func trimIndent(source string, padding int) string { for padding > 0 && strings.HasPrefix(source, " ") { source = source[1:] padding-- } return source } func coordinateText(line int) string { if line <= 0 { return "" } return strconv.Itoa(line) } func highlightedSource(lexer, source string) string { if !colorEnabled { return source } var highlighted bytes.Buffer if err := quick.Highlight(&highlighted, source, lexer, "terminal16m", codeHighlightTheme); err != nil { return source } return strings.TrimSuffix(highlighted.String(), "\n") } func lexerForPath(path string) string { ext := strings.TrimPrefix(filepath.Ext(path), ".") if ext == "" { return "plaintext" } return ext }