diff --git a/document.go b/document.go index f2359b27..26daa903 100644 --- a/document.go +++ b/document.go @@ -6,6 +6,7 @@ import ( "github.com/elk-language/go-prompt/internal/bisect" istrings "github.com/elk-language/go-prompt/internal/strings" + runewidth "github.com/mattn/go-runewidth" "golang.org/x/exp/utf8string" ) @@ -132,6 +133,13 @@ func (d *Document) FindStartOfPreviousWord() int { return 0 } +// Returns the string width (as visible in the terminal) +// of the text before the cursor until the start of the previous word. +func (d *Document) FindStringWidthUntilStartOfPreviousWord() int { + x := d.TextBeforeCursor() + return runewidth.StringWidth(x[d.FindStartOfPreviousWordWithSpace():]) +} + // FindStartOfPreviousWordWithSpace is almost the same as FindStartOfPreviousWord. // The only difference is to ignore contiguous spaces. func (d *Document) FindStartOfPreviousWordWithSpace() int { @@ -211,6 +219,29 @@ func (d *Document) FindEndOfCurrentWordWithSpace() int { return start + end } +// Returns the string width (as visible in the terminal) +// of the text after the cursor until the end of the current word. +func (d *Document) FindStringWidthUntilEndOfCurrentWord() int { + t := d.TextAfterCursor() + width := 0 + nonSpaceCharSeen := false + for _, char := range t { + if !nonSpaceCharSeen && char == ' ' { + width += 1 + continue + } + + if nonSpaceCharSeen && char == ' ' { + break + } + + nonSpaceCharSeen = true + width += runewidth.RuneWidth(char) + } + + return width +} + // FindEndOfCurrentWordUntilSeparator is almost the same as FindEndOfCurrentWord. // But this can specify Separator. Return 0 if nothing was found. func (d *Document) FindEndOfCurrentWordUntilSeparator(sep string) int { diff --git a/emacs.go b/emacs.go index 636606bd..be34b6c4 100644 --- a/emacs.go +++ b/emacs.go @@ -98,7 +98,7 @@ var emacsKeyBindings = []KeyBind{ { Key: AltRight, Fn: func(buf *Buffer) { - buf.CursorRight(buf.Document().FindEndOfCurrentWordWithSpace()) + buf.CursorRight(buf.Document().FindStringWidthUntilEndOfCurrentWord()) }, }, // Left allow: Backward one character @@ -112,7 +112,7 @@ var emacsKeyBindings = []KeyBind{ { Key: AltLeft, Fn: func(buf *Buffer) { - buf.CursorLeft(len([]rune(buf.Document().TextBeforeCursor())) - buf.Document().FindStartOfPreviousWordWithSpace()) + buf.CursorLeft(buf.Document().FindStringWidthUntilStartOfPreviousWord()) }, }, // Cut the Word before the cursor.