X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fcellview.go;h=b0cb6523c3602312b9ba8470d7cae65e83e12ed6;hb=d9735e5c3be7218392f2c3b4cd315d8f6d4834d6;hp=5d03ade37bc3b2cae166761179509a0ec992005a;hpb=d0057121ef8d654577af9dab0205fd3b32711c23;p=micro.git diff --git a/cmd/micro/cellview.go b/cmd/micro/cellview.go index 5d03ade3..b0cb6523 100644 --- a/cmd/micro/cellview.go +++ b/cmd/micro/cellview.go @@ -1,8 +1,6 @@ package main import ( - "time" - "github.com/mattn/go-runewidth" "github.com/zyedidia/tcell" ) @@ -14,28 +12,52 @@ func min(a, b int) int { return b } -func VisualToCharPos(visualIndex int, str string, tabsize int) int { - visualPos := 0 +func visualToCharPos(visualIndex int, lineN int, str string, buf *Buffer, tabsize int) (int, int, *tcell.Style) { charPos := 0 - for _, c := range str { - width := StringWidth(string(c), tabsize) + var lineIdx int + var lastWidth int + var style *tcell.Style + 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.String()) + style = &s + } - if visualPos+width > visualIndex { - return charPos + if width >= visualIndex { + return charPos, visualIndex - lastWidth, style } - visualPos += width - charPos++ + 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 0 + return -1, -1, style } type Char struct { visualLoc Loc realLoc Loc char rune - style tcell.Style + // The actual character that is drawn + // This is only different from char if it's for example hidden character + drawChar rune + style tcell.Style + width int } type CellView struct { @@ -43,18 +65,50 @@ 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 { + curX := buf.Cursor.X + curLoc := buf.Cursor.Loc + if buf.Settings["matchbraceleft"].(bool) { + if curX > 0 { + curX-- + curLoc = curLoc.Move(-1, buf) + } + } + + r := buf.Cursor.RuneUnder(curX) + if r == bp[0] || r == bp[1] { + matchingBrace = buf.FindMatchingBrace(bp, curLoc) + } + } + } + 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 - startTime := time.Now() - matches := buf.highlighter.ReHighlight(buf, start) - elapsed := time.Since(startTime) - for i, m := range matches { - buf.matches[start+i] = m + 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.ReHighlightStates(buf, start) + + buf.highlighter.HighlightMatches(buf, top, top+height) } - messenger.Message("Rehighlighted ", len(matches), " lines in ", elapsed) c.lines = make([][]*Char, 0) @@ -70,8 +124,14 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) { lineStr := buf.Line(lineN) line := []rune(lineStr) - colN := VisualToCharPos(left, lineStr, tabsize) - viewCol := 0 + colN, startOffset, startStyle := visualToCharPos(left, lineN, lineStr, buf, tabsize) + if colN < 0 { + colN = len(line) + } + viewCol := -startOffset + if startStyle != nil { + curStyle = *startStyle + } // We'll either draw the length of the line, or the width of the screen // whichever is smaller @@ -90,21 +150,56 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) { if colN >= len(line) { break } - if group, ok := buf.matches[lineN][colN]; ok { - curStyle = GetColor(group) + if group, ok := buf.Match(lineN)[colN]; ok { + curStyle = GetColor(group.String()) } char := line[colN] + if viewCol >= 0 { + 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' { - c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, indentchar, curStyle} - // TODO: this always adds 4 spaces but it should really add just the remainder to the next tab location - viewCol += tabsize + charWidth := tabsize - (viewCol+left)%tabsize + if viewCol >= 0 { + c.lines[viewLine][viewCol].drawChar = indentchar + 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 + } + + 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 { - c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, curStyle} - 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 { - c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, curStyle} viewCol++ } colN++ @@ -125,12 +220,19 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) { } } - if group, ok := buf.matches[lineN][len(line)]; ok { - curStyle = GetColor(group) + if group, ok := buf.Match(lineN)[len(line)]; ok { + curStyle = GetColor(group.String()) } // newline viewLine++ lineN++ } + + for i := top; i < top+height; i++ { + if i >= buf.NumLines { + break + } + buf.SetMatch(i, nil) + } }