Repository: zyedidia/micro
File: pkg/highlight/parser.go (Go)

Code before:
	if header == nil {
		header, err = MakeHeaderYaml(data)
		if err != nil {
			screen.TermMessage("Error parsing header for syntax file " + f.Name() + ": " + err.Error())
			return nil
		}
	}

	file, err := ParseFile(data)
	if err != nil {
		screen.TermMessage("Error parsing syntax file " + f.Name() + ": " + err.Error())
		return nil
	}

	syndef, err := ParseDef(file, header)
	if err != nil {
		screen.TermMessage("Error parsing syntax file " + f.Name() + ": " + err.Error())
		return nil
	}

	return syndef
}

// FindRealRuntimeFile can be used to find a specific definition in the user's
// custom syntax files
func FindRealRuntimeFile(name string, header *Header) *Def {
	for _, f := range config.ListRealRuntimeFiles(config.RTSyntax) {
		if f.Name() == name {
			syndef := ParseDefFromFile(f, header)
			if syndef == nil {
				continue
			}
			return syndef
		}
	}
	return nil
}

// FindRealRuntimeFile can be used to find a specific definition in the runtime
// files
func FindRuntimeFile(name string, header *Header) *Def {
	for _, f := range config.ListRuntimeFiles(config.RTSyntax) {
		if f.Name() == name {
			syndef := ParseDefFromFile(f, header)
			if syndef == nil {
				continue
			}
			return syndef
		}
	}
	return nil

Review comment (suggestion):
These return a Def, not a RuntimeFile. So, rather something like `FindDefInRealRuntimeFiles()` and `FindDefInRuntimeFiles()`?

OTOH, that's a mouthful... If we move these functions to `internal/buffer/buffer.go` before `UpdateRules()`, as I've suggested, then maybe let them be named `findRuntimeFile()` and `findRealRuntimeFile()` even though they return syntax def, not a file (since it will be clear from the context what are they for)... Or maybe even such way then: let `findRuntimeFile()` and `findRealRuntimeFile()` return both the file itself and the syntax def parsed from it, even though we will ignore the returned file value.

Code after:
	for _, r := range region.rules.regions {
		hasIncludes = hasIncludes || hasIncludesInRegion(r)
	}
	return hasIncludes
}

// GetIncludes returns a list of filetypes that are included by this syntax def
func GetIncludes(d *Def) []string {
	includes := d.rules.includes
	for _, r := range d.rules.regions {
		includes = append(includes, getIncludesInRegion(r)...)
	}
	return includes
}

func getIncludesInRegion(region *region) []string {
	includes := region.rules.includes
	for _, r := range region.rules.regions {
		includes = append(includes, getIncludesInRegion(r)...)
	}
	return includes
}

// ResolveIncludes will sort out the rules for including other filetypes
// You should call this after parsing all the Defs
func ResolveIncludes(def *Def, files []*File) {
	resolveIncludesInDef(files, def)
}

func resolveIncludesInDef(files []*File, d *Def) {
	for _, lang := range d.rules.includes {
		for _, searchFile := range files {
			if lang == searchFile.FileType {
				searchDef, _ := ParseDef(searchFile, nil)
				d.rules.patterns = append(d.rules.patterns, searchDef.rules.patterns...)
				d.rules.regions = append(d.rules.regions, searchDef.rules.regions...)
			}
		}
	}
	for _, r := range d.rules.regions {
		resolveIncludesInRegion(files, r)
		r.parent = nil
	}
}

func resolveIncludesInRegion(files []*File, region *region) {
	for _, lang := range region.rules.includes {
		for _, searchFile := range files {
			if lang == searchFile.FileType {
				searchDef, _ := ParseDef(searchFile, nil)
				region.rules.patterns = append(region.rules.patterns, searchDef.rules.patterns...)