From 04b4dbbfee119c7dd00cc6230e6d7f2155146576 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Wed, 22 Mar 2017 11:58:43 -0400 Subject: [PATCH] Improve performance on long lines --- cmd/micro/cellview.go | 22 ++++++++++++++++++---- cmd/micro/view.go | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/cmd/micro/cellview.go b/cmd/micro/cellview.go index 6d38e8bf..a7dbff12 100644 --- a/cmd/micro/cellview.go +++ b/cmd/micro/cellview.go @@ -15,10 +15,13 @@ 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(highlight.GetGroup(group)) @@ -31,8 +34,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 @@ -53,7 +65,7 @@ type CellView struct { lines [][]*Char } -func (c *CellView) Draw(buf *Buffer, top, height, left, width int) { +func (c *CellView) Draw(buf *Buffer, scrollInfo []*scrollInfo, top, height, left, width int) { tabsize := int(buf.Settings["tabsize"].(float64)) softwrap := buf.Settings["softwrap"].(bool) indentchar := []rune(buf.Settings["indentchar"].(string))[0] @@ -84,7 +96,9 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) { lineStr := buf.Line(lineN) line := []rune(lineStr) - colN, startOffset, startStyle := visualToCharPos(left, lineN, lineStr, buf, tabsize) + // colN, startOffset, startStyle := visualToCharPos(left, lineN, lineStr, buf, tabsize) + info := scrollInfo[lineN-top] + colN, startOffset, startStyle := info.left, info.offset, info.style if colN < 0 { colN = len(line) } diff --git a/cmd/micro/view.go b/cmd/micro/view.go index 52f975ca..722f42b0 100644 --- a/cmd/micro/view.go +++ b/cmd/micro/view.go @@ -22,6 +22,12 @@ var ( vtScratch = ViewType{false, true} ) +type scrollInfo struct { + left int + offset int + style *tcell.Style +} + // The View struct stores information about a view into a buffer. // It stores information about the cursor, and the viewport // that the user sees the buffer from. @@ -32,7 +38,8 @@ type View struct { // The topmost line, used for vertical scrolling Topline int // The leftmost column, used for horizontal scrolling - leftCol int + leftCol int + hScrollInfo []*scrollInfo // Specifies whether or not this view holds a help buffer Type ViewType @@ -159,6 +166,23 @@ func (v *View) ToggleTabbar() { } } +func (v *View) calcHScrollInfo() { + v.hScrollInfo = make([]*scrollInfo, v.Height) + for i := v.Topline; i < v.Topline+v.Height; i++ { + if i >= v.Buf.NumLines { + break + } + + left, offset, style := visualToCharPos(v.leftCol, i, v.Buf.Line(i), v.Buf, int(v.Buf.Settings["tabsize"].(float64))) + v.hScrollInfo[i-v.Topline] = &scrollInfo{left, offset, style} + } +} + +func (v *View) SetLeftCol(n int) { + v.leftCol = n + v.calcHScrollInfo() +} + func (v *View) paste(clip string) { leadingWS := GetLeadingWhitespace(v.Buf.Line(v.Cursor.Y)) @@ -227,7 +251,8 @@ func (v *View) OpenBuffer(buf *Buffer) { v.Buf = buf v.Cursor = &buf.Cursor v.Topline = 0 - v.leftCol = 0 + // v.leftCol = 0 + v.SetLeftCol(0) v.Cursor.ResetSelection() v.Relocate() v.Center(false) @@ -406,11 +431,13 @@ func (v *View) Relocate() bool { if !v.Buf.Settings["softwrap"].(bool) { cx := v.Cursor.GetVisualX() if cx < v.leftCol { - v.leftCol = cx + // v.leftCol = cx + v.SetLeftCol(cx) ret = true } if cx+v.lineNumOffset+1 > v.leftCol+v.Width { - v.leftCol = cx - v.Width + v.lineNumOffset + 1 + // v.leftCol = cx - v.Width + v.lineNumOffset + 1 + v.SetLeftCol(cx - v.Width + v.lineNumOffset + 1) ret = true } } @@ -688,7 +715,7 @@ func (v *View) DisplayView() { left := v.leftCol top := v.Topline - v.cellview.Draw(v.Buf, top, height, left, width-v.lineNumOffset) + v.cellview.Draw(v.Buf, v.hScrollInfo, top, height, left, width-v.lineNumOffset) screenX := v.x realLineN := top - 1