mirror of
https://github.com/rancher/os.git
synced 2025-09-10 11:11:31 +00:00
move dependencies to vendor
This commit is contained in:
380
vendor/github.com/kless/term/readline/buffer.go
generated
vendored
Normal file
380
vendor/github.com/kless/term/readline/buffer.go
generated
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
// 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/.
|
||||
|
||||
package readline
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/kless/term"
|
||||
)
|
||||
|
||||
// Buffer size
|
||||
var (
|
||||
BufferCap = 4096
|
||||
BufferLen = 64 // Initial length
|
||||
)
|
||||
|
||||
// == Init
|
||||
|
||||
/*var lines, columns int
|
||||
|
||||
func init() {
|
||||
lines, columns = term.SizeInChar()
|
||||
}*/
|
||||
|
||||
// == Type
|
||||
|
||||
// A buffer represents the line buffer.
|
||||
type buffer struct {
|
||||
columns int // Number of columns for actual window
|
||||
promptLen int
|
||||
pos int // Pointer position into buffer
|
||||
size int // Amount of characters added
|
||||
data []rune // Text buffer
|
||||
}
|
||||
|
||||
func newBuffer(promptLen, columns int) *buffer {
|
||||
b := new(buffer)
|
||||
|
||||
b.columns = columns
|
||||
b.promptLen = promptLen
|
||||
b.data = make([]rune, BufferLen, BufferCap)
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// == Output
|
||||
|
||||
// insertRune inserts a character in the cursor position.
|
||||
func (b *buffer) insertRune(r rune) error {
|
||||
var useRefresh bool
|
||||
|
||||
b.grow(b.size + 1) // Check if there is free space for one more character
|
||||
|
||||
// Avoid a full update of the line.
|
||||
if b.pos == b.size {
|
||||
char := make([]byte, utf8.UTFMax)
|
||||
utf8.EncodeRune(char, r)
|
||||
|
||||
if _, err := term.Output.Write(char); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
} else {
|
||||
useRefresh = true
|
||||
copy(b.data[b.pos+1:b.size+1], b.data[b.pos:b.size])
|
||||
}
|
||||
|
||||
b.data[b.pos] = r
|
||||
b.pos++
|
||||
b.size++
|
||||
|
||||
if useRefresh {
|
||||
return b.refresh()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// insertRunes inserts several characters.
|
||||
func (b *buffer) insertRunes(runes []rune) error {
|
||||
for _, r := range runes {
|
||||
if err := b.insertRune(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// toBytes returns a slice of the contents of the buffer.
|
||||
func (b *buffer) toBytes() []byte {
|
||||
chars := make([]byte, b.size*utf8.UTFMax)
|
||||
var end, runeLen int
|
||||
|
||||
// == Each character (as integer) is encoded to []byte
|
||||
for i := 0; i < b.size; i++ {
|
||||
if i != 0 {
|
||||
runeLen = utf8.EncodeRune(chars[end:], b.data[i])
|
||||
end += runeLen
|
||||
} else {
|
||||
runeLen = utf8.EncodeRune(chars, b.data[i])
|
||||
end = runeLen
|
||||
}
|
||||
}
|
||||
return chars[:end]
|
||||
}
|
||||
|
||||
// toString returns the contents of the buffer as a string.
|
||||
func (b *buffer) toString() string { return string(b.data[b.promptLen:b.size]) }
|
||||
|
||||
// refresh refreshes the line.
|
||||
func (b *buffer) refresh() (err error) {
|
||||
lastLine, _ := b.pos2xy(b.size)
|
||||
posLine, posColumn := b.pos2xy(b.pos)
|
||||
|
||||
// To the first line.
|
||||
for ln := posLine; ln > 0; ln-- {
|
||||
if _, err = term.Output.Write(ToPreviousLine); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// == Write the line
|
||||
if _, err = term.Output.Write(CR); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
if _, err = term.Output.Write(b.toBytes()); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
if _, err = term.Output.Write(DelToRight); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
|
||||
// == Move cursor to original position.
|
||||
for ln := lastLine; ln > posLine; ln-- {
|
||||
if _, err = term.Output.Write(ToPreviousLine); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
}
|
||||
if _, err = fmt.Fprintf(term.Output, "\r\033[%dC", posColumn); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// == Movement
|
||||
|
||||
// start moves the cursor at the start.
|
||||
func (b *buffer) start() (err error) {
|
||||
if b.pos == b.promptLen {
|
||||
return
|
||||
}
|
||||
|
||||
for ln, _ := b.pos2xy(b.pos); ln > 0; ln-- {
|
||||
if _, err = term.Output.Write(CursorUp); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = fmt.Fprintf(term.Output, "\r\033[%dC", b.promptLen); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
b.pos = b.promptLen
|
||||
return
|
||||
}
|
||||
|
||||
// end moves the cursor at the end.
|
||||
// Returns the number of lines that fill in the data.
|
||||
func (b *buffer) end() (lines int, err error) {
|
||||
if b.pos == b.size {
|
||||
return
|
||||
}
|
||||
|
||||
lastLine, lastColumn := b.pos2xy(b.size)
|
||||
|
||||
for ln, _ := b.pos2xy(b.pos); ln < lastLine; ln++ {
|
||||
if _, err = term.Output.Write(CursorDown); err != nil {
|
||||
return 0, outputError(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = fmt.Fprintf(term.Output, "\r\033[%dC", lastColumn); err != nil {
|
||||
return 0, outputError(err.Error())
|
||||
}
|
||||
b.pos = b.size
|
||||
return lastLine, nil
|
||||
}
|
||||
|
||||
// backward moves the cursor one character backward.
|
||||
// Returns a boolean to know if the cursor is at the beginning of the line.
|
||||
func (b *buffer) backward() (start bool, err error) {
|
||||
if b.pos == b.promptLen {
|
||||
return true, nil
|
||||
}
|
||||
b.pos--
|
||||
|
||||
// If position is on the same line.
|
||||
if _, col := b.pos2xy(b.pos); col != 0 {
|
||||
if _, err = term.Output.Write(CursorBackward); err != nil {
|
||||
return false, outputError(err.Error())
|
||||
}
|
||||
} else {
|
||||
if _, err = term.Output.Write(CursorUp); err != nil {
|
||||
return false, outputError(err.Error())
|
||||
}
|
||||
if _, err = fmt.Fprintf(term.Output, "\033[%dC", b.columns); err != nil {
|
||||
return false, outputError(err.Error())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// forward moves the cursor one character forward.
|
||||
// Returns a boolean to know if the cursor is at the end of the line.
|
||||
func (b *buffer) forward() (end bool, err error) {
|
||||
if b.pos == b.size {
|
||||
return true, nil
|
||||
}
|
||||
b.pos++
|
||||
|
||||
if _, col := b.pos2xy(b.pos); col != 0 {
|
||||
if _, err = term.Output.Write(CursorForward); err != nil {
|
||||
return false, outputError(err.Error())
|
||||
}
|
||||
} else {
|
||||
if _, err = term.Output.Write(ToNextLine); err != nil {
|
||||
return false, outputError(err.Error())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// swap swaps the actual character by the previous one. If it is the end of the
|
||||
// line then it is swapped the 2nd previous by the previous one.
|
||||
func (b *buffer) swap() error {
|
||||
if b.pos == b.promptLen {
|
||||
return nil
|
||||
}
|
||||
|
||||
if b.pos < b.size {
|
||||
aux := b.data[b.pos-1]
|
||||
b.data[b.pos-1] = b.data[b.pos]
|
||||
b.data[b.pos] = aux
|
||||
b.pos++
|
||||
// End of line
|
||||
} else {
|
||||
aux := b.data[b.pos-2]
|
||||
b.data[b.pos-2] = b.data[b.pos-1]
|
||||
b.data[b.pos-1] = aux
|
||||
}
|
||||
return b.refresh()
|
||||
}
|
||||
|
||||
// wordBackward moves the cursor one word backward.
|
||||
func (b *buffer) wordBackward() (err error) {
|
||||
for start := false; ; {
|
||||
start, err = b.backward()
|
||||
if start == true || err != nil || b.data[b.pos-1] == 32 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wordForward moves the cursor one word forward.
|
||||
func (b *buffer) wordForward() (err error) {
|
||||
for end := false; ; {
|
||||
end, err = b.forward()
|
||||
if end == true || err != nil || b.data[b.pos] == 32 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// == Delete
|
||||
|
||||
// deleteChar deletes the character in cursor.
|
||||
func (b *buffer) deleteChar() (err error) {
|
||||
if b.pos == b.size {
|
||||
return
|
||||
}
|
||||
|
||||
copy(b.data[b.pos:], b.data[b.pos+1:b.size])
|
||||
b.size--
|
||||
|
||||
if lastLine, _ := b.pos2xy(b.size); lastLine == 0 {
|
||||
if _, err = term.Output.Write(DelChar); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return b.refresh()
|
||||
}
|
||||
|
||||
// deleteCharPrev deletes the previous character from cursor.
|
||||
func (b *buffer) deleteCharPrev() (err error) {
|
||||
if b.pos == b.promptLen {
|
||||
return
|
||||
}
|
||||
|
||||
copy(b.data[b.pos-1:], b.data[b.pos:b.size])
|
||||
b.pos--
|
||||
b.size--
|
||||
|
||||
if lastLine, _ := b.pos2xy(b.size); lastLine == 0 {
|
||||
if _, err = term.Output.Write(DelBackspace); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return b.refresh()
|
||||
}
|
||||
|
||||
// deleteToRight deletes from current position until to end of line.
|
||||
func (b *buffer) deleteToRight() (err error) {
|
||||
if b.pos == b.size {
|
||||
return
|
||||
}
|
||||
|
||||
lastLine, _ := b.pos2xy(b.size)
|
||||
posLine, _ := b.pos2xy(b.pos)
|
||||
|
||||
// To the last line.
|
||||
for ln := posLine; ln < lastLine; ln++ {
|
||||
if _, err = term.Output.Write(CursorDown); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
}
|
||||
// Delete all lines until the cursor position.
|
||||
for ln := lastLine; ln > posLine; ln-- {
|
||||
if _, err = term.Output.Write(DelLine_cursorUp); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = term.Output.Write(DelToRight); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
b.size = b.pos
|
||||
return nil
|
||||
}
|
||||
|
||||
// deleteLine deletes full line.
|
||||
func (b *buffer) deleteLine() error {
|
||||
lines, err := b.end()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for lines > 0 {
|
||||
if _, err = term.Output.Write(DelLine_cursorUp); err != nil {
|
||||
return outputError(err.Error())
|
||||
}
|
||||
lines--
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// == Utility
|
||||
|
||||
// grow grows buffer to guarantee space for n more byte.
|
||||
func (b *buffer) grow(n int) {
|
||||
for n > len(b.data) {
|
||||
b.data = b.data[:len(b.data)+BufferLen]
|
||||
}
|
||||
}
|
||||
|
||||
// pos2xy returns the coordinates of a position for a line of size given in
|
||||
// columns.
|
||||
func (b *buffer) pos2xy(pos int) (line, column int) {
|
||||
if pos < b.columns {
|
||||
return 0, pos
|
||||
}
|
||||
|
||||
line = pos / b.columns
|
||||
column = pos - (line * b.columns) //- 1
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user