From cb792c0985695ac5ce6f19fb7ad512f8b736efdf Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sun, 26 Mar 2017 20:09:06 -0400 Subject: [PATCH] Make some types private --- examples/syncat.go | 1 + ftdetect.go | 2 +- highlighter.go | 45 +++++++++++++++++------------------ parser.go | 58 ++++++++++++++++++++++++++-------------------- 4 files changed, 58 insertions(+), 48 deletions(-) diff --git a/examples/syncat.go b/examples/syncat.go index 6b41526..fffdf2f 100644 --- a/examples/syncat.go +++ b/examples/syncat.go @@ -47,6 +47,7 @@ func main() { colN := 0 for _, c := range l { if group, ok := matches[lineN][colN]; ok { + // There are more possible groups available than just these ones if group == highlight.Groups["statement"] { color.Set(color.FgGreen) } else if group == highlight.Groups["identifier"] { diff --git a/ftdetect.go b/ftdetect.go index 2d9e296..a649d4b 100644 --- a/ftdetect.go +++ b/ftdetect.go @@ -14,6 +14,6 @@ func DetectFiletype(defs []*Def, filename string, firstLine []byte) *Def { emptyDef := new(Def) emptyDef.FileType = "Unknown" - emptyDef.rules = new(Rules) + emptyDef.rules = new(rules) return emptyDef } diff --git a/highlighter.go b/highlighter.go index 14c5962..4b8abf0 100644 --- a/highlighter.go +++ b/highlighter.go @@ -21,7 +21,7 @@ func combineLineMatch(src, dst LineMatch) LineMatch { } // A State represents the region at the end of a line -type State *Region +type State *region // LineStates is an interface for a buffer-like object which can also store the states and matches for every line type LineStates interface { @@ -34,7 +34,7 @@ type LineStates interface { // A Highlighter contains the information needed to highlight a string type Highlighter struct { - lastRegion *Region + lastRegion *region def *Def } @@ -47,7 +47,7 @@ func NewHighlighter(def *Def) *Highlighter { // LineMatch represents the syntax highlighting matches for one line. Each index where the coloring is changed is marked with that // color's group (represented as one byte) -type LineMatch map[int]uint8 +type LineMatch map[int]Group func findIndex(regex *regexp2.Regexp, str []rune, canMatchStart, canMatchEnd bool) []int { regexStr := regex.String() @@ -83,47 +83,48 @@ func findAllIndex(regex *regexp.Regexp, str []rune, canMatchStart, canMatchEnd b return regex.FindAllIndex([]byte(string(str)), -1) } -func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchEnd bool, lineNum int, line []rune, region *Region, statesOnly bool) LineMatch { +func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchEnd bool, lineNum int, line []rune, curRegion *region, statesOnly bool) LineMatch { // highlights := make(LineMatch) if start == 0 { if !statesOnly { - highlights[0] = region.group + highlights[0] = curRegion.group } } - loc := findIndex(region.end, line, start == 0, canMatchEnd) + loc := findIndex(curRegion.end, line, start == 0, canMatchEnd) if loc != nil { if !statesOnly { - highlights[start+loc[1]-1] = region.group + highlights[start+loc[1]-1] = curRegion.group } - if region.parent == nil { + if curRegion.parent == nil { if !statesOnly { highlights[start+loc[1]] = 0 - h.highlightRegion(highlights, start, false, lineNum, line[:loc[0]], region, statesOnly) + h.highlightRegion(highlights, start, false, lineNum, line[:loc[0]], curRegion, statesOnly) } h.highlightEmptyRegion(highlights, start+loc[1], canMatchEnd, lineNum, line[loc[1]:], statesOnly) return highlights } if !statesOnly { - highlights[start+loc[1]] = region.parent.group - h.highlightRegion(highlights, start, false, lineNum, line[:loc[0]], region, statesOnly) + highlights[start+loc[1]] = curRegion.parent.group + h.highlightRegion(highlights, start, false, lineNum, line[:loc[0]], curRegion, statesOnly) } - h.highlightRegion(highlights, start+loc[1], canMatchEnd, lineNum, line[loc[1]:], region.parent, statesOnly) + h.highlightRegion(highlights, start+loc[1], canMatchEnd, lineNum, line[loc[1]:], curRegion.parent, statesOnly) return highlights } if len(line) == 0 || statesOnly { if canMatchEnd { - h.lastRegion = region + h.lastRegion = curRegion } return highlights } firstLoc := []int{len(line), 0} - var firstRegion *Region - for _, r := range region.rules.regions { + + var firstRegion *region + for _, r := range curRegion.rules.regions { loc := findIndex(r.start, line, start == 0, canMatchEnd) if loc != nil { if loc[0] < firstLoc[0] { @@ -134,17 +135,17 @@ func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchE } if firstLoc[0] != len(line) { highlights[start+firstLoc[0]] = firstRegion.group - h.highlightRegion(highlights, start, false, lineNum, line[:firstLoc[0]], region, statesOnly) + h.highlightRegion(highlights, start, false, lineNum, line[:firstLoc[0]], curRegion, statesOnly) h.highlightRegion(highlights, start+firstLoc[1], canMatchEnd, lineNum, line[firstLoc[1]:], firstRegion, statesOnly) return highlights } - fullHighlights := make([]uint8, len([]rune(string(line)))) + fullHighlights := make([]Group, len([]rune(string(line)))) for i := 0; i < len(fullHighlights); i++ { - fullHighlights[i] = region.group + fullHighlights[i] = curRegion.group } - for _, p := range region.rules.patterns { + for _, p := range curRegion.rules.patterns { matches := findAllIndex(p.regex, line, start == 0, canMatchEnd) for _, m := range matches { for i := m[0]; i < m[1]; i++ { @@ -161,7 +162,7 @@ func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchE } if canMatchEnd { - h.lastRegion = region + h.lastRegion = curRegion } return highlights @@ -176,7 +177,7 @@ func (h *Highlighter) highlightEmptyRegion(highlights LineMatch, start int, canM } firstLoc := []int{len(line), 0} - var firstRegion *Region + var firstRegion *region for _, r := range h.def.rules.regions { loc := findIndex(r.start, line, start == 0, canMatchEnd) if loc != nil { @@ -203,7 +204,7 @@ func (h *Highlighter) highlightEmptyRegion(highlights LineMatch, start int, canM return highlights } - fullHighlights := make([]uint8, len(line)) + fullHighlights := make([]Group, len(line)) for _, p := range h.def.rules.patterns { matches := findAllIndex(p.regex, line, start == 0, canMatchEnd) for _, m := range matches { diff --git a/parser.go b/parser.go index bf57752..95fce74 100644 --- a/parser.go +++ b/parser.go @@ -9,12 +9,18 @@ import ( "gopkg.in/yaml.v2" ) -var Groups map[string]uint8 -var numGroups uint8 +// A Group represents a syntax group +type Group uint8 -func GetGroup(n uint8) string { +// Groups contains all of the groups that are defined +// You can access them in the map via their string name +var Groups map[string]Group +var numGroups Group + +// String returns the group name attached to the specific group +func (g Group) String() string { for k, v := range Groups { - if v == n { + if v == g { return k } } @@ -28,40 +34,40 @@ func GetGroup(n uint8) string { type Def struct { FileType string ftdetect []*regexp.Regexp - rules *Rules + rules *rules } // A Pattern is one simple syntax rule // It has a group that the rule belongs to, as well as // the regular expression to match the pattern -type Pattern struct { - group uint8 +type pattern struct { + group Group regex *regexp.Regexp } -// Rules defines which patterns and regions can be used to highlight +// rules defines which patterns and regions can be used to highlight // a filetype -type Rules struct { - regions []*Region - patterns []*Pattern +type rules struct { + regions []*region + patterns []*pattern includes []string } -// A Region is a highlighted region (such as a multiline comment, or a string) +// A region is a highlighted region (such as a multiline comment, or a string) // It belongs to a group, and has start and end regular expressions -// A Region also has rules of its own that only apply when matching inside the +// A region also has rules of its own that only apply when matching inside the // region and also rules from the above region do not match inside this region // Note that a region may contain more regions -type Region struct { - group uint8 - parent *Region +type region struct { + group Group + parent *region start *regexp2.Regexp end *regexp2.Regexp - rules *Rules + rules *rules } func init() { - Groups = make(map[string]uint8) + Groups = make(map[string]Group) } // ParseDef parses an input syntax file into a highlight Def @@ -118,6 +124,8 @@ func ParseDef(input []byte) (s *Def, err error) { return s, err } +// ResolveIncludes will sort out the rules for including other filetypes +// You should call this after parsing all the Defs func ResolveIncludes(defs []*Def) { for _, d := range defs { resolveIncludesInDef(defs, d) @@ -139,7 +147,7 @@ func resolveIncludesInDef(defs []*Def, d *Def) { } } -func resolveIncludesInRegion(defs []*Def, region *Region) { +func resolveIncludesInRegion(defs []*Def, region *region) { for _, lang := range region.rules.includes { for _, searchDef := range defs { if lang == searchDef.FileType { @@ -154,8 +162,8 @@ func resolveIncludesInRegion(defs []*Def, region *Region) { } } -func parseRules(input []interface{}, curRegion *Region) (*Rules, error) { - rules := new(Rules) +func parseRules(input []interface{}, curRegion *region) (*rules, error) { + rules := new(rules) for _, v := range input { rule := v.(map[interface{}]interface{}) @@ -179,10 +187,10 @@ func parseRules(input []interface{}, curRegion *Region) (*Rules, error) { Groups[groupStr] = numGroups } groupNum := Groups[groupStr] - rules.patterns = append(rules.patterns, &Pattern{groupNum, r}) + rules.patterns = append(rules.patterns, &pattern{groupNum, r}) } case map[interface{}]interface{}: - // Region + // region region, err := parseRegion(group.(string), object, curRegion) if err != nil { return nil, err @@ -197,10 +205,10 @@ func parseRules(input []interface{}, curRegion *Region) (*Rules, error) { return rules, nil } -func parseRegion(group string, regionInfo map[interface{}]interface{}, prevRegion *Region) (*Region, error) { +func parseRegion(group string, regionInfo map[interface{}]interface{}, prevRegion *region) (*region, error) { var err error - region := new(Region) + region := new(region) if _, ok := Groups[group]; !ok { numGroups++ Groups[group] = numGroups