gitlab.com/thomasboni/go-enry/v2@v2.8.3-0.20220418031202-30b0d7a3de98/data/rule/rule.go (about) 1 // Package rule contains rule-based heuristic implementations. 2 // It is used in the generated code in content.go for disambiguation of languages 3 // with colliding extensions, based on regexps from Linguist data. 4 package rule 5 6 // Heuristic consist of (a number of) rules where each, if matches, 7 // identifes content as belonging to a programming language(s). 8 type Heuristic interface { 9 Matcher 10 Languages() []string 11 } 12 13 // Matcher checks if the data matches (number of) pattern. 14 // Every heuristic rule below implements this interface. 15 // A regexp.Regexp satisfies this interface and can be used instead. 16 type Matcher interface { 17 Match(data []byte) bool 18 } 19 20 // languages struct incapsulate data common to every Matcher: all languages 21 // that it identifies. 22 type languages struct { 23 langs []string 24 } 25 26 // Languages returns all languages, identified by this Matcher. 27 func (l languages) Languages() []string { 28 return l.langs 29 } 30 31 // MatchingLanguages is a helper to create new languages. 32 func MatchingLanguages(langs ...string) languages { 33 return languages{langs} 34 } 35 36 // Implements a Heuristic. 37 type or struct { 38 languages 39 pattern Matcher 40 } 41 42 // Or rule matches, if a single matching pattern exists. 43 // It recives only one pattern as it relies on compile-time optimization that 44 // represtes union with | inside a single regexp. 45 func Or(l languages, r Matcher) Heuristic { 46 return or{l, r} 47 } 48 49 // Match implements rule.Matcher. 50 func (r or) Match(data []byte) bool { 51 return r.pattern.Match(data) 52 } 53 54 // Implements a Heuristic. 55 type and struct { 56 languages 57 patterns []Matcher 58 } 59 60 // And rule matches, if each of the patterns does match. 61 func And(l languages, m ...Matcher) Heuristic { 62 return and{l, m} 63 } 64 65 // Match implements data.Matcher. 66 func (r and) Match(data []byte) bool { 67 for _, p := range r.patterns { 68 if !p.Match(data) { 69 return false 70 } 71 } 72 return true 73 } 74 75 // Implements a Heuristic. 76 type not struct { 77 languages 78 Patterns []Matcher 79 } 80 81 // Not rule matches if none of the patterns match. 82 func Not(l languages, r ...Matcher) Heuristic { 83 return not{l, r} 84 } 85 86 // Match implements data.Matcher. 87 func (r not) Match(data []byte) bool { 88 for _, p := range r.Patterns { 89 if p.Match(data) { 90 return false 91 } 92 } 93 return true 94 } 95 96 // Implements a Heuristic. 97 type always struct { 98 languages 99 } 100 101 // Always rule always matches. Often is used as a default fallback. 102 func Always(l languages) Heuristic { 103 return always{l} 104 } 105 106 // Match implements Matcher. 107 func (r always) Match(data []byte) bool { 108 return true 109 }