]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/cellview.go
allow optionally brace matching with the closing brace to the left of the cursor
[micro.git] / cmd / micro / cellview.go
index b4874ee591eac3fea2aae55dd132242b0e2bfba2..9c50856e4ab50ac5eefee8ba12c18395d02429d6 100644 (file)
@@ -14,13 +14,16 @@ func min(a, b int) int {
 
 func visualToCharPos(visualIndex int, lineN int, str string, buf *Buffer, tabsize int) (int, int, *tcell.Style) {
        charPos := 0
+       var lineIdx int
        var lastWidth int
        var style *tcell.Style
-       for i := range str {
-               width := StringWidth(str[:i], tabsize)
+       var width int
+       var rw int
+       for i, c := range str {
+               // width := StringWidth(str[:i], tabsize)
 
                if group, ok := buf.Match(lineN)[charPos]; ok {
-                       s := GetColor(group)
+                       s := GetColor(group.String())
                        style = &s
                }
 
@@ -30,8 +33,17 @@ func visualToCharPos(visualIndex int, lineN int, str string, buf *Buffer, tabsiz
 
                if i != 0 {
                        charPos++
+                       lineIdx += rw
                }
                lastWidth = width
+               rw = 0
+               if c == '\t' {
+                       rw = tabsize - (lineIdx % tabsize)
+                       width += rw
+               } else {
+                       rw = runewidth.RuneWidth(c)
+                       width += rw
+               }
        }
 
        return -1, -1, style
@@ -45,6 +57,7 @@ type Char struct {
        // This is only different from char if it's for example hidden character
        drawChar rune
        style    tcell.Style
+       width    int
 }
 
 type CellView struct {
@@ -52,18 +65,51 @@ type CellView struct {
 }
 
 func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
+       if width <= 0 {
+               return
+       }
+
+       matchingBrace := Loc{-1, -1}
+       // bracePairs is defined in buffer.go
+       if buf.Settings["matchbrace"].(bool) {
+               for _, bp := range bracePairs {
+                       if buf.Cursor.RuneUnder(buf.Cursor.X) == bp[0] {
+                               matchingBrace = buf.FindMatchingBrace(bp, buf.Cursor.Loc)
+                               break
+                       }
+                       left := buf.Cursor.Loc.X
+                       if buf.Settings["matchbraceleft"].(bool) {
+                               left -= 1
+                               if left < 0 {
+                                       left = 0
+                               }
+                       }
+                       if buf.Cursor.RuneUnder(left) == bp[1] {
+                               matchingBrace = buf.FindMatchingBrace(
+                                       bp, Loc{X: left, Y: buf.Cursor.Loc.Y})
+                       }
+               }
+       }
+
        tabsize := int(buf.Settings["tabsize"].(float64))
        softwrap := buf.Settings["softwrap"].(bool)
-       indentchar := []rune(buf.Settings["indentchar"].(string))[0]
+       indentrunes := []rune(buf.Settings["indentchar"].(string))
+       // if empty indentchar settings, use space
+       if indentrunes == nil || len(indentrunes) == 0 {
+               indentrunes = []rune{' '}
+       }
+       indentchar := indentrunes[0]
 
        start := buf.Cursor.Y
-       if buf.Settings["syntax"].(bool) {
+       if buf.Settings["syntax"].(bool) && buf.syntaxDef != nil {
                if start > 0 && buf.lines[start-1].rehighlight {
                        buf.highlighter.ReHighlightLine(buf, start-1)
                        buf.lines[start-1].rehighlight = false
                }
 
-               buf.highlighter.ReHighlight(buf, start)
+               buf.highlighter.ReHighlightStates(buf, start)
+
+               buf.highlighter.HighlightMatches(buf, top, top+height)
        }
 
        c.lines = make([][]*Char, 0)
@@ -107,24 +153,54 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
                                break
                        }
                        if group, ok := buf.Match(lineN)[colN]; ok {
-                               curStyle = GetColor(group)
+                               curStyle = GetColor(group.String())
                        }
 
                        char := line[colN]
 
                        if viewCol >= 0 {
-                               c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, char, curStyle}
+                               st := curStyle
+                               if colN == matchingBrace.X && lineN == matchingBrace.Y && !buf.Cursor.HasSelection() {
+                                       st = curStyle.Reverse(true)
+                               }
+                               if viewCol < len(c.lines[viewLine]) {
+                                       c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, char, st, 1}
+                               }
                        }
                        if char == '\t' {
+                               charWidth := tabsize - (viewCol+left)%tabsize
                                if viewCol >= 0 {
                                        c.lines[viewLine][viewCol].drawChar = indentchar
-                                       viewCol += tabsize - viewCol%tabsize
-                               } else {
-                                       viewCol += tabsize
+                                       c.lines[viewLine][viewCol].width = charWidth
+
+                                       indentStyle := curStyle
+                                       ch := buf.Settings["indentchar"].(string)
+                                       if group, ok := colorscheme["indent-char"]; ok && !IsStrWhitespace(ch) && ch != "" {
+                                               indentStyle = group
+                                       }
+
+                                       c.lines[viewLine][viewCol].style = indentStyle
                                }
-                               // viewCol += tabsize
+
+                               for i := 1; i < charWidth; i++ {
+                                       viewCol++
+                                       if viewCol >= 0 && viewCol < lineLength && viewCol < len(c.lines[viewLine]) {
+                                               c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
+                                       }
+                               }
+                               viewCol++
                        } else if runewidth.RuneWidth(char) > 1 {
-                               viewCol += runewidth.RuneWidth(char)
+                               charWidth := runewidth.RuneWidth(char)
+                               if viewCol >= 0 {
+                                       c.lines[viewLine][viewCol].width = charWidth
+                               }
+                               for i := 1; i < charWidth; i++ {
+                                       viewCol++
+                                       if viewCol >= 0 && viewCol < lineLength && viewCol < len(c.lines[viewLine]) {
+                                               c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
+                                       }
+                               }
+                               viewCol++
                        } else {
                                viewCol++
                        }
@@ -147,11 +223,18 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
 
                }
                if group, ok := buf.Match(lineN)[len(line)]; ok {
-                       curStyle = GetColor(group)
+                       curStyle = GetColor(group.String())
                }
 
                // newline
                viewLine++
                lineN++
        }
+
+       for i := top; i < top+height; i++ {
+               if i >= buf.NumLines {
+                       break
+               }
+               buf.SetMatch(i, nil)
+       }
 }