mirror of
https://github.com/rancher/os.git
synced 2025-09-13 21:51:33 +00:00
move dependencies to vendor
This commit is contained in:
345
vendor/github.com/kless/term/readline/read_unix.go
generated
vendored
Normal file
345
vendor/github.com/kless/term/readline/read_unix.go
generated
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
// Copyright 2010 Jonas mg
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// +build !plan9,!windows
|
||||
|
||||
package readline
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/kless/term"
|
||||
"github.com/kless/term/sys"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if !term.SupportANSI() {
|
||||
panic("Your terminal does not support ANSI")
|
||||
}
|
||||
}
|
||||
|
||||
// NewLine returns a line using both prompts ps1 and ps2, and setting the given
|
||||
// terminal to raw mode, if were necessary.
|
||||
// lenAnsi is the length of ANSI codes that the prompt ps1 could have.
|
||||
// If the history is nil then it is not used.
|
||||
func NewLine(ter *term.Terminal, ps1, ps2 string, lenAnsi int, hist *history) (*Line, error) {
|
||||
if ter.Mode()&term.RawMode == 0 { // the raw mode is not set
|
||||
if err := ter.RawMode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
lenPS1 := len(ps1) - lenAnsi
|
||||
_, col, err := ter.GetSize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := newBuffer(lenPS1, col)
|
||||
buf.insertRunes([]rune(ps1))
|
||||
|
||||
return &Line{
|
||||
ter: ter,
|
||||
buf: buf,
|
||||
hist: hist,
|
||||
|
||||
ps1: ps1,
|
||||
ps2: ps2,
|
||||
lenPS1: lenPS1,
|
||||
|
||||
useHistory: hasHistory(hist),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Prompt prints the primary prompt.
|
||||
func (ln *Line) Prompt() (err error) {
|
||||
if _, err = term.Output.Write(DelLine_CR); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
if _, err = fmt.Fprint(term.Output, ln.ps1); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
|
||||
ln.buf.pos, ln.buf.size = ln.lenPS1, ln.lenPS1
|
||||
return
|
||||
}
|
||||
|
||||
// Read reads charactes from input to write them to output, enabling line editing.
|
||||
// The errors that could return are to indicate if Ctrl+D was pressed, and for
|
||||
// both input/output errors.
|
||||
func (ln *Line) Read() (line string, err error) {
|
||||
var anotherLine []rune // For lines got from history.
|
||||
var isHistoryUsed bool // If the history has been accessed.
|
||||
var action keyAction
|
||||
|
||||
in := bufio.NewReader(term.Input) // Read input.
|
||||
esc := make([]byte, 2) // For escape sequences.
|
||||
extEsc := make([]byte, 3) // Extended escape sequences.
|
||||
|
||||
// Print the primary prompt.
|
||||
if err = ln.Prompt(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// == Detect change of window size.
|
||||
winSize := term.DetectWinSize()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-winSize.Change: // Wait for.
|
||||
_, col, err := ln.ter.GetSize()
|
||||
if err != nil {
|
||||
ln.buf.columns = col
|
||||
ln.buf.refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer winSize.Close()
|
||||
|
||||
for ; ; action = 0 {
|
||||
char, _, err := in.ReadRune()
|
||||
if err != nil {
|
||||
return "", inputError(err.Error())
|
||||
}
|
||||
|
||||
_S:
|
||||
switch char {
|
||||
default:
|
||||
if err = ln.buf.insertRune(char); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
|
||||
case sys.K_RETURN:
|
||||
line = ln.buf.toString()
|
||||
|
||||
if ln.useHistory {
|
||||
ln.hist.Add(line)
|
||||
}
|
||||
if _, err = term.Output.Write(CRLF); err != nil {
|
||||
return "", outputError(err.Error())
|
||||
}
|
||||
return strings.TrimSpace(line), nil
|
||||
|
||||
case sys.K_TAB:
|
||||
// TODO: disabled by now
|
||||
continue
|
||||
|
||||
case sys.K_BACK, sys.K_CTRL_H:
|
||||
if err = ln.buf.deleteCharPrev(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
|
||||
case sys.K_CTRL_C:
|
||||
if err = ln.buf.insertRunes(CtrlC); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err = term.Output.Write(CRLF); err != nil {
|
||||
return "", outputError(err.Error())
|
||||
}
|
||||
|
||||
ChanCtrlC <- 1 //TODO: is really necessary?
|
||||
|
||||
if err = ln.Prompt(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
case sys.K_CTRL_D:
|
||||
if err = ln.buf.insertRunes(CtrlD); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err = term.Output.Write(CRLF); err != nil {
|
||||
return "", outputError(err.Error())
|
||||
}
|
||||
|
||||
ln.Restore()
|
||||
ChanCtrlD <- 1
|
||||
return "", ErrCtrlD
|
||||
|
||||
// Escape sequence
|
||||
case sys.K_ESCAPE: // Ctrl+[ ("\x1b" in hexadecimal, "033" in octal)
|
||||
if _, err = in.Read(esc); err != nil {
|
||||
return "", inputError(err.Error())
|
||||
}
|
||||
|
||||
if esc[0] == 79 { // 'O'
|
||||
switch esc[1] {
|
||||
case 72: // Home: "\x1b O H"
|
||||
action = _HOME
|
||||
break _S
|
||||
case 70: // End: "\x1b O F"
|
||||
action = _END
|
||||
break _S
|
||||
}
|
||||
}
|
||||
|
||||
if esc[0] == 91 { // '['
|
||||
switch esc[1] {
|
||||
case 65: // Up: "\x1b [ A"
|
||||
if !ln.useHistory {
|
||||
continue
|
||||
}
|
||||
action = _UP
|
||||
break _S
|
||||
case 66: // Down: "\x1b [ B"
|
||||
if !ln.useHistory {
|
||||
continue
|
||||
}
|
||||
action = _DOWN
|
||||
break _S
|
||||
case 68: // "\x1b [ D"
|
||||
action = _LEFT
|
||||
break _S
|
||||
case 67: // "\x1b [ C"
|
||||
action = _RIGHT
|
||||
break _S
|
||||
}
|
||||
|
||||
// Extended escape.
|
||||
if esc[1] > 48 && esc[1] < 55 {
|
||||
if _, err = in.Read(extEsc); err != nil {
|
||||
return "", inputError(err.Error())
|
||||
}
|
||||
|
||||
if extEsc[0] == 126 { // '~'
|
||||
switch esc[1] {
|
||||
//case 50: // Insert: "\x1b [ 2 ~"
|
||||
|
||||
case 51: // Delete: "\x1b [ 3 ~"
|
||||
if err = ln.buf.deleteChar(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
//case 53: // RePag: "\x1b [ 5 ~"
|
||||
|
||||
//case 54: // AvPag: "\x1b [ 6 ~"
|
||||
|
||||
}
|
||||
}
|
||||
if esc[1] == 49 && extEsc[0] == 59 && extEsc[1] == 53 { // "1;5"
|
||||
switch extEsc[2] {
|
||||
case 68: // Ctrl+left arrow: "\x1b [ 1 ; 5 D"
|
||||
// move to last word
|
||||
if err = ln.buf.wordBackward(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
case 67: // Ctrl+right arrow: "\x1b [ 1 ; 5 C"
|
||||
// move to next word
|
||||
if err = ln.buf.wordForward(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
|
||||
case sys.K_CTRL_T: // Swap actual character by the previous one.
|
||||
if err = ln.buf.swap(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
|
||||
case sys.K_CTRL_L: // Clear screen.
|
||||
if _, err = term.Output.Write(DelScreenToUpper); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = ln.Prompt(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
case sys.K_CTRL_U: // Delete the whole line.
|
||||
if err = ln.buf.deleteLine(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = ln.Prompt(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
case sys.K_CTRL_K: // Delete from current to end of line.
|
||||
if err = ln.buf.deleteToRight(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
|
||||
case sys.K_CTRL_P: // Up
|
||||
if !ln.useHistory {
|
||||
continue
|
||||
}
|
||||
action = _UP
|
||||
case sys.K_CTRL_N: // Down
|
||||
if !ln.useHistory {
|
||||
continue
|
||||
}
|
||||
action = _DOWN
|
||||
case sys.K_CTRL_B: // Left
|
||||
action = _LEFT
|
||||
case sys.K_CTRL_F: // Right
|
||||
action = _RIGHT
|
||||
|
||||
case sys.K_CTRL_A: // Start of line.
|
||||
action = _HOME
|
||||
case sys.K_CTRL_E: // End of line.
|
||||
action = _END
|
||||
}
|
||||
|
||||
switch action {
|
||||
case _UP, _DOWN: // Up and down arrow: history
|
||||
if action == _UP {
|
||||
anotherLine, err = ln.hist.Prev()
|
||||
} else {
|
||||
anotherLine, err = ln.hist.Next()
|
||||
}
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Update the current history entry before to overwrite it with
|
||||
// the next one.
|
||||
// TODO: it has to be removed before of to be saved the history
|
||||
if !isHistoryUsed {
|
||||
ln.hist.Add(ln.buf.toString())
|
||||
}
|
||||
isHistoryUsed = true
|
||||
|
||||
ln.buf.grow(len(anotherLine))
|
||||
ln.buf.size = len(anotherLine) + ln.buf.promptLen
|
||||
copy(ln.buf.data[ln.lenPS1:], anotherLine)
|
||||
|
||||
if err = ln.buf.refresh(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
case _LEFT:
|
||||
if _, err = ln.buf.backward(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
case _RIGHT:
|
||||
if _, err = ln.buf.forward(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
case _HOME:
|
||||
if err = ln.buf.start(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
case _END:
|
||||
if _, err = ln.buf.end(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user