Better syntax file loading, load files from ~/.micro by default

This commit is contained in:
Zachary Yedidia
2016-03-20 16:27:02 -04:00
parent 6a27593800
commit 4b286bf293
5 changed files with 72 additions and 12 deletions

View File

@@ -25,6 +25,11 @@ type Buffer struct {
// These variables are updated in the update() function
text string
lines []string
// Syntax highlighting rules
rules string
// File type of the buffer
filetype string
}
// NewBuffer creates a new buffer from `txt` with path and name `path`
@@ -35,6 +40,8 @@ func NewBuffer(txt, path string) *Buffer {
b.name = path
b.savedText = txt
b.rules, b.filetype = GetRules(path)
b.Update()
return b

View File

@@ -1,36 +1,81 @@
package main
import (
"fmt"
"github.com/gdamore/tcell"
"io/ioutil"
"os/user"
"path/filepath"
"regexp"
"strings"
)
var syntaxRules string
var syntaxFiles map[*regexp.Regexp][2]string
func GetRules() string {
file, err := ioutil.ReadFile("syntax.micro")
if err != nil {
return ""
}
return string(file)
func LoadSyntaxFiles() {
usr, _ := user.Current()
dir := usr.HomeDir
LoadSyntaxFilesFromDir(dir + "/.micro")
}
// Match ...
func Match(str string) map[int]tcell.Style {
rules := strings.TrimSpace(GetRules())
func LoadSyntaxFilesFromDir(dir string) {
syntaxFiles = make(map[*regexp.Regexp][2]string)
files, _ := ioutil.ReadDir(dir)
for _, f := range files {
if filepath.Ext(f.Name()) == ".micro" {
text, err := ioutil.ReadFile(dir + "/" + f.Name())
if err != nil {
fmt.Println("Error loading syntax files:", err)
continue
}
lines := strings.Split(string(text), "\n")
parser, _ := regexp.Compile(`syntax "(.*?)"\s+"(.*)"`)
matches := parser.FindSubmatch([]byte(lines[0]))
fileExtRegex, err := regexp.Compile(string(matches[2]))
if err != nil {
// Error with the regex!
continue
}
syntaxFiles[fileExtRegex] = [2]string{string(text), string(matches[1])}
}
}
}
// GetRules finds the syntax rules that should be used for the buffer
// and returns them. It also returns the filetype of the file
func GetRules(filename string) (string, string) {
for r := range syntaxFiles {
if r.MatchString(filename) {
return syntaxFiles[r][0], syntaxFiles[r][1]
}
}
return "", "Unknown"
}
// Match takes a buffer and returns a map specifying how it should be syntax highlighted
// The map is from character numbers to styles, so map[3] represents the style change
// at the third character in the buffer
func Match(rules string, buf *Buffer) map[int]tcell.Style {
// rules := strings.TrimSpace(GetRules(buf))
str := buf.text
lines := strings.Split(rules, "\n")
m := make(map[int]tcell.Style)
parser, _ := regexp.Compile(`color (.*?)\s+"(.*)"`)
for _, line := range lines {
if strings.TrimSpace(line) == "" || strings.TrimSpace(line)[0] == '#' || strings.HasPrefix(line, "syntax") {
// Ignore this line
continue
}
submatch := parser.FindSubmatch([]byte(line))
color := string(submatch[1])
regex, err := regexp.Compile(string(submatch[2]))
if err != nil {
continue
// Error with the regex!
continue
}
st := StringToStyle(color)

View File

@@ -37,6 +37,8 @@ func main() {
input = bytes
}
LoadSyntaxFiles()
s, e := tcell.NewScreen()
if e != nil {
fmt.Fprintf(os.Stderr, "%v\n", e)

View File

@@ -23,12 +23,16 @@ func (sl *Statusline) Display() {
file += " +"
}
file += " (" + strconv.Itoa(sl.v.cursor.y+1) + "," + strconv.Itoa(sl.v.cursor.GetVisualX()+1) + ")"
filetype := sl.v.buf.filetype
file += " " + filetype
statusLineStyle := tcell.StyleDefault.Reverse(true)
for x := 0; x < sl.v.width; x++ {
if x < Count(file) {
sl.v.s.SetContent(x, y, []rune(file)[x], nil, statusLineStyle)
// } else if x > sl.v.width-Count(filetype)-1 {
// sl.v.s.SetContent(x, y, []rune(filetype)[Count(filetype)-(sl.v.width-1-x)-1], nil, statusLineStyle)
} else {
sl.v.s.SetContent(x, y, ' ', nil, statusLineStyle)
}

View File

@@ -39,6 +39,8 @@ func NewViewWidthHeight(buf *Buffer, s tcell.Screen, w, h int) *View {
v.buf = buf
v.s = s
v.buf.rules, v.buf.filetype = GetRules(v.buf.path)
v.topline = 0
v.height = h - 1
v.width = w
@@ -301,7 +303,7 @@ func (v *View) Display() {
charNum := v.cursor.loc + v.cursor.Distance(0, v.topline)
matches := Match(v.buf.text)
matches := Match(v.buf.rules, v.buf)
// Convert the length of buffer to a string, and get the length of the string
// We are going to have to offset by that amount