1
2 package internal
3
4 import (
5 "path/filepath"
6 "sort"
7 "strings"
8
9 "github.com/alecthomas/chroma"
10 )
11
12 var (
13 ignoredSuffixes = [...]string{
14
15 "~", ".bak", ".old", ".orig",
16
17 ".dpkg-dist", ".dpkg-old", ".ucf-dist", ".ucf-new", ".ucf-old",
18
19 ".rpmnew", ".rpmorig", ".rpmsave",
20
21 ".in",
22 }
23 )
24
25
26 var Registry = struct {
27 Lexers chroma.Lexers
28 byName map[string]chroma.Lexer
29 byAlias map[string]chroma.Lexer
30 }{
31 byName: map[string]chroma.Lexer{},
32 byAlias: map[string]chroma.Lexer{},
33 }
34
35
36 func Names(withAliases bool) []string {
37 out := []string{}
38 for _, lexer := range Registry.Lexers {
39 config := lexer.Config()
40 out = append(out, config.Name)
41 if withAliases {
42 out = append(out, config.Aliases...)
43 }
44 }
45 sort.Strings(out)
46 return out
47 }
48
49
50 func Get(name string) chroma.Lexer {
51 if lexer := Registry.byName[name]; lexer != nil {
52 return lexer
53 }
54 if lexer := Registry.byAlias[name]; lexer != nil {
55 return lexer
56 }
57 if lexer := Registry.byName[strings.ToLower(name)]; lexer != nil {
58 return lexer
59 }
60 if lexer := Registry.byAlias[strings.ToLower(name)]; lexer != nil {
61 return lexer
62 }
63
64 candidates := chroma.PrioritisedLexers{}
65
66 if lexer := Match("filename." + name); lexer != nil {
67 candidates = append(candidates, lexer)
68 }
69
70 if lexer := Match(name); lexer != nil {
71 candidates = append(candidates, lexer)
72 }
73 if len(candidates) == 0 {
74 return nil
75 }
76 sort.Sort(candidates)
77 return candidates[0]
78 }
79
80
81 func MatchMimeType(mimeType string) chroma.Lexer {
82 matched := chroma.PrioritisedLexers{}
83 for _, l := range Registry.Lexers {
84 for _, lmt := range l.Config().MimeTypes {
85 if mimeType == lmt {
86 matched = append(matched, l)
87 }
88 }
89 }
90 if len(matched) != 0 {
91 sort.Sort(matched)
92 return matched[0]
93 }
94 return nil
95 }
96
97
98 func Match(filename string) chroma.Lexer {
99 filename = filepath.Base(filename)
100 matched := chroma.PrioritisedLexers{}
101
102 for _, lexer := range Registry.Lexers {
103 config := lexer.Config()
104 for _, glob := range config.Filenames {
105 ok, err := filepath.Match(glob, filename)
106 if err != nil {
107 panic(err)
108 } else if ok {
109 matched = append(matched, lexer)
110 } else {
111 for _, suf := range &ignoredSuffixes {
112 ok, err := filepath.Match(glob+suf, filename)
113 if err != nil {
114 panic(err)
115 } else if ok {
116 matched = append(matched, lexer)
117 break
118 }
119 }
120 }
121 }
122 }
123 if len(matched) > 0 {
124 sort.Sort(matched)
125 return matched[0]
126 }
127 matched = nil
128
129 for _, lexer := range Registry.Lexers {
130 config := lexer.Config()
131 for _, glob := range config.AliasFilenames {
132 ok, err := filepath.Match(glob, filename)
133 if err != nil {
134 panic(err)
135 } else if ok {
136 matched = append(matched, lexer)
137 } else {
138 for _, suf := range &ignoredSuffixes {
139 ok, err := filepath.Match(glob+suf, filename)
140 if err != nil {
141 panic(err)
142 } else if ok {
143 matched = append(matched, lexer)
144 break
145 }
146 }
147 }
148 }
149 }
150 if len(matched) > 0 {
151 sort.Sort(matched)
152 return matched[0]
153 }
154 return nil
155 }
156
157
158 func Analyse(text string) chroma.Lexer {
159 var picked chroma.Lexer
160 highest := float32(0.0)
161 for _, lexer := range Registry.Lexers {
162 if analyser, ok := lexer.(chroma.Analyser); ok {
163 weight := analyser.AnalyseText(text)
164 if weight > highest {
165 picked = lexer
166 highest = weight
167 }
168 }
169 }
170 return picked
171 }
172
173
174 func Register(lexer chroma.Lexer) chroma.Lexer {
175 config := lexer.Config()
176 Registry.byName[config.Name] = lexer
177 Registry.byName[strings.ToLower(config.Name)] = lexer
178 for _, alias := range config.Aliases {
179 Registry.byAlias[alias] = lexer
180 Registry.byAlias[strings.ToLower(alias)] = lexer
181 }
182 Registry.Lexers = append(Registry.Lexers, lexer)
183 return lexer
184 }
185
186
187
188 func PlaintextRules() chroma.Rules {
189 return chroma.Rules{
190 "root": []chroma.Rule{
191 {`.+`, chroma.Text, nil},
192 {`\n`, chroma.Text, nil},
193 },
194 }
195 }
196
197
198 var Fallback chroma.Lexer = chroma.MustNewLazyLexer(&chroma.Config{
199 Name: "fallback",
200 Filenames: []string{"*"},
201 }, PlaintextRules)
202
View as plain text