diff --git a/highlighter.go b/highlighter.go new file mode 100644 index 00000000..003c7bdc --- /dev/null +++ b/highlighter.go @@ -0,0 +1,111 @@ +package main + +import ( + "fmt" + "github.com/gdamore/tcell" + "regexp" + "strings" +) + +// Match ... +func Match(str string) map[int]tcell.Style { + rules := `color blue "[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[()]" +color blue "\b(append|cap|close|complex|copy|delete|imag|len)\b" +color blue "\b(make|new|panic|print|println|protect|real|recover)\b" +color green "\b(u?int(8|16|32|64)?|float(32|64)|complex(64|128))\b" +color green "\b(uintptr|byte|rune|string|interface|bool|map|chan|error)\b" +color cyan "\b(package|import|const|var|type|struct|func|go|defer|nil|iota)\b" +color cyan "\b(for|range|if|else|case|default|switch|return)\b" +color red "\b(go|goto|break|continue)\b" +color cyan "\b(true|false)\b" +color red "[-+/*=<>!~%&|^]|:=" +color blue "\b([0-9]+|0x[0-9a-fA-F]*)\b|'.'" +color magenta "\\([0-7]{3}|x[A-Fa-f0-9]{2}|u[A-Fa-f0-9]{4}|U[A-Fa-f0-9]{8})" +color yellow "` + "`" + `[^` + "`" + `]*` + "`" + `" +color green "(^|[[:space:]])//.*" +color brightwhite,cyan "TODO:?" +color ,green "[[:space:]]+$" +color ,red " + +| + +"` + + lines := strings.Split(rules, "\n") + m := make(map[int]tcell.Style) + for _, line := range lines { + split := strings.Split(line, "\"") + color := strings.Split(split[0], " ")[1] + regex, err := regexp.Compile(split[1]) + if err != nil { + fmt.Println("\a") + // Error with the regex! + } + st := StringToStyle(color) + + if regex.MatchString(str) { + indicies := regex.FindAllStringIndex(str, -1) + for _, value := range indicies { + for i := value[0] + 1; i < value[1]; i++ { + if _, exists := m[i]; exists { + delete(m, i) + } + } + m[value[0]] = st + m[value[1]] = tcell.StyleDefault + } + } + } + + return m +} + +// StringToStyle returns a style from a string +func StringToStyle(str string) tcell.Style { + var fg string + var bg string + split := strings.Split(str, ",") + if len(split) > 1 { + fg, bg = split[0], split[1] + } else { + fg = split[0] + } + + return tcell.StyleDefault.Foreground(StringToColor(fg)).Background(StringToColor(bg)) +} + +// StringToColor returns a tcell color from a string representation of a color +func StringToColor(str string) tcell.Color { + switch str { + case "black": + return tcell.ColorBlack + case "red": + return tcell.ColorMaroon + case "green": + return tcell.ColorGreen + case "yellow": + return tcell.ColorOlive + case "blue": + return tcell.ColorNavy + case "magenta": + return tcell.ColorPurple + case "cyan": + return tcell.ColorTeal + case "white": + return tcell.ColorSilver + case "brightblack": + return tcell.ColorGray + case "brightred": + return tcell.ColorRed + case "brightgreen": + return tcell.ColorLime + case "brightyellow": + return tcell.ColorYellow + case "brightblue": + return tcell.ColorBlue + case "brightmagenta": + return tcell.ColorFuchsia + case "brightcyan": + return tcell.ColorAqua + case "brightwhite": + return tcell.ColorWhite + default: + return tcell.ColorDefault + } +} diff --git a/statusline.go b/statusline.go index 8ca1e1d3..6de3d4c3 100644 --- a/statusline.go +++ b/statusline.go @@ -24,7 +24,7 @@ func (sl *Statusline) Display() { } file += " (" + strconv.Itoa(sl.v.cursor.y+1) + "," + strconv.Itoa(sl.v.cursor.GetVisualX()+1) + ")" - statusLineStyle := tcell.StyleDefault.Background(tcell.ColorNavy).Foreground(tcell.ColorBlack) + statusLineStyle := tcell.StyleDefault.Reverse(true) for x := 0; x < sl.v.width; x++ { if x < Count(file) { diff --git a/todolist.md b/todolist.md index 8019e340..c65fb0c7 100644 --- a/todolist.md +++ b/todolist.md @@ -14,8 +14,8 @@ - [x] Use pageup and pagedown keys - [ ] Much more (copy sublime text or standard system applications) -- [ ] Syntax highlighting - - [ ] Use nano-like syntax files (https://github.com/scopatz/nanorc) +- [x] Syntax highlighting + - [x] Use nano-like syntax files (https://github.com/scopatz/nanorc) - [ ] Colorschemes - [ ] Support for 256 color and true color diff --git a/view.go b/view.go index caa4ec5a..3566b51e 100644 --- a/view.go +++ b/view.go @@ -301,12 +301,16 @@ func (v *View) Display() { charNum := v.cursor.loc + v.cursor.Distance(0, v.topline) + matches := Match(v.buf.text) + // 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 maxLineLength := len(strconv.Itoa(len(v.buf.lines))) // + 1 for the little space after the line number v.lineNumOffset = maxLineLength + 1 + var lineStyle tcell.Style + for lineN := 0; lineN < v.height; lineN++ { if lineN+v.topline >= len(v.buf.lines) { break @@ -333,26 +337,34 @@ func (v *View) Display() { // Write the line tabchars := 0 for _, ch := range line { - st := tcell.StyleDefault + st, ok := matches[charNum] + if ok { + lineStyle = st + } + if v.cursor.HasSelection() && (charNum >= v.cursor.selectionStart && charNum <= v.cursor.selectionEnd || charNum <= v.cursor.selectionStart && charNum >= v.cursor.selectionEnd) { - st = st.Reverse(true) + lineStyle = lineStyle.Reverse(true) } if ch == '\t' { - v.s.SetContent(x+tabchars, lineN, ' ', nil, st) + v.s.SetContent(x+tabchars, lineN, ' ', nil, lineStyle) for i := 0; i < tabSize-1; i++ { tabchars++ - v.s.SetContent(x+tabchars, lineN, ' ', nil, st) + v.s.SetContent(x+tabchars, lineN, ' ', nil, lineStyle) } } else { - v.s.SetContent(x+tabchars, lineN, ch, nil, st) + v.s.SetContent(x+tabchars, lineN, ch, nil, lineStyle) } charNum++ x++ } x = 0 + st, ok := matches[charNum] + if ok { + lineStyle = st + } charNum++ } }