summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/jesseduffield/gocui/edit.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/jesseduffield/gocui/edit.go')
-rw-r--r--vendor/github.com/jesseduffield/gocui/edit.go111
1 files changed, 83 insertions, 28 deletions
diff --git a/vendor/github.com/jesseduffield/gocui/edit.go b/vendor/github.com/jesseduffield/gocui/edit.go
index e1b19c20b..a5e6f690b 100644
--- a/vendor/github.com/jesseduffield/gocui/edit.go
+++ b/vendor/github.com/jesseduffield/gocui/edit.go
@@ -4,7 +4,11 @@
package gocui
-import "errors"
+import (
+ "errors"
+
+ "github.com/mattn/go-runewidth"
+)
const maxInt = int(^uint(0) >> 1)
@@ -54,8 +58,9 @@ func simpleEditor(v *View, key Key, ch rune, mod Modifier) {
// EditWrite writes a rune at the cursor position.
func (v *View) EditWrite(ch rune) {
+ w := runewidth.RuneWidth(ch)
v.writeRune(v.cx, v.cy, ch)
- v.MoveCursor(1, 0, true)
+ v.moveCursor(w, 0, true)
}
// EditDelete deletes a rune at the cursor position. back determines the
@@ -89,12 +94,12 @@ func (v *View) EditDelete(back bool) {
v.MoveCursor(-1, 0, true)
}
} else { // wrapped line
- v.deleteRune(len(v.viewLines[y-1].line)-1, v.cy-1)
- v.MoveCursor(-1, 0, true)
+ n, _ := v.deleteRune(len(v.viewLines[y-1].line)-1, v.cy-1)
+ v.MoveCursor(-n, 0, true)
}
} else { // middle/end of the line
- v.deleteRune(v.cx-1, v.cy)
- v.MoveCursor(-1, 0, true)
+ n, _ := v.deleteRune(v.cx-1, v.cy)
+ v.MoveCursor(-n, 0, true)
}
} else {
if x == len(v.viewLines[y].line) { // end of the line
@@ -116,35 +121,74 @@ func (v *View) EditNewLine() {
// MoveCursor moves the cursor taking into account the width of the line/view,
// displacing the origin if necessary.
func (v *View) MoveCursor(dx, dy int, writeMode bool) {
+ ox, oy := v.cx+v.ox, v.cy+v.oy
+ x, y := ox+dx, oy+dy
+
+ if y < 0 || y >= len(v.viewLines) {
+ v.moveCursor(dx, dy, writeMode)
+ return
+ }
+
+ // Removing newline.
+ if x < 0 {
+ var prevLen int
+ if y-1 >= 0 && y-1 < len(v.viewLines) {
+ prevLen = lineWidth(v.viewLines[y-1].line)
+ }
+
+ v.MoveCursor(prevLen, -1, writeMode)
+ return
+ }
+
+ line := v.viewLines[y].line
+ var col int
+ var prevCol int
+ for i := range line {
+ prevCol = col
+ col += runewidth.RuneWidth(line[i].chr)
+ if dx > 0 {
+ if x <= col {
+ x = col
+ break
+ }
+ continue
+ }
+
+ if x < col {
+ x = prevCol
+ break
+ }
+ }
+
+ v.moveCursor(x-ox, y-oy, writeMode)
+}
+
+func (v *View) moveCursor(dx, dy int, writeMode bool) {
maxX, maxY := v.Size()
cx, cy := v.cx+dx, v.cy+dy
x, y := v.ox+cx, v.oy+cy
var curLineWidth, prevLineWidth int
// get the width of the current line
- if writeMode {
- if v.Wrap {
- curLineWidth = maxX - 1
- } else {
- curLineWidth = maxInt
- }
- } else {
+ curLineWidth = maxInt
+ if v.Wrap {
+ curLineWidth = maxX - 1
+ }
+
+ if !writeMode {
+ curLineWidth = 0
if y >= 0 && y < len(v.viewLines) {
- curLineWidth = len(v.viewLines[y].line)
+ curLineWidth = lineWidth(v.viewLines[y].line)
if v.Wrap && curLineWidth >= maxX {
curLineWidth = maxX - 1
}
- } else {
- curLineWidth = 0
}
}
// get the width of the previous line
+ prevLineWidth = 0
if y-1 >= 0 && y-1 < len(v.viewLines) {
- prevLineWidth = len(v.viewLines[y-1].line)
- } else {
- prevLineWidth = 0
+ prevLineWidth = lineWidth(v.viewLines[y-1].line)
}
-
// adjust cursor's x position and view's x origin
if x > curLineWidth { // move to next line
if dx > 0 { // horizontal movement
@@ -190,10 +234,9 @@ func (v *View) MoveCursor(dx, dy int, writeMode bool) {
if !v.Wrap { // set origin so the EOL is visible
nox := prevLineWidth - maxX + 1
if nox < 0 {
- v.ox = 0
- } else {
- v.ox = nox
+ nox = 0
}
+ v.ox = nox
}
v.cx = prevLineWidth
} else {
@@ -275,19 +318,31 @@ func (v *View) writeRune(x, y int, ch rune) error {
// deleteRune removes a rune from the view's internal buffer, at the
// position corresponding to the point (x, y).
-func (v *View) deleteRune(x, y int) error {
+// returns the amount of columns that where removed.
+func (v *View) deleteRune(x, y int) (int, error) {
v.tainted = true
x, y, err := v.realPosition(x, y)
if err != nil {
- return err
+ return 0, err
}
if x < 0 || y < 0 || y >= len(v.lines) || x >= len(v.lines[y]) {
- return errors.New("invalid point")
+ return 0, errors.New("invalid point")
}
- v.lines[y] = append(v.lines[y][:x], v.lines[y][x+1:]...)
- return nil
+
+ var tw int
+ for i := range v.lines[y] {
+ w := runewidth.RuneWidth(v.lines[y][i].chr)
+ tw += w
+ if tw > x {
+ v.lines[y] = append(v.lines[y][:i], v.lines[y][i+1:]...)
+ return w, nil
+ }
+
+ }
+
+ return 0, nil
}
// mergeLines merges the lines "y" and "y+1" if possible.