From f413a3dbb2e674175da3a5b06ef1e88bad0ad02a Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@users.noreply.github.com>
Date: Tue, 5 Feb 2019 12:00:42 +0100
Subject: [PATCH] vendor: update github.com/peterh/liner (#18990)

Fixes #16286
---
 .../github.com/peterh/liner/fallbackinput.go  |  2 +
 vendor/github.com/peterh/liner/go.mod         |  3 ++
 vendor/github.com/peterh/liner/go.sum         |  2 +
 vendor/github.com/peterh/liner/input.go       |  7 ++-
 .../github.com/peterh/liner/input_windows.go  | 35 ++++++++++++--
 vendor/github.com/peterh/liner/line.go        | 48 +++++++++++++++++--
 vendor/github.com/peterh/liner/output.go      |  3 --
 .../github.com/peterh/liner/output_windows.go |  4 --
 vendor/github.com/peterh/liner/width.go       | 31 +++++-------
 vendor/vendor.json                            |  6 +--
 10 files changed, 101 insertions(+), 40 deletions(-)
 create mode 100644 vendor/github.com/peterh/liner/go.mod
 create mode 100644 vendor/github.com/peterh/liner/go.sum

diff --git a/vendor/github.com/peterh/liner/fallbackinput.go b/vendor/github.com/peterh/liner/fallbackinput.go
index d9eb79d9e..043fb3321 100644
--- a/vendor/github.com/peterh/liner/fallbackinput.go
+++ b/vendor/github.com/peterh/liner/fallbackinput.go
@@ -55,3 +55,5 @@ func (n noopMode) ApplyMode() error {
 func TerminalMode() (ModeApplier, error) {
 	return noopMode{}, nil
 }
+
+const cursorColumn = true
diff --git a/vendor/github.com/peterh/liner/go.mod b/vendor/github.com/peterh/liner/go.mod
new file mode 100644
index 000000000..6804de36f
--- /dev/null
+++ b/vendor/github.com/peterh/liner/go.mod
@@ -0,0 +1,3 @@
+module github.com/peterh/liner
+
+require github.com/mattn/go-runewidth v0.0.3
diff --git a/vendor/github.com/peterh/liner/go.sum b/vendor/github.com/peterh/liner/go.sum
new file mode 100644
index 000000000..1c1891604
--- /dev/null
+++ b/vendor/github.com/peterh/liner/go.sum
@@ -0,0 +1,2 @@
+github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
+github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
diff --git a/vendor/github.com/peterh/liner/input.go b/vendor/github.com/peterh/liner/input.go
index 95dd5d143..e04e77225 100644
--- a/vendor/github.com/peterh/liner/input.go
+++ b/vendor/github.com/peterh/liner/input.go
@@ -264,9 +264,9 @@ func (s *State) readNext() (interface{}, error) {
 						return pageUp, nil
 					case 6:
 						return pageDown, nil
-					case 7:
+					case 1, 7:
 						return home, nil
-					case 8:
+					case 4, 8:
 						return end, nil
 					case 15:
 						return f5, nil
@@ -328,6 +328,9 @@ func (s *State) readNext() (interface{}, error) {
 	case 'b':
 		s.pending = s.pending[:0] // escape code complete
 		return altB, nil
+	case 'd':
+		s.pending = s.pending[:0] // escape code complete
+		return altD, nil
 	case 'f':
 		s.pending = s.pending[:0] // escape code complete
 		return altF, nil
diff --git a/vendor/github.com/peterh/liner/input_windows.go b/vendor/github.com/peterh/liner/input_windows.go
index a48eb0f1d..36e95161a 100644
--- a/vendor/github.com/peterh/liner/input_windows.go
+++ b/vendor/github.com/peterh/liner/input_windows.go
@@ -4,6 +4,7 @@ import (
 	"bufio"
 	"os"
 	"syscall"
+	"unicode/utf16"
 	"unsafe"
 )
 
@@ -103,7 +104,7 @@ type key_event_record struct {
 	RepeatCount     uint16
 	VirtualKeyCode  uint16
 	VirtualScanCode uint16
-	Char            int16
+	Char            uint16
 	ControlKeyState uint32
 }
 
@@ -111,6 +112,7 @@ type key_event_record struct {
 // what golint suggests)
 const (
 	vk_tab    = 0x09
+	vk_menu   = 0x12 // ALT key
 	vk_prior  = 0x21
 	vk_next   = 0x22
 	vk_end    = 0x23
@@ -134,6 +136,7 @@ const (
 	vk_f11    = 0x7a
 	vk_f12    = 0x7b
 	bKey      = 0x42
+	dKey      = 0x44
 	fKey      = 0x46
 	yKey      = 0x59
 )
@@ -174,6 +177,8 @@ func (s *State) readNext() (interface{}, error) {
 	var rv uint32
 	prv := uintptr(unsafe.Pointer(&rv))
 
+	var surrogate uint16
+
 	for {
 		ok, _, err := procReadConsoleInput.Call(uintptr(s.handle), pbuf, 1, prv)
 
@@ -184,9 +189,6 @@ func (s *State) readNext() (interface{}, error) {
 		if input.eventType == window_buffer_size_event {
 			xy := (*coord)(unsafe.Pointer(&input.blob[0]))
 			s.columns = int(xy.x)
-			if s.columns > 1 {
-				s.columns--
-			}
 			return winch, nil
 		}
 		if input.eventType != key_event {
@@ -194,6 +196,17 @@ func (s *State) readNext() (interface{}, error) {
 		}
 		ke := (*key_event_record)(unsafe.Pointer(&input.blob[0]))
 		if ke.KeyDown == 0 {
+			if ke.VirtualKeyCode == vk_menu && ke.Char > 0 {
+				// paste of unicode (eg. via ALT-numpad)
+				if surrogate > 0 {
+					return utf16.DecodeRune(rune(surrogate), rune(ke.Char)), nil
+				} else if utf16.IsSurrogate(rune(ke.Char)) {
+					surrogate = ke.Char
+					continue
+				} else {
+					return rune(ke.Char), nil
+				}
+			}
 			continue
 		}
 
@@ -202,6 +215,9 @@ func (s *State) readNext() (interface{}, error) {
 		} else if ke.VirtualKeyCode == bKey && (ke.ControlKeyState&modKeys == leftAltPressed ||
 			ke.ControlKeyState&modKeys == rightAltPressed) {
 			s.key = altB
+		} else if ke.VirtualKeyCode == dKey && (ke.ControlKeyState&modKeys == leftAltPressed ||
+			ke.ControlKeyState&modKeys == rightAltPressed) {
+			s.key = altD
 		} else if ke.VirtualKeyCode == fKey && (ke.ControlKeyState&modKeys == leftAltPressed ||
 			ke.ControlKeyState&modKeys == rightAltPressed) {
 			s.key = altF
@@ -209,7 +225,14 @@ func (s *State) readNext() (interface{}, error) {
 			ke.ControlKeyState&modKeys == rightAltPressed) {
 			s.key = altY
 		} else if ke.Char > 0 {
-			s.key = rune(ke.Char)
+			if surrogate > 0 {
+				s.key = utf16.DecodeRune(rune(surrogate), rune(ke.Char))
+			} else if utf16.IsSurrogate(rune(ke.Char)) {
+				surrogate = ke.Char
+				continue
+			} else {
+				s.key = rune(ke.Char)
+			}
 		} else {
 			switch ke.VirtualKeyCode {
 			case vk_prior:
@@ -337,3 +360,5 @@ func TerminalMode() (ModeApplier, error) {
 	}
 	return mode, err
 }
+
+const cursorColumn = true
diff --git a/vendor/github.com/peterh/liner/line.go b/vendor/github.com/peterh/liner/line.go
index d61f0696b..076a195c4 100644
--- a/vendor/github.com/peterh/liner/line.go
+++ b/vendor/github.com/peterh/liner/line.go
@@ -40,6 +40,7 @@ const (
 	f11
 	f12
 	altB
+	altD
 	altF
 	altY
 	shiftTab
@@ -112,6 +113,10 @@ func (s *State) refreshSingleLine(prompt []rune, buf []rune, pos int) error {
 
 	pLen := countGlyphs(prompt)
 	bLen := countGlyphs(buf)
+	// on some OS / terminals extra column is needed to place the cursor char
+	if cursorColumn {
+		bLen++
+	}
 	pos = countGlyphs(buf[:pos])
 	if pLen+bLen < s.columns {
 		_, err = fmt.Print(string(buf))
@@ -162,6 +167,14 @@ func (s *State) refreshSingleLine(prompt []rune, buf []rune, pos int) error {
 func (s *State) refreshMultiLine(prompt []rune, buf []rune, pos int) error {
 	promptColumns := countMultiLineGlyphs(prompt, s.columns, 0)
 	totalColumns := countMultiLineGlyphs(buf, s.columns, promptColumns)
+	// on some OS / terminals extra column is needed to place the cursor char
+	// if cursorColumn {
+	//	totalColumns++
+	// }
+
+	// it looks like Multiline mode always assume that a cursor need an extra column,
+	// and always emit a newline if we are at the screen end, so no worarounds needed there
+
 	totalRows := (totalColumns + s.columns - 1) / s.columns
 	maxRows := s.maxRows
 	if totalRows > s.maxRows {
@@ -583,7 +596,7 @@ func (s *State) Prompt(prompt string) (string, error) {
 
 // PromptWithSuggestion displays prompt and an editable text with cursor at
 // given position. The cursor will be set to the end of the line if given position
-// is negative or greater than length of text. Returns a line of user input, not
+// is negative or greater than length of text (in runes). Returns a line of user input, not
 // including a trailing newline character. An io.EOF error is returned if the user
 // signals end-of-file by pressing Ctrl-D.
 func (s *State) PromptWithSuggestion(prompt string, text string, pos int) (string, error) {
@@ -618,8 +631,8 @@ func (s *State) PromptWithSuggestion(prompt string, text string, pos int) (strin
 
 	defer s.stopPrompt()
 
-	if pos < 0 || len(text) < pos {
-		pos = len(text)
+	if pos < 0 || len(line) < pos {
+		pos = len(line)
 	}
 	if len(line) > 0 {
 		err := s.refresh(p, line, pos)
@@ -969,6 +982,35 @@ mainLoop:
 				pos = 0
 			case end: // End of line
 				pos = len(line)
+			case altD: // Delete next word
+				if pos == len(line) {
+					fmt.Print(beep)
+					break
+				}
+				// Remove whitespace to the right
+				var buf []rune // Store the deleted chars in a buffer
+				for {
+					if pos == len(line) || !unicode.IsSpace(line[pos]) {
+						break
+					}
+					buf = append(buf, line[pos])
+					line = append(line[:pos], line[pos+1:]...)
+				}
+				// Remove non-whitespace to the right
+				for {
+					if pos == len(line) || unicode.IsSpace(line[pos]) {
+						break
+					}
+					buf = append(buf, line[pos])
+					line = append(line[:pos], line[pos+1:]...)
+				}
+				// Save the result on the killRing
+				if killAction > 0 {
+					s.addToKillRing(buf, 2) // Add in prepend mode
+				} else {
+					s.addToKillRing(buf, 0) // Add in normal mode
+				}
+				killAction = 2 // Mark that there was some killing
 			case winch: // Window change
 				if s.multiLineMode {
 					if s.maxRows-s.cursorRows > 0 {
diff --git a/vendor/github.com/peterh/liner/output.go b/vendor/github.com/peterh/liner/output.go
index 6d83d4ebf..db0641cfe 100644
--- a/vendor/github.com/peterh/liner/output.go
+++ b/vendor/github.com/peterh/liner/output.go
@@ -56,9 +56,6 @@ func (s *State) getColumns() bool {
 		return false
 	}
 	s.columns = int(ws.col)
-	if cursorColumn && s.columns > 1 {
-		s.columns--
-	}
 	return true
 }
 
diff --git a/vendor/github.com/peterh/liner/output_windows.go b/vendor/github.com/peterh/liner/output_windows.go
index 63c9c5d75..45cd978c9 100644
--- a/vendor/github.com/peterh/liner/output_windows.go
+++ b/vendor/github.com/peterh/liner/output_windows.go
@@ -69,8 +69,4 @@ func (s *State) getColumns() {
 	var sbi consoleScreenBufferInfo
 	procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi)))
 	s.columns = int(sbi.dwSize.x)
-	if s.columns > 1 {
-		// Windows 10 needs a spare column for the cursor
-		s.columns--
-	}
 }
diff --git a/vendor/github.com/peterh/liner/width.go b/vendor/github.com/peterh/liner/width.go
index 42e899983..0395f3a8b 100644
--- a/vendor/github.com/peterh/liner/width.go
+++ b/vendor/github.com/peterh/liner/width.go
@@ -1,6 +1,10 @@
 package liner
 
-import "unicode"
+import (
+	"unicode"
+
+	"github.com/mattn/go-runewidth"
+)
 
 // These character classes are mostly zero width (when combined).
 // A few might not be, depending on the user's font. Fixing this
@@ -13,13 +17,6 @@ var zeroWidth = []*unicode.RangeTable{
 	unicode.Cf,
 }
 
-var doubleWidth = []*unicode.RangeTable{
-	unicode.Han,
-	unicode.Hangul,
-	unicode.Hiragana,
-	unicode.Katakana,
-}
-
 // countGlyphs considers zero-width characters to be zero glyphs wide,
 // and members of Chinese, Japanese, and Korean scripts to be 2 glyphs wide.
 func countGlyphs(s []rune) int {
@@ -31,13 +28,7 @@ func countGlyphs(s []rune) int {
 			continue
 		}
 
-		switch {
-		case unicode.IsOneOf(zeroWidth, r):
-		case unicode.IsOneOf(doubleWidth, r):
-			n += 2
-		default:
-			n++
-		}
+		n += runewidth.RuneWidth(r)
 	}
 	return n
 }
@@ -49,17 +40,17 @@ func countMultiLineGlyphs(s []rune, columns int, start int) int {
 			n++
 			continue
 		}
-		switch {
-		case unicode.IsOneOf(zeroWidth, r):
-		case unicode.IsOneOf(doubleWidth, r):
+		switch runewidth.RuneWidth(r) {
+		case 0:
+		case 1:
+			n++
+		case 2:
 			n += 2
 			// no room for a 2-glyphs-wide char in the ending
 			// so skip a column and display it at the beginning
 			if n%columns == 1 {
 				n++
 			}
-		default:
-			n++
 		}
 	}
 	return n
diff --git a/vendor/vendor.json b/vendor/vendor.json
index fd150a374..2e3847689 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -359,10 +359,10 @@
 			"revisionTime": "2017-01-12T15:04:04Z"
 		},
 		{
-			"checksumSHA1": "lSRg5clrIZUxq4aaExbpnpAgtWA=",
+			"checksumSHA1": "fGwQlTsml12gzgbWjOyyKPzbMD8=",
 			"path": "github.com/peterh/liner",
-			"revision": "a37ad39843113264dae84a5d89fcee28f50b35c6",
-			"revisionTime": "2017-09-02T20:46:57Z"
+			"revision": "a2c9a5303de792c7581a3b80a8f10258319bb20e",
+			"revisionTime": "2019-01-23T17:38:45Z"
 		},
 		{
 			"checksumSHA1": "xCv4GBFyw07vZkVtKF/XrUnkHRk=",
-- 
GitLab