From 94175d1aa6fdfc11e51cbcc7344828f36e8f4d63 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Mon, 13 Feb 2017 16:11:57 -0500 Subject: [PATCH] Add beginning of cellview as well as improved ViewTypes This is the beginning of the view refactor (#515). It's just the start and is untested for now. --- cmd/micro/cellview.go | 108 ++++++++++++++++++++++++++++++++++++++++++ cmd/micro/view.go | 14 ++++-- 2 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 cmd/micro/cellview.go diff --git a/cmd/micro/cellview.go b/cmd/micro/cellview.go new file mode 100644 index 00000000..097ffea8 --- /dev/null +++ b/cmd/micro/cellview.go @@ -0,0 +1,108 @@ +package main + +import ( + "github.com/mattn/go-runewidth" + "github.com/zyedidia/tcell" +) + +func min(a, b int) int { + if a <= b { + return a + } + return b +} + +func VisualToCharPos(visualIndex int, str string, tabsize int) int { + visualPos := 0 + charPos := 0 + for _, c := range str { + width := StringWidth(string(c), tabsize) + + if visualPos+width > visualIndex { + return charPos + } + + visualPos += width + charPos++ + } + + return 0 +} + +type Char struct { + visualLoc Loc + realLoc Loc + char rune + style tcell.Style +} + +type CellView struct { + lines [][]*Char +} + +func (c *CellView) Draw(buf *Buffer, start, top, height, left, width int) { + tabsize := buf.Settings["tabsize"].(int) + softwrap := buf.Settings["softwrap"].(bool) + indentchar := []rune(buf.Settings["indentchar"].(string))[0] + + if len(c.lines) != height { + c.lines = make([][]*Char, height) + } + + viewLine := 0 + lineN := top + + for viewLine < height { + lineStr := string(buf.lines[lineN]) + line := []rune(lineStr) + + colN := VisualToCharPos(left, lineStr, tabsize) + viewCol := 0 + + // We'll either draw the length of the line, or the width of the screen + // whichever is smaller + lineLength := min(len(line), width) + if len(c.lines[viewLine]) != lineLength { + c.lines[viewLine] = make([]*Char, lineLength) + } + + wrap := false + // We only need to wrap if the length of the line is greater than the width of the terminal screen + if softwrap && len(line) > width { + wrap = true + // We're going to draw the entire line now + lineLength = len(line) + } + + for viewCol < lineLength { + char := line[colN] + + colN++ + if char == '\t' { + c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, indentchar, tcell.StyleDefault} + // TODO: this always adds 4 spaces but it should really add just the remainder to the next tab location + viewCol += tabsize + } else if runewidth.RuneWidth(char) > 1 { + c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, tcell.StyleDefault} + viewCol += runewidth.RuneWidth(char) + } else { + c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, tcell.StyleDefault} + viewCol++ + } + + if wrap && viewCol > width { + viewLine++ + viewCol = 0 + + // If we go too far soft wrapping we have to cut off + if viewLine >= height { + break + } + } + } + + // newline + viewLine++ + lineN++ + } +} diff --git a/cmd/micro/view.go b/cmd/micro/view.go index 1c3b42ba..4b985d9b 100644 --- a/cmd/micro/view.go +++ b/cmd/micro/view.go @@ -11,12 +11,16 @@ import ( "github.com/zyedidia/tcell" ) -type ViewType int +type ViewType struct { + readonly bool // The file cannot be edited + scratch bool // The file cannot be saved +} -const ( - vtDefault ViewType = iota - vtHelp - vtLog +var ( + vtDefault = ViewType{false, false} + vtHelp = ViewType{true, true} + vtLog = ViewType{true, true} + vtScratch = ViewType{false, true} ) // The View struct stores information about a view into a buffer.