]> git.lizzy.rs Git - micro.git/commitdiff
Proper support for double width characters
authorZachary Yedidia <zyedidia@gmail.com>
Sat, 4 Jun 2016 20:25:11 +0000 (16:25 -0400)
committerZachary Yedidia <zyedidia@gmail.com>
Sat, 4 Jun 2016 20:25:11 +0000 (16:25 -0400)
Fixes #99

cmd/micro/cursor.go
cmd/micro/util.go
cmd/micro/view.go

index a2ca8b446e1e74d2180d56a2ed4b6e35c0ab6ea7..19f36dfc087668ad0c48b4a697e4649793885191 100644 (file)
@@ -1,9 +1,5 @@
 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)
@@ -357,13 +353,13 @@ func (c *Cursor) GetCharPosInLine(lineNum, visualPos int) int {
        // 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
 }
@@ -371,8 +367,7 @@ func (c *Cursor) GetCharPosInLine(lineNum, visualPos int) int {
 // 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
index 02dacf38a68e5d29ca749a0f4591401926a29cb4..46da66da2918fd51a984bebc556fef36043313c6 100644 (file)
@@ -7,6 +7,8 @@ import (
        "strings"
        "time"
        "unicode/utf8"
+
+       "github.com/mattn/go-runewidth"
 )
 
 // Util.go is a collection of utility functions that are used throughout
@@ -138,6 +140,28 @@ func GetModTime(path string) (time.Time, bool) {
        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])
 }
index cd2fc3248e3683a38149177a8fc5094f9abcf714..0940acc98cb8156b1dfac7bbda683cb79a616abd 100644 (file)
@@ -7,6 +7,7 @@ import (
        "strings"
        "time"
 
+       "github.com/mattn/go-runewidth"
        "github.com/zyedidia/tcell"
 )
 
@@ -601,6 +602,16 @@ func (v *View) DisplayView() {
                                                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)