Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix how wide runes are displayed #109

Merged
merged 3 commits into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 18 additions & 34 deletions edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ package gocui

import (
"errors"

"github.com/mattn/go-runewidth"
)

// Editor interface must be satisfied by gocui editors.
Expand Down Expand Up @@ -47,13 +45,13 @@ func simpleEditor(v *View, key Key, ch rune, mod Modifier) {
case KeyEnter:
v.EditNewLine()
case KeyArrowDown:
v.moveCursor(0, 1)
v.MoveCursor(0, 1)
case KeyArrowUp:
v.moveCursor(0, -1)
v.MoveCursor(0, -1)
case KeyArrowLeft:
v.moveCursor(-1, 0)
v.MoveCursor(-1, 0)
case KeyArrowRight:
v.moveCursor(1, 0)
v.MoveCursor(1, 0)
case KeyTab:
v.EditWrite('\t')
case KeyEsc:
Expand All @@ -66,7 +64,7 @@ func simpleEditor(v *View, key Key, ch rune, mod Modifier) {
// EditWrite writes a rune at the cursor position.
func (v *View) EditWrite(ch rune) {
v.writeRune(v.cx, v.cy, ch)
v.moveCursor(1, 0)
v.MoveCursor(1, 0)
}

// EditDeleteToStartOfLine is the equivalent of pressing ctrl+U in your terminal, it deletes to the start of the line. Or if you are already at the start of the line, it deletes the newline character
Expand All @@ -87,7 +85,7 @@ func (v *View) EditDeleteToStartOfLine() {
func (v *View) EditGotoToStartOfLine() {
x, _ := v.Cursor()
for x > 0 {
v.moveCursor(-1, 0)
v.MoveCursor(-1, 0)
x, _ = v.Cursor()
}
}
Expand All @@ -102,12 +100,12 @@ func (v *View) EditGotoToEndOfLine() {
prevX := -1
for prevX != x {
prevX = x
v.moveCursor(1, 0)
v.MoveCursor(1, 0)
x, _ = v.Cursor()
}
} else {
// most left so now we're at the end of the original line
v.moveCursor(-1, 0)
v.MoveCursor(-1, 0)
}
}

Expand All @@ -119,7 +117,7 @@ func (v *View) EditDelete(back bool) {
return
}
if y >= len(v.lines) {
v.moveCursor(-1, 0)
v.MoveCursor(-1, 0)
return
}

Expand All @@ -135,15 +133,16 @@ func (v *View) EditDelete(back bool) {
return
}
if back { // middle/end of the line
n, _ := v.deleteRune(v.cx-1, v.cy)
v.moveCursor(-n, 0)
if err := v.deleteRune(v.cx-1, v.cy); err == nil {
v.MoveCursor(-1, 0)
}
return
}
if x == len(v.lines[y]) { // end of the line
_ = v.mergeLines(y)
return
}
_, _ = v.deleteRune(v.cx, v.cy) // start/middle of the line
v.deleteRune(v.cx, v.cy) // start/middle of the line
}

// EditNewLine inserts a new line under the cursor.
Expand All @@ -156,11 +155,6 @@ func (v *View) EditNewLine() {

// MoveCursor mores the cursor relative from it's current possition
func (v *View) MoveCursor(dx, dy int) {
v.moveCursor(dx, dy)
v.gui.userEvents <- userEvent{func(g *Gui) error { return nil }}
}

func (v *View) moveCursor(dx, dy int) {
newX, newY := v.cx+dx, v.cy+dy

if len(v.lines) == 0 {
Expand Down Expand Up @@ -266,26 +260,16 @@ 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).
// returns the amount of columns that where removed.
func (v *View) deleteRune(x, y int) (int, error) {
// returns error if invalid point is specified.
func (v *View) deleteRune(x, y int) error {
v.tainted = true

if x < 0 || y < 0 || y >= len(v.lines) || x >= len(v.lines[y]) {
return 0, errors.New("invalid point")
}

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 errors.New("invalid point")
}

return 0, nil
v.lines[y] = append(v.lines[y][:x], v.lines[y][x+1:]...)
return nil
}

// mergeLines merges the lines "y" and "y+1" if possible.
Expand Down
29 changes: 22 additions & 7 deletions view.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,11 @@ func (v *View) draw() error {
if err := v.setRune(x, y, char.chr, fgColor, bgColor); err != nil {
return err
}
x += runewidth.RuneWidth(char.chr)
if char.chr == 0 {
x++ // if NULL increase, so `SetWritePos` can be used (NULL translate to SPACE in setRune)
} else {
x += runewidth.RuneWidth(char.chr)
}
}
y++
}
Expand Down Expand Up @@ -733,8 +737,9 @@ func (v *View) Buffer() string {
// ViewBufferLines returns the lines in the view's internal
// buffer that is shown to the user.
func (v *View) ViewBufferLines() []string {
lines := make([]string, len(v.lines))
for i, line := range v.lines {
viewLines := v.viewLines()
lines := make([]string, len(viewLines))
for i, line := range viewLines {
str := lineType(line).String()
str = strings.Replace(str, "\x00", " ", -1)
lines[i] = str
Expand All @@ -759,7 +764,7 @@ func (v *View) ViewLinesHeight() int {
// ViewBuffer returns a string with the contents of the view's buffer that is
// shown to the user.
func (v *View) ViewBuffer() string {
return linesToString(v.lines)
return linesToString(v.viewLines())
}

// Line returns a string with the line of the view's internal buffer
Expand Down Expand Up @@ -846,7 +851,11 @@ func (v *View) SetHighlight(y int, on bool) error {

func lineWidth(line []cell) (n int) {
for i := range line {
n += runewidth.RuneWidth(line[i].chr)
if line[i].chr == 0 {
n++ // if it's NULL character, it's translated to SPACE in setRune
} else {
n += runewidth.RuneWidth(line[i].chr)
}
}

return
Expand All @@ -872,9 +881,13 @@ func (v *View) takeLine(l *[]cell) (visableLine []cell, width int, end bool) {

for i, cell = range *l {
chr := cell.chr
charWidth := runewidth.RuneWidth(chr)
charWidth := 1 // default for NULL character (translated to SPACE in setRune)
if chr != 0 {
charWidth = runewidth.RuneWidth(chr)
}

if width+charWidth > maxX {
i-- // decrease as this character is not included
break
}

Expand All @@ -898,7 +911,9 @@ func linesToString(lines [][]cell) string {
rns := make([]rune, 0, len(lines[i]))
line := lineType(lines[i]).String()
for _, c := range line {
if c != '\x00' {
if c == '\x00' {
rns = append(rns, ' ')
} else {
rns = append(rns, c)
}
}
Expand Down