diff --git a/go.mod b/go.mod index 9eef2df..e2c9f10 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect + golang.org/x/text v0.3.6 // indirect ) replace mvdan.cc/sh/v3 => github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220306140409-795a84b00b4e diff --git a/go.sum b/go.sum index 3cad6af..bc3a192 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/Rosettea/golua v0.0.0-20220406024702-f447a8095170 h1:k2MAUwR1diHqqoFPEhxMKAQoz131tMSti8ArzCTg2HI= -github.com/Rosettea/golua v0.0.0-20220406024702-f447a8095170/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE= github.com/Rosettea/golua v0.0.0-20220419183026-6d22d6fec5ac h1:dtXrgjch8PQyf7C90anZUquB5U3dr8AcMGJofeuirrI= github.com/Rosettea/golua v0.0.0-20220419183026-6d22d6fec5ac/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE= github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220306140409-795a84b00b4e h1:P2XupP8SaylWaudD1DqbWtZ3mIa8OsE9635LmR+Q+lg= @@ -57,6 +55,7 @@ golang.org/x/term v0.0.0-20210916214954-140adaaadfaf/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/readline/update.go b/readline/update.go index 7c8d657..508ae24 100644 --- a/readline/update.go +++ b/readline/update.go @@ -1,5 +1,7 @@ package readline +import "golang.org/x/text/width" + // updateHelpers is a key part of the whole refresh process: // it should coordinate reprinting the input line, any Infos and completions // and manage to get back to the current (computed) cursor coordinates @@ -21,6 +23,23 @@ func (rl *Instance) updateHelpers() { rl.renderHelpers() } +const tabWidth = 4 + +func getWidth(x []rune) int { + var w int + for _, j := range x { + k := width.LookupRune(j).Kind() + if j == '\t' { + w += tabWidth + } else if k == width.EastAsianWide || k == width.EastAsianFullwidth { + w += 2 + } else { + w++ + } + } + return w +} + // Update reference should be called only once in a "loop" (not Readline(), but key control loop) func (rl *Instance) updateReferences() { @@ -33,11 +52,11 @@ func (rl *Instance) updateReferences() { var fullLine, cPosLine int if len(rl.currentComp) > 0 { - fullLine = len(rl.lineComp) - cPosLine = len(rl.lineComp[:rl.pos]) + fullLine = getWidth(rl.lineComp) + cPosLine = getWidth(rl.lineComp[:rl.pos]) } else { - fullLine = len(rl.line) - cPosLine = len(rl.line[:rl.pos]) + fullLine = getWidth(rl.line) + cPosLine = getWidth(rl.line[:rl.pos]) } // We need the X offset of the whole line @@ -106,7 +125,7 @@ func (rl *Instance) clearHelpers() { // and replaces the cursor to its current position. This function never // computes or refreshes any value, except from inside the echo function. func (rl *Instance) renderHelpers() { - + // when the instance is in this state we want it to be "below" the user's // input for it to be aligned properly if !rl.compConfirmWait {