mirror of
				https://gitea.com/gitea/tea.git
				synced 2025-10-31 09:15:26 +01:00 
			
		
		
		
	Use Survey For Interactions With User (#186)
fixes Use Survey For Interactions With User Add Vendor "github.com/AlecAivazis/survey/v2" Co-authored-by: Norwin Roosen <git@nroo.de> Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/186 Reviewed-by: techknowlogick <techknowlogick@gitea.io> Reviewed-by: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
		
							
								
								
									
										22
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| Copyright (c) 2014 Takashi Kokubun | ||||
|  | ||||
| MIT License | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining | ||||
| a copy of this software and associated documentation files (the | ||||
| "Software"), to deal in the Software without restriction, including | ||||
| without limitation the rights to use, copy, modify, merge, publish, | ||||
| distribute, sublicense, and/or sell copies of the Software, and to | ||||
| permit persons to whom the Software is furnished to do so, subject to | ||||
| the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be | ||||
| included in all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										3
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # survey/terminal | ||||
|  | ||||
| This package started as a copy of [kokuban/go-ansi](http://github.com/k0kubun/go-ansi) but has since been modified to fit survey's specific needs. | ||||
							
								
								
									
										22
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/buffered_reader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/buffered_reader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| type BufferedReader struct { | ||||
| 	In     io.Reader | ||||
| 	Buffer *bytes.Buffer | ||||
| } | ||||
|  | ||||
| func (br *BufferedReader) Read(p []byte) (int, error) { | ||||
| 	n, err := br.Buffer.Read(p) | ||||
| 	if err != nil && err != io.EOF { | ||||
| 		return n, err | ||||
| 	} else if err == nil { | ||||
| 		return n, nil | ||||
| 	} | ||||
|  | ||||
| 	return br.In.Read(p[n:]) | ||||
| } | ||||
							
								
								
									
										190
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| // +build !windows | ||||
|  | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| ) | ||||
|  | ||||
| var COORDINATE_SYSTEM_BEGIN Short = 1 | ||||
|  | ||||
| var dsrPattern = regexp.MustCompile(`\x1b\[(\d+);(\d+)R$`) | ||||
|  | ||||
| type Cursor struct { | ||||
| 	In  FileReader | ||||
| 	Out FileWriter | ||||
| } | ||||
|  | ||||
| // Up moves the cursor n cells to up. | ||||
| func (c *Cursor) Up(n int) { | ||||
| 	fmt.Fprintf(c.Out, "\x1b[%dA", n) | ||||
| } | ||||
|  | ||||
| // Down moves the cursor n cells to down. | ||||
| func (c *Cursor) Down(n int) { | ||||
| 	fmt.Fprintf(c.Out, "\x1b[%dB", n) | ||||
| } | ||||
|  | ||||
| // Forward moves the cursor n cells to right. | ||||
| func (c *Cursor) Forward(n int) { | ||||
| 	fmt.Fprintf(c.Out, "\x1b[%dC", n) | ||||
| } | ||||
|  | ||||
| // Back moves the cursor n cells to left. | ||||
| func (c *Cursor) Back(n int) { | ||||
| 	fmt.Fprintf(c.Out, "\x1b[%dD", n) | ||||
| } | ||||
|  | ||||
| // NextLine moves cursor to beginning of the line n lines down. | ||||
| func (c *Cursor) NextLine(n int) { | ||||
| 	fmt.Fprintf(c.Out, "\x1b[%dE", n) | ||||
| } | ||||
|  | ||||
| // PreviousLine moves cursor to beginning of the line n lines up. | ||||
| func (c *Cursor) PreviousLine(n int) { | ||||
| 	fmt.Fprintf(c.Out, "\x1b[%dF", n) | ||||
| } | ||||
|  | ||||
| // HorizontalAbsolute moves cursor horizontally to x. | ||||
| func (c *Cursor) HorizontalAbsolute(x int) { | ||||
| 	fmt.Fprintf(c.Out, "\x1b[%dG", x) | ||||
| } | ||||
|  | ||||
| // Show shows the cursor. | ||||
| func (c *Cursor) Show() { | ||||
| 	fmt.Fprint(c.Out, "\x1b[?25h") | ||||
| } | ||||
|  | ||||
| // Hide hide the cursor. | ||||
| func (c *Cursor) Hide() { | ||||
| 	fmt.Fprint(c.Out, "\x1b[?25l") | ||||
| } | ||||
|  | ||||
| // Move moves the cursor to a specific x,y location. | ||||
| func (c *Cursor) Move(x int, y int) { | ||||
| 	fmt.Fprintf(c.Out, "\x1b[%d;%df", x, y) | ||||
| } | ||||
|  | ||||
| // Save saves the current position | ||||
| func (c *Cursor) Save() { | ||||
| 	fmt.Fprint(c.Out, "\x1b7") | ||||
| } | ||||
|  | ||||
| // Restore restores the saved position of the cursor | ||||
| func (c *Cursor) Restore() { | ||||
| 	fmt.Fprint(c.Out, "\x1b8") | ||||
| } | ||||
|  | ||||
| // for comparability purposes between windows | ||||
| // in unix we need to print out a new line on some terminals | ||||
| func (c *Cursor) MoveNextLine(cur *Coord, terminalSize *Coord) { | ||||
| 	if cur.Y == terminalSize.Y { | ||||
| 		fmt.Fprintln(c.Out) | ||||
| 	} | ||||
| 	c.NextLine(1) | ||||
| } | ||||
|  | ||||
| // Location returns the current location of the cursor in the terminal | ||||
| func (c *Cursor) Location(buf *bytes.Buffer) (*Coord, error) { | ||||
| 	// ANSI escape sequence for DSR - Device Status Report | ||||
| 	// https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences | ||||
| 	fmt.Fprint(c.Out, "\x1b[6n") | ||||
|  | ||||
| 	// There may be input in Stdin prior to CursorLocation so make sure we don't | ||||
| 	// drop those bytes. | ||||
| 	var loc []int | ||||
| 	var match string | ||||
| 	for loc == nil { | ||||
| 		// Reports the cursor position (CPR) to the application as (as though typed at | ||||
| 		// the keyboard) ESC[n;mR, where n is the row and m is the column. | ||||
| 		reader := bufio.NewReader(c.In) | ||||
| 		text, err := reader.ReadSlice(byte('R')) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		loc = dsrPattern.FindStringIndex(string(text)) | ||||
| 		if loc == nil { | ||||
| 			// After reading slice to byte 'R', the bufio Reader may have read more | ||||
| 			// bytes into its internal buffer which will be discarded on next ReadSlice. | ||||
| 			// We create a temporary buffer to read the remaining buffered slice and | ||||
| 			// write them to output buffer. | ||||
| 			buffered := make([]byte, reader.Buffered()) | ||||
| 			_, err = io.ReadFull(reader, buffered) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			// Stdin contains R that doesn't match DSR, so pass the bytes along to | ||||
| 			// output buffer. | ||||
| 			buf.Write(text) | ||||
| 			buf.Write(buffered) | ||||
| 		} else { | ||||
| 			// Write the non-matching leading bytes to output buffer. | ||||
| 			buf.Write(text[:loc[0]]) | ||||
|  | ||||
| 			// Save the matching bytes to extract the row and column of the cursor. | ||||
| 			match = string(text[loc[0]:loc[1]]) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	matches := dsrPattern.FindStringSubmatch(string(match)) | ||||
| 	if len(matches) != 3 { | ||||
| 		return nil, fmt.Errorf("incorrect number of matches: %d", len(matches)) | ||||
| 	} | ||||
|  | ||||
| 	col, err := strconv.Atoi(matches[2]) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	row, err := strconv.Atoi(matches[1]) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &Coord{Short(col), Short(row)}, nil | ||||
| } | ||||
|  | ||||
| func (cur Coord) CursorIsAtLineEnd(size *Coord) bool { | ||||
| 	return cur.X == size.X | ||||
| } | ||||
|  | ||||
| func (cur Coord) CursorIsAtLineBegin() bool { | ||||
| 	return cur.X == COORDINATE_SYSTEM_BEGIN | ||||
| } | ||||
|  | ||||
| // Size returns the height and width of the terminal. | ||||
| func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) { | ||||
| 	// the general approach here is to move the cursor to the very bottom | ||||
| 	// of the terminal, ask for the current location and then move the | ||||
| 	// cursor back where we started | ||||
|  | ||||
| 	// hide the cursor (so it doesn't blink when getting the size of the terminal) | ||||
| 	c.Hide() | ||||
| 	// save the current location of the cursor | ||||
| 	c.Save() | ||||
|  | ||||
| 	// move the cursor to the very bottom of the terminal | ||||
| 	c.Move(999, 999) | ||||
|  | ||||
| 	// ask for the current location | ||||
| 	bottom, err := c.Location(buf) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// move back where we began | ||||
| 	c.Restore() | ||||
|  | ||||
| 	// show the cursor | ||||
| 	c.Show() | ||||
| 	// since the bottom was calculated in the lower right corner, it | ||||
| 	// is the dimensions we are looking for | ||||
| 	return bottom, nil | ||||
| } | ||||
							
								
								
									
										138
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/cursor_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/cursor_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,138 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| var COORDINATE_SYSTEM_BEGIN Short = 0 | ||||
|  | ||||
| // shared variable to save the cursor location from CursorSave() | ||||
| var cursorLoc Coord | ||||
|  | ||||
| type Cursor struct { | ||||
| 	In  FileReader | ||||
| 	Out FileWriter | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Up(n int) { | ||||
| 	c.cursorMove(0, n) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Down(n int) { | ||||
| 	c.cursorMove(0, -1*n) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Forward(n int) { | ||||
| 	c.cursorMove(n, 0) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Back(n int) { | ||||
| 	c.cursorMove(-1*n, 0) | ||||
| } | ||||
|  | ||||
| // save the cursor location | ||||
| func (c *Cursor) Save() { | ||||
| 	cursorLoc, _ = c.Location(nil) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Restore() { | ||||
| 	handle := syscall.Handle(c.Out.Fd()) | ||||
| 	// restore it to the original position | ||||
| 	procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursorLoc)))) | ||||
| } | ||||
|  | ||||
| func (cur Coord) CursorIsAtLineEnd(size *Coord) bool { | ||||
| 	return cur.X == size.X | ||||
| } | ||||
|  | ||||
| func (cur Coord) CursorIsAtLineBegin() bool { | ||||
| 	return cur.X == 0 | ||||
| } | ||||
|  | ||||
| func (c *Cursor) cursorMove(x int, y int) { | ||||
| 	handle := syscall.Handle(c.Out.Fd()) | ||||
|  | ||||
| 	var csbi consoleScreenBufferInfo | ||||
| 	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) | ||||
|  | ||||
| 	var cursor Coord | ||||
| 	cursor.X = csbi.cursorPosition.X + Short(x) | ||||
| 	cursor.Y = csbi.cursorPosition.Y + Short(y) | ||||
|  | ||||
| 	procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursor)))) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) NextLine(n int) { | ||||
| 	c.Up(n) | ||||
| 	c.HorizontalAbsolute(0) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) PreviousLine(n int) { | ||||
| 	c.Down(n) | ||||
| 	c.HorizontalAbsolute(0) | ||||
| } | ||||
|  | ||||
| // for comparability purposes between windows | ||||
| // in windows we don't have to print out a new line | ||||
| func (c *Cursor) MoveNextLine(cur Coord, terminalSize *Coord) { | ||||
| 	c.NextLine(1) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) HorizontalAbsolute(x int) { | ||||
| 	handle := syscall.Handle(c.Out.Fd()) | ||||
|  | ||||
| 	var csbi consoleScreenBufferInfo | ||||
| 	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) | ||||
|  | ||||
| 	var cursor Coord | ||||
| 	cursor.X = Short(x) | ||||
| 	cursor.Y = csbi.cursorPosition.Y | ||||
|  | ||||
| 	if csbi.size.X < cursor.X { | ||||
| 		cursor.X = csbi.size.X | ||||
| 	} | ||||
|  | ||||
| 	procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursor)))) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Show() { | ||||
| 	handle := syscall.Handle(c.Out.Fd()) | ||||
|  | ||||
| 	var cci consoleCursorInfo | ||||
| 	procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci))) | ||||
| 	cci.visible = 1 | ||||
|  | ||||
| 	procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci))) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Hide() { | ||||
| 	handle := syscall.Handle(c.Out.Fd()) | ||||
|  | ||||
| 	var cci consoleCursorInfo | ||||
| 	procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci))) | ||||
| 	cci.visible = 0 | ||||
|  | ||||
| 	procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci))) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Location(buf *bytes.Buffer) (Coord, error) { | ||||
| 	handle := syscall.Handle(c.Out.Fd()) | ||||
|  | ||||
| 	var csbi consoleScreenBufferInfo | ||||
| 	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) | ||||
|  | ||||
| 	return csbi.cursorPosition, nil | ||||
| } | ||||
|  | ||||
| func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) { | ||||
| 	handle := syscall.Handle(c.Out.Fd()) | ||||
|  | ||||
| 	var csbi consoleScreenBufferInfo | ||||
| 	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) | ||||
| 	// windows' coordinate system begins at (0, 0) | ||||
| 	csbi.size.X-- | ||||
| 	csbi.size.Y-- | ||||
| 	return &csbi.size, nil | ||||
| } | ||||
							
								
								
									
										9
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/display.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/display.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package terminal | ||||
|  | ||||
| type EraseLineMode int | ||||
|  | ||||
| const ( | ||||
| 	ERASE_LINE_END EraseLineMode = iota | ||||
| 	ERASE_LINE_START | ||||
| 	ERASE_LINE_ALL | ||||
| ) | ||||
							
								
								
									
										11
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/display_posix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/display_posix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !windows | ||||
|  | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| func EraseLine(out FileWriter, mode EraseLineMode) { | ||||
| 	fmt.Fprintf(out, "\x1b[%dK", mode) | ||||
| } | ||||
							
								
								
									
										27
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/display_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/display_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| func EraseLine(out FileWriter, mode EraseLineMode) { | ||||
| 	handle := syscall.Handle(out.Fd()) | ||||
|  | ||||
| 	var csbi consoleScreenBufferInfo | ||||
| 	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) | ||||
|  | ||||
| 	var w uint32 | ||||
| 	var x Short | ||||
| 	cursor := csbi.cursorPosition | ||||
| 	switch mode { | ||||
| 	case ERASE_LINE_END: | ||||
| 		x = csbi.size.X | ||||
| 	case ERASE_LINE_START: | ||||
| 		x = 0 | ||||
| 	case ERASE_LINE_ALL: | ||||
| 		cursor.X = 0 | ||||
| 		x = csbi.size.X | ||||
| 	} | ||||
| 	procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(x), uintptr(*(*int32)(unsafe.Pointer(&cursor))), uintptr(unsafe.Pointer(&w))) | ||||
| } | ||||
							
								
								
									
										9
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	InterruptErr = errors.New("interrupt") | ||||
| ) | ||||
							
								
								
									
										19
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/output.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/output.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| // +build !windows | ||||
|  | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| // NewAnsiStdout returns special stdout, which converts escape sequences to Windows API calls | ||||
| // on Windows environment. | ||||
| func NewAnsiStdout(out FileWriter) io.Writer { | ||||
| 	return out | ||||
| } | ||||
|  | ||||
| // NewAnsiStderr returns special stderr, which converts escape sequences to Windows API calls | ||||
| // on Windows environment. | ||||
| func NewAnsiStderr(out FileWriter) io.Writer { | ||||
| 	return out | ||||
| } | ||||
							
								
								
									
										227
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/output_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/output_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,227 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/mattn/go-isatty" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	cursorFunctions = map[rune]func(c *Cursor) func(int){ | ||||
| 		'A': func(c *Cursor) func(int) { return c.Up }, | ||||
| 		'B': func(c *Cursor) func(int) { return c.Down }, | ||||
| 		'C': func(c *Cursor) func(int) { return c.Forward }, | ||||
| 		'D': func(c *Cursor) func(int) { return c.Back }, | ||||
| 		'E': func(c *Cursor) func(int) { return c.NextLine }, | ||||
| 		'F': func(c *Cursor) func(int) { return c.PreviousLine }, | ||||
| 		'G': func(c *Cursor) func(int) { return c.HorizontalAbsolute }, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	foregroundBlue      = 0x1 | ||||
| 	foregroundGreen     = 0x2 | ||||
| 	foregroundRed       = 0x4 | ||||
| 	foregroundIntensity = 0x8 | ||||
| 	foregroundMask      = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity) | ||||
| 	backgroundBlue      = 0x10 | ||||
| 	backgroundGreen     = 0x20 | ||||
| 	backgroundRed       = 0x40 | ||||
| 	backgroundIntensity = 0x80 | ||||
| 	backgroundMask      = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) | ||||
| ) | ||||
|  | ||||
| type Writer struct { | ||||
| 	out     FileWriter | ||||
| 	handle  syscall.Handle | ||||
| 	orgAttr word | ||||
| } | ||||
|  | ||||
| func NewAnsiStdout(out FileWriter) io.Writer { | ||||
| 	var csbi consoleScreenBufferInfo | ||||
| 	if !isatty.IsTerminal(out.Fd()) { | ||||
| 		return out | ||||
| 	} | ||||
| 	handle := syscall.Handle(out.Fd()) | ||||
| 	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) | ||||
| 	return &Writer{out: out, handle: handle, orgAttr: csbi.attributes} | ||||
| } | ||||
|  | ||||
| func NewAnsiStderr(out FileWriter) io.Writer { | ||||
| 	var csbi consoleScreenBufferInfo | ||||
| 	if !isatty.IsTerminal(out.Fd()) { | ||||
| 		return out | ||||
| 	} | ||||
| 	handle := syscall.Handle(out.Fd()) | ||||
| 	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) | ||||
| 	return &Writer{out: out, handle: handle, orgAttr: csbi.attributes} | ||||
| } | ||||
|  | ||||
| func (w *Writer) Write(data []byte) (n int, err error) { | ||||
| 	r := bytes.NewReader(data) | ||||
|  | ||||
| 	for { | ||||
| 		ch, size, err := r.ReadRune() | ||||
| 		if err != nil { | ||||
| 			break | ||||
| 		} | ||||
| 		n += size | ||||
|  | ||||
| 		switch ch { | ||||
| 		case '\x1b': | ||||
| 			size, err = w.handleEscape(r) | ||||
| 			n += size | ||||
| 			if err != nil { | ||||
| 				break | ||||
| 			} | ||||
| 		default: | ||||
| 			fmt.Fprint(w.out, string(ch)) | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (w *Writer) handleEscape(r *bytes.Reader) (n int, err error) { | ||||
| 	buf := make([]byte, 0, 10) | ||||
| 	buf = append(buf, "\x1b"...) | ||||
|  | ||||
| 	// Check '[' continues after \x1b | ||||
| 	ch, size, err := r.ReadRune() | ||||
| 	if err != nil { | ||||
| 		fmt.Fprint(w.out, string(buf)) | ||||
| 		return | ||||
| 	} | ||||
| 	n += size | ||||
| 	if ch != '[' { | ||||
| 		fmt.Fprint(w.out, string(buf)) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Parse escape code | ||||
| 	var code rune | ||||
| 	argBuf := make([]byte, 0, 10) | ||||
| 	for { | ||||
| 		ch, size, err = r.ReadRune() | ||||
| 		if err != nil { | ||||
| 			fmt.Fprint(w.out, string(buf)) | ||||
| 			return | ||||
| 		} | ||||
| 		n += size | ||||
| 		if ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') { | ||||
| 			code = ch | ||||
| 			break | ||||
| 		} | ||||
| 		argBuf = append(argBuf, string(ch)...) | ||||
| 	} | ||||
|  | ||||
| 	w.applyEscapeCode(buf, string(argBuf), code) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (w *Writer) applyEscapeCode(buf []byte, arg string, code rune) { | ||||
| 	c := &Cursor{Out: w.out} | ||||
|  | ||||
| 	switch arg + string(code) { | ||||
| 	case "?25h": | ||||
| 		c.Show() | ||||
| 		return | ||||
| 	case "?25l": | ||||
| 		c.Hide() | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if f, ok := cursorFunctions[code]; ok { | ||||
| 		if n, err := strconv.Atoi(arg); err == nil { | ||||
| 			f(c)(n) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	switch code { | ||||
| 	case 'm': | ||||
| 		w.applySelectGraphicRendition(arg) | ||||
| 	default: | ||||
| 		buf = append(buf, string(code)...) | ||||
| 		fmt.Fprint(w.out, string(buf)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Original implementation: https://github.com/mattn/go-colorable | ||||
| func (w *Writer) applySelectGraphicRendition(arg string) { | ||||
| 	if arg == "" { | ||||
| 		procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.orgAttr)) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	var csbi consoleScreenBufferInfo | ||||
| 	procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) | ||||
| 	attr := csbi.attributes | ||||
|  | ||||
| 	for _, param := range strings.Split(arg, ";") { | ||||
| 		n, err := strconv.Atoi(param) | ||||
| 		if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		switch { | ||||
| 		case n == 0 || n == 100: | ||||
| 			attr = w.orgAttr | ||||
| 		case 1 <= n && n <= 5: | ||||
| 			attr |= foregroundIntensity | ||||
| 		case 30 <= n && n <= 37: | ||||
| 			attr = (attr & backgroundMask) | ||||
| 			if (n-30)&1 != 0 { | ||||
| 				attr |= foregroundRed | ||||
| 			} | ||||
| 			if (n-30)&2 != 0 { | ||||
| 				attr |= foregroundGreen | ||||
| 			} | ||||
| 			if (n-30)&4 != 0 { | ||||
| 				attr |= foregroundBlue | ||||
| 			} | ||||
| 		case 40 <= n && n <= 47: | ||||
| 			attr = (attr & foregroundMask) | ||||
| 			if (n-40)&1 != 0 { | ||||
| 				attr |= backgroundRed | ||||
| 			} | ||||
| 			if (n-40)&2 != 0 { | ||||
| 				attr |= backgroundGreen | ||||
| 			} | ||||
| 			if (n-40)&4 != 0 { | ||||
| 				attr |= backgroundBlue | ||||
| 			} | ||||
| 		case 90 <= n && n <= 97: | ||||
| 			attr = (attr & backgroundMask) | ||||
| 			attr |= foregroundIntensity | ||||
| 			if (n-90)&1 != 0 { | ||||
| 				attr |= foregroundRed | ||||
| 			} | ||||
| 			if (n-90)&2 != 0 { | ||||
| 				attr |= foregroundGreen | ||||
| 			} | ||||
| 			if (n-90)&4 != 0 { | ||||
| 				attr |= foregroundBlue | ||||
| 			} | ||||
| 		case 100 <= n && n <= 107: | ||||
| 			attr = (attr & foregroundMask) | ||||
| 			attr |= backgroundIntensity | ||||
| 			if (n-100)&1 != 0 { | ||||
| 				attr |= backgroundRed | ||||
| 			} | ||||
| 			if (n-100)&2 != 0 { | ||||
| 				attr |= backgroundGreen | ||||
| 			} | ||||
| 			if (n-100)&4 != 0 { | ||||
| 				attr |= backgroundBlue | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr)) | ||||
| } | ||||
							
								
								
									
										330
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,330 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"unicode" | ||||
|  | ||||
| 	"golang.org/x/text/width" | ||||
| ) | ||||
|  | ||||
| type RuneReader struct { | ||||
| 	stdio  Stdio | ||||
| 	cursor *Cursor | ||||
| 	state  runeReaderState | ||||
| } | ||||
|  | ||||
| func NewRuneReader(stdio Stdio) *RuneReader { | ||||
| 	return &RuneReader{ | ||||
| 		stdio: stdio, | ||||
| 		state: newRuneReaderState(stdio.In), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) printChar(char rune, mask rune) { | ||||
| 	// if we don't need to mask the input | ||||
| 	if mask == 0 { | ||||
| 		// just print the character the user pressed | ||||
| 		fmt.Fprintf(rr.stdio.Out, "%c", char) | ||||
| 	} else { | ||||
| 		// otherwise print the mask we were given | ||||
| 		fmt.Fprintf(rr.stdio.Out, "%c", mask) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { | ||||
| 	line := []rune{} | ||||
| 	// we only care about horizontal displacements from the origin so start counting at 0 | ||||
| 	index := 0 | ||||
|  | ||||
| 	cursor := &Cursor{ | ||||
| 		In:  rr.stdio.In, | ||||
| 		Out: rr.stdio.Out, | ||||
| 	} | ||||
|  | ||||
| 	// we get the terminal width and height (if resized after this point the property might become invalid) | ||||
| 	terminalSize, _ := cursor.Size(rr.Buffer()) | ||||
| 	// we set the current location of the cursor once | ||||
| 	cursorCurrent, _ := cursor.Location(rr.Buffer()) | ||||
|  | ||||
| 	for { | ||||
| 		// wait for some input | ||||
| 		r, _, err := rr.ReadRune() | ||||
| 		if err != nil { | ||||
| 			return line, err | ||||
| 		} | ||||
| 		// increment cursor location | ||||
| 		cursorCurrent.X++ | ||||
|  | ||||
| 		// if the user pressed enter or some other newline/termination like ctrl+d | ||||
| 		if r == '\r' || r == '\n' || r == KeyEndTransmission { | ||||
| 			// delete what's printed out on the console screen (cleanup) | ||||
| 			for index > 0 { | ||||
| 				if cursorCurrent.CursorIsAtLineBegin() { | ||||
| 					EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 					cursor.PreviousLine(1) | ||||
| 					cursor.Forward(int(terminalSize.X)) | ||||
| 					cursorCurrent.X = terminalSize.X | ||||
| 					cursorCurrent.Y-- | ||||
|  | ||||
| 				} else { | ||||
| 					cursor.Back(1) | ||||
| 					cursorCurrent.X-- | ||||
| 				} | ||||
| 				index-- | ||||
| 			} | ||||
| 			// move the cursor the a new line | ||||
| 			cursor.MoveNextLine(cursorCurrent, terminalSize) | ||||
|  | ||||
| 			// we're done processing the input | ||||
| 			return line, nil | ||||
| 		} | ||||
| 		// if the user interrupts (ie with ctrl+c) | ||||
| 		if r == KeyInterrupt { | ||||
| 			// go to the beginning of the next line | ||||
| 			fmt.Fprint(rr.stdio.Out, "\r\n") | ||||
|  | ||||
| 			// we're done processing the input, and treat interrupt like an error | ||||
| 			return line, InterruptErr | ||||
| 		} | ||||
|  | ||||
| 		// allow for backspace/delete editing of inputs | ||||
| 		if r == KeyBackspace || r == KeyDelete { | ||||
| 			// and we're not at the beginning of the line | ||||
| 			if index > 0 && len(line) > 0 { | ||||
| 				// if we are at the end of the word | ||||
| 				if index == len(line) { | ||||
| 					// just remove the last letter from the internal representation | ||||
| 					// also count the number of cells the rune before the cursor occupied | ||||
| 					cells := runeWidth(line[len(line)-1]) | ||||
| 					line = line[:len(line)-1] | ||||
| 					// go back one | ||||
| 					if cursorCurrent.X == 1 { | ||||
| 						cursor.PreviousLine(1) | ||||
| 						cursor.Forward(int(terminalSize.X)) | ||||
| 					} else { | ||||
| 						cursor.Back(cells) | ||||
| 					} | ||||
|  | ||||
| 					// clear the rest of the line | ||||
| 					EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 				} else { | ||||
| 					// we need to remove a character from the middle of the word | ||||
|  | ||||
| 					cells := runeWidth(line[index-1]) | ||||
|  | ||||
| 					// remove the current index from the list | ||||
| 					line = append(line[:index-1], line[index:]...) | ||||
|  | ||||
| 					// save the current position of the cursor, as we have to move the cursor one back to erase the current symbol | ||||
| 					// and then move the cursor for each symbol in line[index-1:] to print it out, afterwards we want to restore | ||||
| 					// the cursor to its previous location. | ||||
| 					cursor.Save() | ||||
|  | ||||
| 					// clear the rest of the line | ||||
| 					cursor.Back(cells) | ||||
|  | ||||
| 					// print what comes after | ||||
| 					for _, char := range line[index-1:] { | ||||
| 						//Erase symbols which are left over from older print | ||||
| 						EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 						// print characters to the new line appropriately | ||||
| 						rr.printChar(char, mask) | ||||
|  | ||||
| 					} | ||||
| 					// erase what's left over from last print | ||||
| 					if cursorCurrent.Y < terminalSize.Y { | ||||
| 						cursor.NextLine(1) | ||||
| 						EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 					} | ||||
| 					// restore cursor | ||||
| 					cursor.Restore() | ||||
| 					if cursorCurrent.CursorIsAtLineBegin() { | ||||
| 						cursor.PreviousLine(1) | ||||
| 						cursor.Forward(int(terminalSize.X)) | ||||
| 					} else { | ||||
| 						cursor.Back(cells) | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				// decrement the index | ||||
| 				index-- | ||||
| 			} else { | ||||
| 				// otherwise the user pressed backspace while at the beginning of the line | ||||
| 				soundBell(rr.stdio.Out) | ||||
| 			} | ||||
|  | ||||
| 			// we're done processing this key | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// if the left arrow is pressed | ||||
| 		if r == KeyArrowLeft { | ||||
| 			// if we have space to the left | ||||
| 			if index > 0 { | ||||
| 				//move the cursor to the prev line if necessary | ||||
| 				if cursorCurrent.CursorIsAtLineBegin() { | ||||
| 					cursor.PreviousLine(1) | ||||
| 					cursor.Forward(int(terminalSize.X)) | ||||
| 				} else { | ||||
| 					cursor.Back(runeWidth(line[index-1])) | ||||
| 				} | ||||
| 				//decrement the index | ||||
| 				index-- | ||||
|  | ||||
| 			} else { | ||||
| 				// otherwise we are at the beginning of where we started reading lines | ||||
| 				// sound the bell | ||||
| 				soundBell(rr.stdio.Out) | ||||
| 			} | ||||
|  | ||||
| 			// we're done processing this key press | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// if the right arrow is pressed | ||||
| 		if r == KeyArrowRight { | ||||
| 			// if we have space to the right | ||||
| 			if index < len(line) { | ||||
| 				// move the cursor to the next line if necessary | ||||
| 				if cursorCurrent.CursorIsAtLineEnd(terminalSize) { | ||||
| 					cursor.NextLine(1) | ||||
| 				} else { | ||||
| 					cursor.Forward(runeWidth(line[index])) | ||||
| 				} | ||||
| 				index++ | ||||
|  | ||||
| 			} else { | ||||
| 				// otherwise we are at the end of the word and can't go past | ||||
| 				// sound the bell | ||||
| 				soundBell(rr.stdio.Out) | ||||
| 			} | ||||
|  | ||||
| 			// we're done processing this key press | ||||
| 			continue | ||||
| 		} | ||||
| 		// the user pressed one of the special keys | ||||
| 		if r == SpecialKeyHome { | ||||
| 			for index > 0 { | ||||
| 				if cursorCurrent.CursorIsAtLineBegin() { | ||||
| 					cursor.PreviousLine(1) | ||||
| 					cursor.Forward(int(terminalSize.X)) | ||||
| 					cursorCurrent.X = terminalSize.X | ||||
| 					cursorCurrent.Y-- | ||||
|  | ||||
| 				} else { | ||||
| 					cursor.Back(runeWidth(line[index-1])) | ||||
| 					cursorCurrent.X-- | ||||
| 				} | ||||
| 				index-- | ||||
| 			} | ||||
| 			continue | ||||
| 			// user pressed end | ||||
| 		} else if r == SpecialKeyEnd { | ||||
| 			for index != len(line) { | ||||
| 				if cursorCurrent.CursorIsAtLineEnd(terminalSize) { | ||||
| 					cursor.NextLine(1) | ||||
| 					cursorCurrent.X = COORDINATE_SYSTEM_BEGIN | ||||
| 					cursorCurrent.Y++ | ||||
|  | ||||
| 				} else { | ||||
| 					cursor.Forward(runeWidth(line[index])) | ||||
| 					cursorCurrent.X++ | ||||
| 				} | ||||
| 				index++ | ||||
| 			} | ||||
| 			continue | ||||
| 			// user pressed forward delete key | ||||
| 		} else if r == SpecialKeyDelete { | ||||
| 			// if index at the end of the line nothing to delete | ||||
| 			if index != len(line) { | ||||
| 				// save the current position of the cursor, as we have to  erase the current symbol | ||||
| 				// and then move the cursor for each symbol in line[index:] to print it out, afterwards we want to restore | ||||
| 				// the cursor to its previous location. | ||||
| 				cursor.Save() | ||||
| 				// remove the symbol after the cursor | ||||
| 				line = append(line[:index], line[index+1:]...) | ||||
| 				// print the updated line | ||||
| 				for _, char := range line[index:] { | ||||
| 					EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 					// print out the character | ||||
| 					rr.printChar(char, mask) | ||||
| 				} | ||||
| 				// erase what's left on last line | ||||
| 				if cursorCurrent.Y < terminalSize.Y { | ||||
| 					cursor.NextLine(1) | ||||
| 					EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 				} | ||||
| 				// restore cursor | ||||
| 				cursor.Restore() | ||||
| 				if len(line) == 0 || index == len(line) { | ||||
| 					EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 				} | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// if the letter is another escape sequence | ||||
| 		if unicode.IsControl(r) || r == IgnoreKey { | ||||
| 			// ignore it | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// the user pressed a regular key | ||||
|  | ||||
| 		// if we are at the end of the line | ||||
| 		if index == len(line) { | ||||
| 			// just append the character at the end of the line | ||||
| 			line = append(line, r) | ||||
| 			// save the location of the cursor | ||||
| 			index++ | ||||
| 			// print out the character | ||||
| 			rr.printChar(r, mask) | ||||
| 		} else { | ||||
| 			// we are in the middle of the word so we need to insert the character the user pressed | ||||
| 			line = append(line[:index], append([]rune{r}, line[index:]...)...) | ||||
| 			// save the current position of the cursor, as we have to move the cursor back to erase the current symbol | ||||
| 			// and then move for each symbol in line[index:] to print it out, afterwards we want to restore | ||||
| 			// cursor's location to its previous one. | ||||
| 			cursor.Save() | ||||
| 			EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 			// remove the symbol after the cursor | ||||
| 			// print the updated line | ||||
| 			for _, char := range line[index:] { | ||||
| 				EraseLine(rr.stdio.Out, ERASE_LINE_END) | ||||
| 				// print out the character | ||||
| 				rr.printChar(char, mask) | ||||
| 				cursorCurrent.X++ | ||||
| 			} | ||||
| 			// if we are at the last line, we want to visually insert a new line and append to it. | ||||
| 			if cursorCurrent.CursorIsAtLineEnd(terminalSize) && cursorCurrent.Y == terminalSize.Y { | ||||
| 				// add a new line to the terminal | ||||
| 				fmt.Fprintln(rr.stdio.Out) | ||||
| 				// restore the position of the cursor horizontally | ||||
| 				cursor.Restore() | ||||
| 				// restore the position of the cursor vertically | ||||
| 				cursor.Up(1) | ||||
| 			} else { | ||||
| 				// restore cursor | ||||
| 				cursor.Restore() | ||||
| 			} | ||||
| 			// check if cursor needs to move to next line | ||||
| 			cursorCurrent, _ = cursor.Location(rr.Buffer()) | ||||
| 			if cursorCurrent.CursorIsAtLineEnd(terminalSize) { | ||||
| 				cursor.NextLine(1) | ||||
| 			} else { | ||||
| 				cursor.Forward(runeWidth(r)) | ||||
| 			} | ||||
| 			// increment the index | ||||
| 			index++ | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func runeWidth(r rune) int { | ||||
| 	switch width.LookupRune(r).Kind() { | ||||
| 	case width.EastAsianWide, width.EastAsianFullwidth: | ||||
| 		return 2 | ||||
| 	} | ||||
| 	return 1 | ||||
| } | ||||
							
								
								
									
										13
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_bsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_bsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // copied from: https://github.com/golang/crypto/blob/master/ssh/terminal/util_bsd.go | ||||
| // Copyright 2013 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| // +build darwin dragonfly freebsd netbsd openbsd | ||||
|  | ||||
| package terminal | ||||
|  | ||||
| import "syscall" | ||||
|  | ||||
| const ioctlReadTermios = syscall.TIOCGETA | ||||
| const ioctlWriteTermios = syscall.TIOCSETA | ||||
							
								
								
									
										13
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // copied from https://github.com/golang/crypto/blob/master/ssh/terminal/util_linux.go | ||||
| // Copyright 2013 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| // +build linux,!ppc64le | ||||
|  | ||||
| package terminal | ||||
|  | ||||
| // These constants are declared here, rather than importing | ||||
| // them from the syscall package as some syscall packages, even | ||||
| // on linux, for example gccgo, do not declare them. | ||||
| const ioctlReadTermios = 0x5401  // syscall.TCGETS | ||||
| const ioctlWriteTermios = 0x5402 // syscall.TCSETS | ||||
							
								
								
									
										111
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_posix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_posix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| // +build !windows | ||||
|  | ||||
| // The terminal mode manipulation code is derived heavily from: | ||||
| // https://github.com/golang/crypto/blob/master/ssh/terminal/util.go: | ||||
| // Copyright 2011 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| type runeReaderState struct { | ||||
| 	term   syscall.Termios | ||||
| 	reader *bufio.Reader | ||||
| 	buf    *bytes.Buffer | ||||
| } | ||||
|  | ||||
| func newRuneReaderState(input FileReader) runeReaderState { | ||||
| 	buf := new(bytes.Buffer) | ||||
| 	return runeReaderState{ | ||||
| 		reader: bufio.NewReader(&BufferedReader{ | ||||
| 			In:     input, | ||||
| 			Buffer: buf, | ||||
| 		}), | ||||
| 		buf: buf, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) Buffer() *bytes.Buffer { | ||||
| 	return rr.state.buf | ||||
| } | ||||
|  | ||||
| // For reading runes we just want to disable echo. | ||||
| func (rr *RuneReader) SetTermMode() error { | ||||
| 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(rr.stdio.In.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&rr.state.term)), 0, 0, 0); err != 0 { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	newState := rr.state.term | ||||
| 	newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | ||||
|  | ||||
| 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(rr.stdio.In.Fd()), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) RestoreTermMode() error { | ||||
| 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(rr.stdio.In.Fd()), ioctlWriteTermios, uintptr(unsafe.Pointer(&rr.state.term)), 0, 0, 0); err != 0 { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) ReadRune() (rune, int, error) { | ||||
| 	r, size, err := rr.state.reader.ReadRune() | ||||
| 	if err != nil { | ||||
| 		return r, size, err | ||||
| 	} | ||||
|  | ||||
| 	// parse ^[ sequences to look for arrow keys | ||||
| 	if r == '\033' { | ||||
| 		if rr.state.reader.Buffered() == 0 { | ||||
| 			// no more characters so must be `Esc` key | ||||
| 			return KeyEscape, 1, nil | ||||
| 		} | ||||
| 		r, size, err = rr.state.reader.ReadRune() | ||||
| 		if err != nil { | ||||
| 			return r, size, err | ||||
| 		} | ||||
| 		if r != '[' { | ||||
| 			return r, size, fmt.Errorf("Unexpected Escape Sequence: %q", []rune{'\033', r}) | ||||
| 		} | ||||
| 		r, size, err = rr.state.reader.ReadRune() | ||||
| 		if err != nil { | ||||
| 			return r, size, err | ||||
| 		} | ||||
| 		switch r { | ||||
| 		case 'D': | ||||
| 			return KeyArrowLeft, 1, nil | ||||
| 		case 'C': | ||||
| 			return KeyArrowRight, 1, nil | ||||
| 		case 'A': | ||||
| 			return KeyArrowUp, 1, nil | ||||
| 		case 'B': | ||||
| 			return KeyArrowDown, 1, nil | ||||
| 		case 'H': // Home button | ||||
| 			return SpecialKeyHome, 1, nil | ||||
| 		case 'F': // End button | ||||
| 			return SpecialKeyEnd, 1, nil | ||||
| 		case '3': // Delete Button | ||||
| 			// discard the following '~' key from buffer | ||||
| 			rr.state.reader.Discard(1) | ||||
| 			return SpecialKeyDelete, 1, nil | ||||
| 		default: | ||||
| 			// discard the following '~' key from buffer | ||||
| 			rr.state.reader.Discard(1) | ||||
| 			return IgnoreKey, 1, nil | ||||
| 		} | ||||
| 		return r, size, fmt.Errorf("Unknown Escape Sequence: %q", []rune{'\033', '[', r}) | ||||
| 	} | ||||
| 	return r, size, err | ||||
| } | ||||
							
								
								
									
										7
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_ppc64le.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_ppc64le.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| // +build ppc64le,linux | ||||
|  | ||||
| package terminal | ||||
|  | ||||
| // Used syscall numbers from https://github.com/golang/go/blob/master/src/syscall/ztypes_linux_ppc64le.go | ||||
| const ioctlReadTermios = 0x402c7413  // syscall.TCGETS | ||||
| const ioctlWriteTermios = 0x802c7414 // syscall.TCSETS | ||||
							
								
								
									
										142
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/runereader_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	dll              = syscall.NewLazyDLL("kernel32.dll") | ||||
| 	setConsoleMode   = dll.NewProc("SetConsoleMode") | ||||
| 	getConsoleMode   = dll.NewProc("GetConsoleMode") | ||||
| 	readConsoleInput = dll.NewProc("ReadConsoleInputW") | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	EVENT_KEY = 0x0001 | ||||
|  | ||||
| 	// key codes for arrow keys | ||||
| 	// https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx | ||||
| 	VK_DELETE = 0x2E | ||||
| 	VK_END    = 0x23 | ||||
| 	VK_HOME   = 0x24 | ||||
| 	VK_LEFT   = 0x25 | ||||
| 	VK_UP     = 0x26 | ||||
| 	VK_RIGHT  = 0x27 | ||||
| 	VK_DOWN   = 0x28 | ||||
|  | ||||
| 	RIGHT_CTRL_PRESSED = 0x0004 | ||||
| 	LEFT_CTRL_PRESSED  = 0x0008 | ||||
|  | ||||
| 	ENABLE_ECHO_INPUT      uint32 = 0x0004 | ||||
| 	ENABLE_LINE_INPUT      uint32 = 0x0002 | ||||
| 	ENABLE_PROCESSED_INPUT uint32 = 0x0001 | ||||
| ) | ||||
|  | ||||
| type inputRecord struct { | ||||
| 	eventType uint16 | ||||
| 	padding   uint16 | ||||
| 	event     [16]byte | ||||
| } | ||||
|  | ||||
| type keyEventRecord struct { | ||||
| 	bKeyDown          int32 | ||||
| 	wRepeatCount      uint16 | ||||
| 	wVirtualKeyCode   uint16 | ||||
| 	wVirtualScanCode  uint16 | ||||
| 	unicodeChar       uint16 | ||||
| 	wdControlKeyState uint32 | ||||
| } | ||||
|  | ||||
| type runeReaderState struct { | ||||
| 	term uint32 | ||||
| } | ||||
|  | ||||
| func newRuneReaderState(input FileReader) runeReaderState { | ||||
| 	return runeReaderState{} | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) Buffer() *bytes.Buffer { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) SetTermMode() error { | ||||
| 	r, _, err := getConsoleMode.Call(uintptr(rr.stdio.In.Fd()), uintptr(unsafe.Pointer(&rr.state.term))) | ||||
| 	// windows return 0 on error | ||||
| 	if r == 0 { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	newState := rr.state.term | ||||
| 	newState &^= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ||||
| 	r, _, err = setConsoleMode.Call(uintptr(rr.stdio.In.Fd()), uintptr(newState)) | ||||
| 	// windows return 0 on error | ||||
| 	if r == 0 { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) RestoreTermMode() error { | ||||
| 	r, _, err := setConsoleMode.Call(uintptr(rr.stdio.In.Fd()), uintptr(rr.state.term)) | ||||
| 	// windows return 0 on error | ||||
| 	if r == 0 { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (rr *RuneReader) ReadRune() (rune, int, error) { | ||||
| 	ir := &inputRecord{} | ||||
| 	bytesRead := 0 | ||||
| 	for { | ||||
| 		rv, _, e := readConsoleInput.Call(rr.stdio.In.Fd(), uintptr(unsafe.Pointer(ir)), 1, uintptr(unsafe.Pointer(&bytesRead))) | ||||
| 		// windows returns non-zero to indicate success | ||||
| 		if rv == 0 && e != nil { | ||||
| 			return 0, 0, e | ||||
| 		} | ||||
|  | ||||
| 		if ir.eventType != EVENT_KEY { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// the event data is really a c struct union, so here we have to do an usafe | ||||
| 		// cast to put the data into the keyEventRecord (since we have already verified | ||||
| 		// above that this event does correspond to a key event | ||||
| 		key := (*keyEventRecord)(unsafe.Pointer(&ir.event[0])) | ||||
| 		// we only care about key down events | ||||
| 		if key.bKeyDown == 0 { | ||||
| 			continue | ||||
| 		} | ||||
| 		if key.wdControlKeyState&(LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED) != 0 && key.unicodeChar == 'C' { | ||||
| 			return KeyInterrupt, bytesRead, nil | ||||
| 		} | ||||
| 		// not a normal character so look up the input sequence from the | ||||
| 		// virtual key code mappings (VK_*) | ||||
| 		if key.unicodeChar == 0 { | ||||
| 			switch key.wVirtualKeyCode { | ||||
| 			case VK_DOWN: | ||||
| 				return KeyArrowDown, bytesRead, nil | ||||
| 			case VK_LEFT: | ||||
| 				return KeyArrowLeft, bytesRead, nil | ||||
| 			case VK_RIGHT: | ||||
| 				return KeyArrowRight, bytesRead, nil | ||||
| 			case VK_UP: | ||||
| 				return KeyArrowUp, bytesRead, nil | ||||
| 			case VK_DELETE: | ||||
| 				return SpecialKeyDelete, bytesRead, nil | ||||
| 			case VK_HOME: | ||||
| 				return SpecialKeyHome, bytesRead, nil | ||||
| 			case VK_END: | ||||
| 				return SpecialKeyEnd, bytesRead, nil | ||||
| 			default: | ||||
| 				// not a virtual key that we care about so just continue on to | ||||
| 				// the next input key | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 		r := rune(key.unicodeChar) | ||||
| 		return r, bytesRead, nil | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										30
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/sequences.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/sequences.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	KeyArrowLeft       = '\x02' | ||||
| 	KeyArrowRight      = '\x06' | ||||
| 	KeyArrowUp         = '\x10' | ||||
| 	KeyArrowDown       = '\x0e' | ||||
| 	KeySpace           = ' ' | ||||
| 	KeyEnter           = '\r' | ||||
| 	KeyBackspace       = '\b' | ||||
| 	KeyDelete          = '\x7f' | ||||
| 	KeyInterrupt       = '\x03' | ||||
| 	KeyEndTransmission = '\x04' | ||||
| 	KeyEscape          = '\x1b' | ||||
| 	KeyDeleteWord      = '\x17' // Ctrl+W | ||||
| 	KeyDeleteLine      = '\x18' // Ctrl+X | ||||
| 	SpecialKeyHome     = '\x01' | ||||
| 	SpecialKeyEnd      = '\x11' | ||||
| 	SpecialKeyDelete   = '\x12' | ||||
| 	IgnoreKey          = '\000' | ||||
| ) | ||||
|  | ||||
| func soundBell(out io.Writer) { | ||||
| 	fmt.Fprint(out, "\a") | ||||
| } | ||||
							
								
								
									
										24
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/stdio.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/stdio.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| // Stdio is the standard input/output the terminal reads/writes with. | ||||
| type Stdio struct { | ||||
| 	In  FileReader | ||||
| 	Out FileWriter | ||||
| 	Err io.Writer | ||||
| } | ||||
|  | ||||
| // FileWriter provides a minimal interface for Stdin. | ||||
| type FileWriter interface { | ||||
| 	io.Writer | ||||
| 	Fd() uintptr | ||||
| } | ||||
|  | ||||
| // FileReader provides a minimal interface for Stdout. | ||||
| type FileReader interface { | ||||
| 	io.Reader | ||||
| 	Fd() uintptr | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/syscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/syscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| package terminal | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	kernel32                       = syscall.NewLazyDLL("kernel32.dll") | ||||
| 	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") | ||||
| 	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute") | ||||
| 	procSetConsoleCursorPosition   = kernel32.NewProc("SetConsoleCursorPosition") | ||||
| 	procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") | ||||
| 	procGetConsoleCursorInfo       = kernel32.NewProc("GetConsoleCursorInfo") | ||||
| 	procSetConsoleCursorInfo       = kernel32.NewProc("SetConsoleCursorInfo") | ||||
| ) | ||||
|  | ||||
| type wchar uint16 | ||||
| type dword uint32 | ||||
| type word uint16 | ||||
|  | ||||
| type smallRect struct { | ||||
| 	left   Short | ||||
| 	top    Short | ||||
| 	right  Short | ||||
| 	bottom Short | ||||
| } | ||||
|  | ||||
| type consoleScreenBufferInfo struct { | ||||
| 	size              Coord | ||||
| 	cursorPosition    Coord | ||||
| 	attributes        word | ||||
| 	window            smallRect | ||||
| 	maximumWindowSize Coord | ||||
| } | ||||
|  | ||||
| type consoleCursorInfo struct { | ||||
| 	size    dword | ||||
| 	visible int32 | ||||
| } | ||||
							
								
								
									
										8
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/terminal.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/AlecAivazis/survey/v2/terminal/terminal.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| package terminal | ||||
|  | ||||
| type Short int16 | ||||
|  | ||||
| type Coord struct { | ||||
| 	X Short | ||||
| 	Y Short | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 6543
					6543