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