From bc724bf781ef8cb225003b390ce07ea3857312dd Mon Sep 17 00:00:00 2001 From: boombuler Date: Wed, 28 Sep 2016 21:54:34 +0200 Subject: [PATCH] fixes #379 (second try) --- cmd/micro/util.go | 22 ++++++++++++++++++++-- cmd/micro/util_test.go | 38 ++++++++++++++++++++++++++++++++++++++ cmd/micro/view.go | 4 +++- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/cmd/micro/util.go b/cmd/micro/util.go index 4402a22e..1577866d 100644 --- a/cmd/micro/util.go +++ b/cmd/micro/util.go @@ -157,7 +157,19 @@ func GetModTime(path string) (time.Time, bool) { // StringWidth returns the width of a string where tabs count as `tabsize` width func StringWidth(str string, tabsize int) int { sw := runewidth.StringWidth(str) - sw += NumOccurrences(str, '\t') * (tabsize - 1) + lineIdx := 0 + for _, ch := range str { + switch ch { + case '\t': + ts := tabsize - (lineIdx % tabsize) + sw += ts - 1 + lineIdx += ts + case '\n': + lineIdx = 0 + default: + lineIdx++ + } + } return sw } @@ -165,16 +177,22 @@ func StringWidth(str string, tabsize int) int { // that have a width larger than 1 (this also counts tabs as `tabsize` width) func WidthOfLargeRunes(str string, tabsize int) int { count := 0 + lineIdx := 0 for _, ch := range str { var w int if ch == '\t' { - w = tabsize + w = tabsize - (lineIdx % tabsize) } else { w = runewidth.RuneWidth(ch) } if w > 1 { count += (w - 1) } + if ch == '\n' { + lineIdx = 0 + } else { + lineIdx += w + } } return count } diff --git a/cmd/micro/util_test.go b/cmd/micro/util_test.go index 16e46fe4..0104218e 100644 --- a/cmd/micro/util_test.go +++ b/cmd/micro/util_test.go @@ -116,3 +116,41 @@ func TestJoinAndSplitCommandArgs(t *testing.T) { } } } + +func TestStringWidth(t *testing.T) { + tabsize := 4 + if w := StringWidth("1\t2", tabsize); w != 5 { + t.Error("StringWidth 1 Failed. Got", w) + } + if w := StringWidth("\t", tabsize); w != 4 { + t.Error("StringWidth 2 Failed. Got", w) + } + if w := StringWidth("1\t", tabsize); w != 4 { + t.Error("StringWidth 3 Failed. Got", w) + } + if w := StringWidth("\t\t", tabsize); w != 8 { + t.Error("StringWidth 4 Failed. Got", w) + } + if w := StringWidth("12\t2\t", tabsize); w != 8 { + t.Error("StringWidth 5 Failed. Got", w) + } +} + +func TestWidthOfLargeRunes(t *testing.T) { + tabsize := 4 + if w := WidthOfLargeRunes("1\t2", tabsize); w != 2 { + t.Error("WidthOfLargeRunes 1 Failed. Got", w) + } + if w := WidthOfLargeRunes("\t", tabsize); w != 3 { + t.Error("WidthOfLargeRunes 2 Failed. Got", w) + } + if w := WidthOfLargeRunes("1\t", tabsize); w != 2 { + t.Error("WidthOfLargeRunes 3 Failed. Got", w) + } + if w := WidthOfLargeRunes("\t\t", tabsize); w != 6 { + t.Error("WidthOfLargeRunes 4 Failed. Got", w) + } + if w := WidthOfLargeRunes("12\t2\t", tabsize); w != 3 { + t.Error("WidthOfLargeRunes 5 Failed. Got", w) + } +} diff --git a/cmd/micro/view.go b/cmd/micro/view.go index aef1ccea..43b38f25 100644 --- a/cmd/micro/view.go +++ b/cmd/micro/view.go @@ -777,7 +777,9 @@ func (v *View) DisplayView() { } // Now the tab has to be displayed as a bunch of spaces tabSize := int(v.Buf.Settings["tabsize"].(float64)) - for i := 0; i < tabSize-1; i++ { + visLoc := StringWidth(line[:colN], tabSize) + remainder := tabSize - (visLoc % tabSize) + for i := 0; i < remainder-1; i++ { screenX++ if screenX-v.x-v.leftCol >= v.lineNumOffset { v.drawCell(screenX-v.leftCol, screenY, ' ', nil, lineStyle)