package main
-import (
- "strings"
-)
-
// FromCharPos converts from a character position to an x, y position
func FromCharPos(loc int, buf *Buffer) (int, int) {
return FromCharPosStart(0, 0, 0, loc, buf)
// Get the tab size
tabSize := int(settings["tabsize"].(float64))
// This is the visual line -- every \t replaced with the correct number of spaces
- visualLine := strings.Replace(c.buf.Lines[lineNum], "\t", "\t"+Spaces(tabSize-1), -1)
- if visualPos > Count(visualLine) {
- visualPos = Count(visualLine)
+ visualLineLen := StringWidth(c.buf.Lines[lineNum])
+ if visualPos > visualLineLen {
+ visualPos = visualLineLen
}
- numTabs := NumOccurences(visualLine[:visualPos], '\t')
- if visualPos >= (tabSize-1)*numTabs {
- return visualPos - (tabSize-1)*numTabs
+ width := WidthOfLargeRunes(c.buf.Lines[lineNum])
+ if visualPos >= width {
+ return visualPos - width
}
return visualPos / tabSize
}
// GetVisualX returns the x value of the cursor in visual spaces
func (c *Cursor) GetVisualX() int {
runes := []rune(c.buf.Lines[c.Y])
- tabSize := int(settings["tabsize"].(float64))
- return c.X + NumOccurences(string(runes[:c.X]), '\t')*(tabSize-1)
+ return StringWidth(string(runes[:c.X]))
}
// Relocate makes sure that the cursor is inside the bounds of the buffer
"strings"
"time"
"unicode/utf8"
+
+ "github.com/mattn/go-runewidth"
)
// Util.go is a collection of utility functions that are used throughout
return info.ModTime(), true
}
+func StringWidth(str string) int {
+ sw := runewidth.StringWidth(str)
+ sw += NumOccurences(str, '\t') * (int(settings["tabsize"].(float64)) - 1)
+ return sw
+}
+
+func WidthOfLargeRunes(str string) int {
+ count := 0
+ for _, ch := range str {
+ var w int
+ if ch == '\t' {
+ w = int(settings["tabsize"].(float64))
+ } else {
+ w = runewidth.RuneWidth(ch)
+ }
+ if w > 1 {
+ count += (w - 1)
+ }
+ }
+ return count
+}
+
func runePos(p int, str string) int {
return utf8.RuneCountInString(str[:p])
}
"strings"
"time"
+ "github.com/mattn/go-runewidth"
"github.com/zyedidia/tcell"
)
screen.SetContent(x-v.leftCol, lineN, ' ', nil, lineStyle)
}
}
+ } else if runewidth.RuneWidth(ch) > 1 {
+ if x-v.leftCol >= v.lineNumOffset {
+ screen.SetContent(x-v.leftCol, lineN, ch, nil, lineStyle)
+ }
+ for i := 0; i < runewidth.RuneWidth(ch)-1; i++ {
+ x++
+ if x-v.leftCol >= v.lineNumOffset {
+ screen.SetContent(x-v.leftCol, lineN, ' ', nil, lineStyle)
+ }
+ }
} else {
if x-v.leftCol >= v.lineNumOffset {
screen.SetContent(x-v.leftCol, lineN, ch, nil, lineStyle)