diff --git a/cmd/micro/actions.go b/cmd/micro/actions.go index a9a34aa0..41c89e71 100644 --- a/cmd/micro/actions.go +++ b/cmd/micro/actions.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" "time" + "unicode/utf8" "github.com/yuin/gopher-lua" "github.com/zyedidia/clipboard" @@ -742,9 +743,9 @@ func (v *View) Backspace(usePlugin bool) bool { // If the user is using spaces instead of tabs and they are deleting // whitespace at the start of the line, we should delete as if it's a // tab (tabSize number of spaces) - lineStart := v.Buf.Line(v.Cursor.Y)[:v.Cursor.X] + lineStart := sliceEnd(v.Buf.LineBytes(v.Cursor.Y), v.Cursor.X) tabSize := int(v.Buf.Settings["tabsize"].(float64)) - if v.Buf.Settings["tabstospaces"].(bool) && IsSpaces(lineStart) && len(lineStart) != 0 && len(lineStart)%tabSize == 0 { + if v.Buf.Settings["tabstospaces"].(bool) && IsSpaces(lineStart) && utf8.RuneCount(lineStart) != 0 && utf8.RuneCount(lineStart)%tabSize == 0 { loc := v.Cursor.Loc v.Buf.Remove(loc.Move(-tabSize, v.Buf), loc) } else { diff --git a/cmd/micro/cellview.go b/cmd/micro/cellview.go index 7a6c13cd..c33d2925 100644 --- a/cmd/micro/cellview.go +++ b/cmd/micro/cellview.go @@ -85,7 +85,7 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) { indentrunes := []rune(buf.Settings["indentchar"].(string)) // if empty indentchar settings, use space if indentrunes == nil || len(indentrunes) == 0 { - indentrunes = []rune(" ") + indentrunes = []rune{' '} } indentchar := indentrunes[0] diff --git a/cmd/micro/command.go b/cmd/micro/command.go index ade999cd..ebb79365 100644 --- a/cmd/micro/command.go +++ b/cmd/micro/command.go @@ -176,7 +176,7 @@ func PluginCmd(args []string) { continue } } - if !IsSpaces(removed) { + if !IsSpaces([]byte(removed)) { messenger.Message("Removed ", removed) } else { messenger.Error("The requested plugins do not exist") diff --git a/cmd/micro/lineArray.go b/cmd/micro/lineArray.go index 20fde585..24860378 100644 --- a/cmd/micro/lineArray.go +++ b/cmd/micro/lineArray.go @@ -89,7 +89,6 @@ func NewLineArray(size int64, reader io.Reader) *LineArray { if n >= 1000 && loaded >= 0 { totalLinesNum := int(float64(size) * (float64(n) / float64(loaded))) newSlice := make([]Line, len(la.lines), totalLinesNum+10000) - // The copy function is predeclared and works for any slice type. copy(newSlice, la.lines) la.lines = newSlice loaded = -1 @@ -147,9 +146,9 @@ func (la *LineArray) SaveString(useCrlf bool) string { // NewlineBelow adds a newline below the given line number func (la *LineArray) NewlineBelow(y int) { - la.lines = append(la.lines, Line{[]byte(" "), nil, nil, false}) + la.lines = append(la.lines, Line{[]byte{' '}, nil, nil, false}) copy(la.lines[y+2:], la.lines[y+1:]) - la.lines[y+1] = Line{[]byte(""), la.lines[y].state, nil, false} + la.lines[y+1] = Line{[]byte{}, la.lines[y].state, nil, false} } // inserts a byte array at a given location diff --git a/cmd/micro/util.go b/cmd/micro/util.go index 878ddb25..b8a8e92a 100644 --- a/cmd/micro/util.go +++ b/cmd/micro/util.go @@ -37,6 +37,40 @@ func toRunes(b []byte) []rune { return runes } +func sliceStart(slc []byte, index int) []byte { + len := len(slc) + i := 0 + totalSize := 0 + for totalSize < len { + if i >= index { + return slc[totalSize:] + } + + _, size := utf8.DecodeRune(slc[totalSize:]) + totalSize += size + i++ + } + + return slc[totalSize:] +} + +func sliceEnd(slc []byte, index int) []byte { + len := len(slc) + i := 0 + totalSize := 0 + for totalSize < len { + if i >= index { + return slc[:totalSize] + } + + _, size := utf8.DecodeRune(slc[totalSize:]) + totalSize += size + i++ + } + + return slc[:totalSize] +} + // NumOccurrences counts the number of occurrences of a byte in a string func NumOccurrences(s string, c byte) int { var n int @@ -144,7 +178,7 @@ func GetLeadingWhitespace(str string) string { } // IsSpaces checks if a given string is only spaces -func IsSpaces(str string) bool { +func IsSpaces(str []byte) bool { for _, c := range str { if c != ' ' { return false