1package common
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7
8 "github.com/alecthomas/chroma/v2/lexers"
9 gansi "github.com/charmbracelet/glamour/v2/ansi"
10 "github.com/charmbracelet/soft-serve/pkg/ui/styles"
11)
12
13// 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 (because
17 // it's counting bytes instead of runes) but in this case it's okay
18 // 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 for
29 // 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"), mll
34}
35
36// 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().Name
43 }
44 formatter := &gansi.CodeBlockElement{
45 Code: c,
46 Language: lang,
47 }
48 r := strings.Builder{}
49 styles := StyleConfig()
50 styles.CodeBlock.Margin = &zero
51 rctx := StyleRendererWithStyles(styles)
52 err := formatter.Render(&r, rctx)
53 if err != nil {
54 return "", err //nolint:wrapcheck
55 }
56 return r.String(), nil
57}
58
59// UnquoteFilename unquotes a filename.
60// When Git is with "core.quotePath" set to "true" (default), it will quote
61// 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 := s
65 if n, err := strconv.Unquote(`"` + s + `"`); err == nil {
66 name = n
67 }
68
69 name = strconv.Quote(name)
70 return strings.Trim(name, `"`)
71}