1package common23import (4 "fmt"5 "strconv"6 "strings"78 gansi "charm.land/glamour/v2/ansi"9 "github.com/alecthomas/chroma/v2/lexers"10 "github.com/charmbracelet/soft-serve/pkg/ui/styles"11)1213// FormatLineNumber adds line numbers to a string.14func FormatLineNumber(styles *styles.Styles, s string, color bool) (string, int) {15 lines := strings.Split(s, "\n")16 // NB: len() is not a particularly safe way to count string width (because17 // it's counting bytes instead of runes) but in this case it's okay18 // because we're only dealing with digits, which are one byte each.19 mll := len(fmt.Sprintf("%d", len(lines)))20 for i, l := range lines {21 digit := fmt.Sprintf("%*d", mll, i+1)22 bar := "│"23 if color {24 digit = styles.Code.LineDigit.Render(digit)25 bar = styles.Code.LineBar.Render(bar)26 }27 if i < len(lines)-1 || len(l) != 0 {28 // If the final line was a newline we'll get an empty string for29 // the final line, so drop the newline altogether.30 lines[i] = fmt.Sprintf(" %s %s %s", digit, bar, l)31 }32 }33 return strings.Join(lines, "\n"), mll34}3536// FormatHighlight adds syntax highlighting to a string.37func FormatHighlight(p, c string) (string, error) {38 zero := uint(0)39 lang := ""40 lexer := lexers.Match(p)41 if lexer != nil && lexer.Config() != nil {42 lang = lexer.Config().Name43 }44 formatter := &gansi.CodeBlockElement{45 Code: c,46 Language: lang,47 }48 r := strings.Builder{}49 styles := StyleConfig()50 styles.CodeBlock.Margin = &zero51 rctx := StyleRendererWithStyles(styles)52 err := formatter.Render(&r, rctx)53 if err != nil {54 return "", err55 }56 return r.String(), nil57}5859// UnquoteFilename unquotes a filename.60// When Git is with "core.quotePath" set to "true" (default), it will quote61// the filename with double quotes if it contains control characters or unicode.62// this function will unquote the filename.63func UnquoteFilename(s string) string {64 name := s65 if n, err := strconv.Unquote(`"` + s + `"`); err == nil {66 name = n67 }6869 name = strconv.Quote(name)70 return strings.Trim(name, `"`)71}