aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/peterh
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2016-02-11 22:16:52 +0800
committerPéter Szilágyi <peterke@gmail.com>2016-02-11 22:16:52 +0800
commitb019f3ee29ce55c3d515ee8bafe0f4bb14221c0a (patch)
tree26e023be6c99a10e82a5a0ebadd1e42cefe9bd3c /Godeps/_workspace/src/github.com/peterh
parentb05e472c076d30035233d6a8b5fb3360b236e3ff (diff)
downloaddexon-b019f3ee29ce55c3d515ee8bafe0f4bb14221c0a.tar
dexon-b019f3ee29ce55c3d515ee8bafe0f4bb14221c0a.tar.gz
dexon-b019f3ee29ce55c3d515ee8bafe0f4bb14221c0a.tar.bz2
dexon-b019f3ee29ce55c3d515ee8bafe0f4bb14221c0a.tar.lz
dexon-b019f3ee29ce55c3d515ee8bafe0f4bb14221c0a.tar.xz
dexon-b019f3ee29ce55c3d515ee8bafe0f4bb14221c0a.tar.zst
dexon-b019f3ee29ce55c3d515ee8bafe0f4bb14221c0a.zip
Godeps: update all dependencies to latest code
Diffstat (limited to 'Godeps/_workspace/src/github.com/peterh')
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/README.md17
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/common.go26
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/input.go17
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/input_test.go61
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/input_windows.go8
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/line.go228
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/line_test.go90
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/output.go12
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/output_windows.go18
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/prefix_test.go37
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/race_test.go44
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/width.go34
-rw-r--r--Godeps/_workspace/src/github.com/peterh/liner/width_test.go87
13 files changed, 308 insertions, 371 deletions
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/README.md b/Godeps/_workspace/src/github.com/peterh/liner/README.md
index 99027c6e2..9148b2492 100644
--- a/Godeps/_workspace/src/github.com/peterh/liner/README.md
+++ b/Godeps/_workspace/src/github.com/peterh/liner/README.md
@@ -21,8 +21,8 @@ Ctrl-A, Home | Move cursor to beginning of line
Ctrl-E, End | Move cursor to end of line
Ctrl-B, Left | Move cursor one character left
Ctrl-F, Right| Move cursor one character right
-Ctrl-Left | Move cursor to previous word
-Ctrl-Right | Move cursor to next word
+Ctrl-Left, Alt-B | Move cursor to previous word
+Ctrl-Right, Alt-F | Move cursor to next word
Ctrl-D, Del | (if line is *not* empty) Delete character under cursor
Ctrl-D | (if line *is* empty) End of File - usually quits application
Ctrl-C | Reset input (create new empty prompt)
@@ -48,13 +48,14 @@ package main
import (
"log"
"os"
+ "path/filepath"
"strings"
"github.com/peterh/liner"
)
var (
- history_fn = "/tmp/.liner_history"
+ history_fn = filepath.Join(os.TempDir(), ".liner_example_history")
names = []string{"john", "james", "mary", "nancy"}
)
@@ -62,6 +63,8 @@ func main() {
line := liner.NewLiner()
defer line.Close()
+ line.SetCtrlCAborts(true)
+
line.SetCompleter(func(line string) (c []string) {
for _, n := range names {
if strings.HasPrefix(n, strings.ToLower(line)) {
@@ -76,11 +79,13 @@ func main() {
f.Close()
}
- if name, err := line.Prompt("What is your name? "); err != nil {
- log.Print("Error reading line: ", err)
- } else {
+ if name, err := line.Prompt("What is your name? "); err == nil {
log.Print("Got: ", name)
line.AppendHistory(name)
+ } else if err == liner.ErrPromptAborted {
+ log.Print("Aborted")
+ } else {
+ log.Print("Error reading line: ", err)
}
if f, err := os.Create(history_fn); err != nil {
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/common.go b/Godeps/_workspace/src/github.com/peterh/liner/common.go
index f8753a195..b6162b624 100644
--- a/Godeps/_workspace/src/github.com/peterh/liner/common.go
+++ b/Godeps/_workspace/src/github.com/peterh/liner/common.go
@@ -7,7 +7,6 @@ package liner
import (
"bufio"
- "bytes"
"container/ring"
"errors"
"fmt"
@@ -29,6 +28,10 @@ type commonState struct {
ctrlCAborts bool
r *bufio.Reader
tabStyle TabStyle
+ multiLineMode bool
+ cursorRows int
+ maxRows int
+ shouldRestart ShouldRestart
}
// TabStyle is used to select how tab completions are displayed.
@@ -174,7 +177,7 @@ func (s *State) SetCompleter(f Completer) {
return
}
s.completer = func(line string, pos int) (string, []string, string) {
- return "", f(line[:pos]), line[pos:]
+ return "", f(string([]rune(line)[:pos])), string([]rune(line)[pos:])
}
}
@@ -207,13 +210,28 @@ func (s *State) SetCtrlCAborts(aborts bool) {
s.ctrlCAborts = aborts
}
+// SetMultiLineMode sets whether line is auto-wrapped. The default is false (single line).
+func (s *State) SetMultiLineMode(mlmode bool) {
+ s.multiLineMode = mlmode
+}
+
+// ShouldRestart is passed the error generated by readNext and returns true if
+// the the read should be restarted or false if the error should be returned.
+type ShouldRestart func(err error) bool
+
+// SetShouldRestart sets the restart function that Liner will call to determine
+// whether to retry the call to, or return the error returned by, readNext.
+func (s *State) SetShouldRestart(f ShouldRestart) {
+ s.shouldRestart = f
+}
+
func (s *State) promptUnsupported(p string) (string, error) {
- if !s.inputRedirected {
+ if !s.inputRedirected || !s.terminalSupported {
fmt.Print(p)
}
linebuf, _, err := s.r.ReadLine()
if err != nil {
return "", err
}
- return string(bytes.TrimSpace(linebuf)), nil
+ return string(linebuf), nil
}
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/input.go b/Godeps/_workspace/src/github.com/peterh/liner/input.go
index cf71d2bce..c80c85f69 100644
--- a/Godeps/_workspace/src/github.com/peterh/liner/input.go
+++ b/Godeps/_workspace/src/github.com/peterh/liner/input.go
@@ -44,14 +44,15 @@ func NewLiner() *State {
if m, err := TerminalMode(); err == nil {
s.origMode = *m.(*termios)
} else {
- s.terminalSupported = false
s.inputRedirected = true
}
if _, err := getMode(syscall.Stdout); err != 0 {
- s.terminalSupported = false
s.outputRedirected = true
}
- if s.terminalSupported {
+ if s.inputRedirected && s.outputRedirected {
+ s.terminalSupported = false
+ }
+ if s.terminalSupported && !s.inputRedirected && !s.outputRedirected {
mode := s.origMode
mode.Iflag &^= icrnl | inpck | istrip | ixon
mode.Cflag |= cs8
@@ -328,6 +329,12 @@ func (s *State) readNext() (interface{}, error) {
default:
return unknown, nil
}
+ case 'b':
+ s.pending = s.pending[:0] // escape code complete
+ return altB, nil
+ case 'f':
+ s.pending = s.pending[:0] // escape code complete
+ return altF, nil
case 'y':
s.pending = s.pending[:0] // escape code complete
return altY, nil
@@ -344,7 +351,7 @@ func (s *State) readNext() (interface{}, error) {
// Close returns the terminal to its previous mode
func (s *State) Close() error {
stopSignal(s.winch)
- if s.terminalSupported {
+ if !s.inputRedirected {
s.origMode.ApplyMode()
}
return nil
@@ -353,6 +360,8 @@ func (s *State) Close() error {
// TerminalSupported returns true if the current terminal supports
// line editing features, and false if liner will use the 'dumb'
// fallback for input.
+// Note that TerminalSupported does not check all factors that may
+// cause liner to not fully support the terminal (such as stdin redirection)
func TerminalSupported() bool {
bad := map[string]bool{"": true, "dumb": true, "cons25": true}
return !bad[strings.ToLower(os.Getenv("TERM"))]
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/input_test.go b/Godeps/_workspace/src/github.com/peterh/liner/input_test.go
deleted file mode 100644
index e515a4894..000000000
--- a/Godeps/_workspace/src/github.com/peterh/liner/input_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// +build !windows
-
-package liner
-
-import (
- "bufio"
- "bytes"
- "testing"
-)
-
-func (s *State) expectRune(t *testing.T, r rune) {
- item, err := s.readNext()
- if err != nil {
- t.Fatalf("Expected rune '%c', got error %s\n", r, err)
- }
- if v, ok := item.(rune); !ok {
- t.Fatalf("Expected rune '%c', got non-rune %v\n", r, v)
- } else {
- if v != r {
- t.Fatalf("Expected rune '%c', got rune '%c'\n", r, v)
- }
- }
-}
-
-func (s *State) expectAction(t *testing.T, a action) {
- item, err := s.readNext()
- if err != nil {
- t.Fatalf("Expected Action %d, got error %s\n", a, err)
- }
- if v, ok := item.(action); !ok {
- t.Fatalf("Expected Action %d, got non-Action %v\n", a, v)
- } else {
- if v != a {
- t.Fatalf("Expected Action %d, got Action %d\n", a, v)
- }
- }
-}
-
-func TestTypes(t *testing.T) {
- input := []byte{'A', 27, 'B', 27, 91, 68, 27, '[', '1', ';', '5', 'D', 'e'}
- var s State
- s.r = bufio.NewReader(bytes.NewBuffer(input))
-
- next := make(chan nexter)
- go func() {
- for {
- var n nexter
- n.r, _, n.err = s.r.ReadRune()
- next <- n
- }
- }()
- s.next = next
-
- s.expectRune(t, 'A')
- s.expectRune(t, 27)
- s.expectRune(t, 'B')
- s.expectAction(t, left)
- s.expectAction(t, wordLeft)
-
- s.expectRune(t, 'e')
-}
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/input_windows.go b/Godeps/_workspace/src/github.com/peterh/liner/input_windows.go
index cc98719c1..9dcc3115c 100644
--- a/Godeps/_workspace/src/github.com/peterh/liner/input_windows.go
+++ b/Godeps/_workspace/src/github.com/peterh/liner/input_windows.go
@@ -132,6 +132,8 @@ const (
vk_f10 = 0x79
vk_f11 = 0x7a
vk_f12 = 0x7b
+ bKey = 0x42
+ fKey = 0x46
yKey = 0x59
)
@@ -178,6 +180,12 @@ func (s *State) readNext() (interface{}, error) {
if ke.VirtualKeyCode == vk_tab && ke.ControlKeyState&modKeys == shiftPressed {
s.key = shiftTab
+ } else if ke.VirtualKeyCode == bKey && (ke.ControlKeyState&modKeys == leftAltPressed ||
+ ke.ControlKeyState&modKeys == rightAltPressed) {
+ s.key = altB
+ } else if ke.VirtualKeyCode == fKey && (ke.ControlKeyState&modKeys == leftAltPressed ||
+ ke.ControlKeyState&modKeys == rightAltPressed) {
+ s.key = altF
} else if ke.VirtualKeyCode == yKey && (ke.ControlKeyState&modKeys == leftAltPressed ||
ke.ControlKeyState&modKeys == rightAltPressed) {
s.key = altY
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/line.go b/Godeps/_workspace/src/github.com/peterh/liner/line.go
index a70fb59e5..95364ae56 100644
--- a/Godeps/_workspace/src/github.com/peterh/liner/line.go
+++ b/Godeps/_workspace/src/github.com/peterh/liner/line.go
@@ -37,6 +37,8 @@ const (
f10
f11
f12
+ altB
+ altF
altY
shiftTab
wordLeft
@@ -88,6 +90,14 @@ const (
)
func (s *State) refresh(prompt []rune, buf []rune, pos int) error {
+ if s.multiLineMode {
+ return s.refreshMultiLine(prompt, buf, pos)
+ } else {
+ return s.refreshSingleLine(prompt, buf, pos)
+ }
+}
+
+func (s *State) refreshSingleLine(prompt []rune, buf []rune, pos int) error {
s.cursorPos(0)
_, err := fmt.Print(string(prompt))
if err != nil {
@@ -143,6 +153,82 @@ func (s *State) refresh(prompt []rune, buf []rune, pos int) error {
return err
}
+func (s *State) refreshMultiLine(prompt []rune, buf []rune, pos int) error {
+ promptColumns := countMultiLineGlyphs(prompt, s.columns, 0)
+ totalColumns := countMultiLineGlyphs(buf, s.columns, promptColumns)
+ totalRows := (totalColumns + s.columns - 1) / s.columns
+ maxRows := s.maxRows
+ if totalRows > s.maxRows {
+ s.maxRows = totalRows
+ }
+ cursorRows := s.cursorRows
+ if cursorRows == 0 {
+ cursorRows = 1
+ }
+
+ /* First step: clear all the lines used before. To do so start by
+ * going to the last row. */
+ if maxRows-cursorRows > 0 {
+ s.moveDown(maxRows - cursorRows)
+ }
+
+ /* Now for every row clear it, go up. */
+ for i := 0; i < maxRows-1; i++ {
+ s.cursorPos(0)
+ s.eraseLine()
+ s.moveUp(1)
+ }
+
+ /* Clean the top line. */
+ s.cursorPos(0)
+ s.eraseLine()
+
+ /* Write the prompt and the current buffer content */
+ if _, err := fmt.Print(string(prompt)); err != nil {
+ return err
+ }
+ if _, err := fmt.Print(string(buf)); err != nil {
+ return err
+ }
+
+ /* If we are at the very end of the screen with our prompt, we need to
+ * emit a newline and move the prompt to the first column. */
+ cursorColumns := countMultiLineGlyphs(buf[:pos], s.columns, promptColumns)
+ if cursorColumns == totalColumns && totalColumns%s.columns == 0 {
+ s.emitNewLine()
+ s.cursorPos(0)
+ totalRows++
+ if totalRows > s.maxRows {
+ s.maxRows = totalRows
+ }
+ }
+
+ /* Move cursor to right position. */
+ cursorRows = (cursorColumns + s.columns) / s.columns
+ if s.cursorRows > 0 && totalRows-cursorRows > 0 {
+ s.moveUp(totalRows - cursorRows)
+ }
+ /* Set column. */
+ s.cursorPos(cursorColumns % s.columns)
+
+ s.cursorRows = cursorRows
+ return nil
+}
+
+func (s *State) resetMultiLine(prompt []rune, buf []rune, pos int) {
+ columns := countMultiLineGlyphs(prompt, s.columns, 0)
+ columns = countMultiLineGlyphs(buf[:pos], s.columns, columns)
+ columns += 2 // ^C
+ cursorRows := (columns + s.columns) / s.columns
+ if s.maxRows-cursorRows > 0 {
+ for i := 0; i < s.maxRows-cursorRows; i++ {
+ fmt.Println() // always moves the cursor down or scrolls the window up as needed
+ }
+ }
+ s.maxRows = 1
+ s.cursorRows = 0
+}
+
func longestCommonPrefix(strs []string) string {
if len(strs) == 0 {
return ""
@@ -179,6 +265,29 @@ func (s *State) circularTabs(items []string) func(tabDirection) (string, error)
}
}
+func calculateColumns(screenWidth int, items []string) (numColumns, numRows, maxWidth int) {
+ for _, item := range items {
+ if len(item) >= screenWidth {
+ return 1, len(items), screenWidth - 1
+ }
+ if len(item) >= maxWidth {
+ maxWidth = len(item) + 1
+ }
+ }
+
+ numColumns = screenWidth / maxWidth
+ numRows = len(items) / numColumns
+ if len(items)%numColumns > 0 {
+ numRows++
+ }
+
+ if len(items) <= numColumns {
+ maxWidth = 0
+ }
+
+ return
+}
+
func (s *State) printedTabs(items []string) func(tabDirection) (string, error) {
numTabs := 1
prefix := longestCommonPrefix(items)
@@ -190,6 +299,7 @@ func (s *State) printedTabs(items []string) func(tabDirection) (string, error) {
if numTabs == 2 {
if len(items) > 100 {
fmt.Printf("\nDisplay all %d possibilities? (y or n) ", len(items))
+ prompt:
for {
next, err := s.readNext()
if err != nil {
@@ -197,36 +307,26 @@ func (s *State) printedTabs(items []string) func(tabDirection) (string, error) {
}
if key, ok := next.(rune); ok {
- if unicode.ToLower(key) == 'n' {
+ switch key {
+ case 'n', 'N':
return prefix, nil
- } else if unicode.ToLower(key) == 'y' {
- break
+ case 'y', 'Y':
+ break prompt
+ case ctrlC, ctrlD, cr, lf:
+ s.restartPrompt()
}
}
}
}
fmt.Println("")
- maxWidth := 0
- for _, item := range items {
- if len(item) >= maxWidth {
- maxWidth = len(item) + 1
- }
- }
- numColumns := s.columns / maxWidth
- numRows := len(items) / numColumns
- if len(items)%numColumns > 0 {
- numRows++
- }
+ numColumns, numRows, maxWidth := calculateColumns(s.columns, items)
- if len(items) <= numColumns {
- maxWidth = 0
- }
for i := 0; i < numRows; i++ {
for j := 0; j < numColumns*numRows; j += numRows {
if i+j < len(items) {
if maxWidth > 0 {
- fmt.Printf("%-*s", maxWidth, items[i+j])
+ fmt.Printf("%-*.[1]*s", maxWidth, items[i+j])
} else {
fmt.Printf("%v ", items[i+j])
}
@@ -460,26 +560,20 @@ func (s *State) yank(p []rune, text []rune, pos int) ([]rune, int, interface{},
return line, pos, esc, nil
}
-// Prompt displays p, and then waits for user input. Prompt allows line editing
-// if the terminal supports it.
+// Prompt displays p and 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. Prompt allows line editing if the terminal supports it.
func (s *State) Prompt(prompt string) (string, error) {
- if s.inputRedirected {
+ if s.inputRedirected || !s.terminalSupported {
return s.promptUnsupported(prompt)
}
if s.outputRedirected {
return "", ErrNotTerminalOutput
}
- if !s.terminalSupported {
- return s.promptUnsupported(prompt)
- }
s.historyMutex.RLock()
defer s.historyMutex.RUnlock()
- s.startPrompt()
- defer s.stopPrompt()
- s.getColumns()
-
fmt.Print(prompt)
p := []rune(prompt)
var line []rune
@@ -489,11 +583,21 @@ func (s *State) Prompt(prompt string) (string, error) {
historyPos := len(prefixHistory)
historyAction := false // used to mark history related actions
killAction := 0 // used to mark kill related actions
+
+ defer s.stopPrompt()
+
+restart:
+ s.startPrompt()
+ s.getColumns()
+
mainLoop:
for {
next, err := s.readNext()
haveNext:
if err != nil {
+ if s.shouldRestart != nil && s.shouldRestart(err) {
+ goto restart
+ }
return "", err
}
@@ -502,6 +606,9 @@ mainLoop:
case rune:
switch v {
case cr, lf:
+ if s.multiLineMode {
+ s.resetMultiLine(p, line, pos)
+ }
fmt.Println()
break mainLoop
case ctrlA: // Start of line
@@ -603,6 +710,9 @@ mainLoop:
s.refresh(p, line, pos)
case ctrlC: // reset
fmt.Println("^C")
+ if s.multiLineMode {
+ s.resetMultiLine(p, line, pos)
+ }
if s.ctrlCAborts {
return "", ErrPromptAborted
}
@@ -687,7 +797,7 @@ mainLoop:
case 0, 28, 29, 30, 31:
fmt.Print(beep)
default:
- if pos == len(line) && len(p)+len(line) < s.columns-1 {
+ if pos == len(line) && !s.multiLineMode && countGlyphs(p)+countGlyphs(line) < s.columns-1 {
line = append(line, v)
fmt.Printf("%c", v)
pos++
@@ -712,11 +822,21 @@ mainLoop:
} else {
fmt.Print(beep)
}
- case wordLeft:
+ case wordLeft, altB:
if pos > 0 {
+ var spaceHere, spaceLeft, leftKnown bool
for {
pos--
- if pos == 0 || unicode.IsSpace(line[pos-1]) {
+ if pos == 0 {
+ break
+ }
+ if leftKnown {
+ spaceHere = spaceLeft
+ } else {
+ spaceHere = unicode.IsSpace(line[pos])
+ }
+ spaceLeft, leftKnown = unicode.IsSpace(line[pos-1]), true
+ if !spaceHere && spaceLeft {
break
}
}
@@ -729,11 +849,21 @@ mainLoop:
} else {
fmt.Print(beep)
}
- case wordRight:
+ case wordRight, altF:
if pos < len(line) {
+ var spaceHere, spaceLeft, hereKnown bool
for {
pos++
- if pos == len(line) || unicode.IsSpace(line[pos]) {
+ if pos == len(line) {
+ break
+ }
+ if hereKnown {
+ spaceLeft = spaceHere
+ } else {
+ spaceLeft = unicode.IsSpace(line[pos-1])
+ }
+ spaceHere, hereKnown = unicode.IsSpace(line[pos]), true
+ if spaceHere && !spaceLeft {
break
}
}
@@ -769,6 +899,19 @@ mainLoop:
pos = 0
case end: // End of line
pos = len(line)
+ case winch: // Window change
+ if s.multiLineMode {
+ if s.maxRows-s.cursorRows > 0 {
+ s.moveDown(s.maxRows - s.cursorRows)
+ }
+ for i := 0; i < s.maxRows-1; i++ {
+ s.cursorPos(0)
+ s.eraseLine()
+ s.moveUp(1)
+ }
+ s.maxRows = 1
+ s.cursorRows = 1
+ }
}
s.refresh(p, line, pos)
}
@@ -786,18 +929,20 @@ mainLoop:
// PasswordPrompt displays p, and then waits for user input. The input typed by
// the user is not displayed in the terminal.
func (s *State) PasswordPrompt(prompt string) (string, error) {
+ if !s.terminalSupported {
+ return "", errors.New("liner: function not supported in this terminal")
+ }
if s.inputRedirected {
return s.promptUnsupported(prompt)
}
if s.outputRedirected {
return "", ErrNotTerminalOutput
}
- if !s.terminalSupported {
- return "", errors.New("liner: function not supported in this terminal")
- }
- s.startPrompt()
defer s.stopPrompt()
+
+restart:
+ s.startPrompt()
s.getColumns()
fmt.Print(prompt)
@@ -809,6 +954,9 @@ mainLoop:
for {
next, err := s.readNext()
if err != nil {
+ if s.shouldRestart != nil && s.shouldRestart(err) {
+ goto restart
+ }
return "", err
}
@@ -816,6 +964,9 @@ mainLoop:
case rune:
switch v {
case cr, lf:
+ if s.multiLineMode {
+ s.resetMultiLine(p, line, pos)
+ }
fmt.Println()
break mainLoop
case ctrlD: // del
@@ -840,6 +991,9 @@ mainLoop:
}
case ctrlC:
fmt.Println("^C")
+ if s.multiLineMode {
+ s.resetMultiLine(p, line, pos)
+ }
if s.ctrlCAborts {
return "", ErrPromptAborted
}
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/line_test.go b/Godeps/_workspace/src/github.com/peterh/liner/line_test.go
deleted file mode 100644
index 727da6ce7..000000000
--- a/Godeps/_workspace/src/github.com/peterh/liner/line_test.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package liner
-
-import (
- "bytes"
- "strings"
- "testing"
-)
-
-func TestAppend(t *testing.T) {
- var s State
- s.AppendHistory("foo")
- s.AppendHistory("bar")
-
- var out bytes.Buffer
- num, err := s.WriteHistory(&out)
- if err != nil {
- t.Fatal("Unexpected error writing history", err)
- }
- if num != 2 {
- t.Fatalf("Expected 2 history entries, got %d", num)
- }
-
- s.AppendHistory("baz")
- num, err = s.WriteHistory(&out)
- if err != nil {
- t.Fatal("Unexpected error writing history", err)
- }
- if num != 3 {
- t.Fatalf("Expected 3 history entries, got %d", num)
- }
-
- s.AppendHistory("baz")
- num, err = s.WriteHistory(&out)
- if err != nil {
- t.Fatal("Unexpected error writing history", err)
- }
- if num != 3 {
- t.Fatalf("Expected 3 history entries after duplicate append, got %d", num)
- }
-
- s.AppendHistory("baz")
-
-}
-
-func TestHistory(t *testing.T) {
- input := `foo
-bar
-baz
-quux
-dingle`
-
- var s State
- num, err := s.ReadHistory(strings.NewReader(input))
- if err != nil {
- t.Fatal("Unexpected error reading history", err)
- }
- if num != 5 {
- t.Fatal("Wrong number of history entries read")
- }
-
- var out bytes.Buffer
- num, err = s.WriteHistory(&out)
- if err != nil {
- t.Fatal("Unexpected error writing history", err)
- }
- if num != 5 {
- t.Fatal("Wrong number of history entries written")
- }
- if strings.TrimSpace(out.String()) != input {
- t.Fatal("Round-trip failure")
- }
-
- // Test reading with a trailing newline present
- var s2 State
- num, err = s2.ReadHistory(&out)
- if err != nil {
- t.Fatal("Unexpected error reading history the 2nd time", err)
- }
- if num != 5 {
- t.Fatal("Wrong number of history entries read the 2nd time")
- }
-
- num, err = s.ReadHistory(strings.NewReader(input + "\n\xff"))
- if err == nil {
- t.Fatal("Unexpected success reading corrupted history", err)
- }
- if num != 5 {
- t.Fatal("Wrong number of history entries read the 3rd time")
- }
-}
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/output.go b/Godeps/_workspace/src/github.com/peterh/liner/output.go
index e91f4ea81..049273b53 100644
--- a/Godeps/_workspace/src/github.com/peterh/liner/output.go
+++ b/Godeps/_workspace/src/github.com/peterh/liner/output.go
@@ -31,6 +31,18 @@ func (s *State) eraseScreen() {
fmt.Print("\x1b[H\x1b[2J")
}
+func (s *State) moveUp(lines int) {
+ fmt.Printf("\x1b[%dA", lines)
+}
+
+func (s *State) moveDown(lines int) {
+ fmt.Printf("\x1b[%dB", lines)
+}
+
+func (s *State) emitNewLine() {
+ fmt.Print("\n")
+}
+
type winSize struct {
row, col uint16
xpixel, ypixel uint16
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/output_windows.go b/Godeps/_workspace/src/github.com/peterh/liner/output_windows.go
index 27ae55a14..45cd978c9 100644
--- a/Godeps/_workspace/src/github.com/peterh/liner/output_windows.go
+++ b/Godeps/_workspace/src/github.com/peterh/liner/output_windows.go
@@ -47,6 +47,24 @@ func (s *State) eraseScreen() {
procSetConsoleCursorPosition.Call(uintptr(s.hOut), 0)
}
+func (s *State) moveUp(lines int) {
+ var sbi consoleScreenBufferInfo
+ procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi)))
+ procSetConsoleCursorPosition.Call(uintptr(s.hOut),
+ uintptr(int(sbi.dwCursorPosition.x)&0xFFFF|(int(sbi.dwCursorPosition.y)-lines)<<16))
+}
+
+func (s *State) moveDown(lines int) {
+ var sbi consoleScreenBufferInfo
+ procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi)))
+ procSetConsoleCursorPosition.Call(uintptr(s.hOut),
+ uintptr(int(sbi.dwCursorPosition.x)&0xFFFF|(int(sbi.dwCursorPosition.y)+lines)<<16))
+}
+
+func (s *State) emitNewLine() {
+ // windows doesn't need to omit a new line
+}
+
func (s *State) getColumns() {
var sbi consoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(uintptr(s.hOut), uintptr(unsafe.Pointer(&sbi)))
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/prefix_test.go b/Godeps/_workspace/src/github.com/peterh/liner/prefix_test.go
deleted file mode 100644
index c826d6c3b..000000000
--- a/Godeps/_workspace/src/github.com/peterh/liner/prefix_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// +build windows linux darwin openbsd freebsd netbsd
-
-package liner
-
-import "testing"
-
-type testItem struct {
- list []string
- prefix string
-}
-
-func TestPrefix(t *testing.T) {
- list := []testItem{
- {[]string{"food", "foot"}, "foo"},
- {[]string{"foo", "foot"}, "foo"},
- {[]string{"food", "foo"}, "foo"},
- {[]string{"food", "foe", "foot"}, "fo"},
- {[]string{"food", "foot", "barbeque"}, ""},
- {[]string{"cafeteria", "café"}, "caf"},
- {[]string{"cafe", "café"}, "caf"},
- {[]string{"cafè", "café"}, "caf"},
- {[]string{"cafés", "café"}, "café"},
- {[]string{"áéíóú", "áéíóú"}, "áéíóú"},
- {[]string{"éclairs", "éclairs"}, "éclairs"},
- {[]string{"éclairs are the best", "éclairs are great", "éclairs"}, "éclairs"},
- {[]string{"éclair", "éclairs"}, "éclair"},
- {[]string{"éclairs", "éclair"}, "éclair"},
- {[]string{"éclair", "élan"}, "é"},
- }
-
- for _, test := range list {
- lcp := longestCommonPrefix(test.list)
- if lcp != test.prefix {
- t.Errorf("%s != %s for %+v", lcp, test.prefix, test.list)
- }
- }
-}
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/race_test.go b/Godeps/_workspace/src/github.com/peterh/liner/race_test.go
deleted file mode 100644
index e320849c7..000000000
--- a/Godeps/_workspace/src/github.com/peterh/liner/race_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// +build race
-
-package liner
-
-import (
- "io/ioutil"
- "os"
- "sync"
- "testing"
-)
-
-func TestWriteHistory(t *testing.T) {
- oldout := os.Stdout
- defer func() { os.Stdout = oldout }()
- oldin := os.Stdout
- defer func() { os.Stdin = oldin }()
-
- newinr, newinw, err := os.Pipe()
- if err != nil {
- t.Fatal(err)
- }
- os.Stdin = newinr
- newoutr, newoutw, err := os.Pipe()
- if err != nil {
- t.Fatal(err)
- }
- defer newoutr.Close()
- os.Stdout = newoutw
-
- var wait sync.WaitGroup
- wait.Add(1)
- s := NewLiner()
- go func() {
- s.AppendHistory("foo")
- s.AppendHistory("bar")
- s.Prompt("")
- wait.Done()
- }()
-
- s.WriteHistory(ioutil.Discard)
-
- newinw.Close()
- wait.Wait()
-}
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/width.go b/Godeps/_workspace/src/github.com/peterh/liner/width.go
index 02cfb5e1b..d8984aae9 100644
--- a/Godeps/_workspace/src/github.com/peterh/liner/width.go
+++ b/Godeps/_workspace/src/github.com/peterh/liner/width.go
@@ -13,10 +13,42 @@ 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 {
n := 0
for _, r := range s {
- if !unicode.IsOneOf(zeroWidth, r) {
+ switch {
+ case unicode.IsOneOf(zeroWidth, r):
+ case unicode.IsOneOf(doubleWidth, r):
+ n += 2
+ default:
+ n++
+ }
+ }
+ return n
+}
+
+func countMultiLineGlyphs(s []rune, columns int, start int) int {
+ n := start
+ for _, r := range s {
+ switch {
+ case unicode.IsOneOf(zeroWidth, r):
+ case unicode.IsOneOf(doubleWidth, r):
+ 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++
}
}
diff --git a/Godeps/_workspace/src/github.com/peterh/liner/width_test.go b/Godeps/_workspace/src/github.com/peterh/liner/width_test.go
deleted file mode 100644
index 134920a4b..000000000
--- a/Godeps/_workspace/src/github.com/peterh/liner/width_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package liner
-
-import (
- "strconv"
- "testing"
-)
-
-func accent(in []rune) []rune {
- var out []rune
- for _, r := range in {
- out = append(out, r)
- out = append(out, '\u0301')
- }
- return out
-}
-
-var testString = []rune("query")
-
-func TestCountGlyphs(t *testing.T) {
- count := countGlyphs(testString)
- if count != len(testString) {
- t.Errorf("ASCII count incorrect. %d != %d", count, len(testString))
- }
- count = countGlyphs(accent(testString))
- if count != len(testString) {
- t.Errorf("Accent count incorrect. %d != %d", count, len(testString))
- }
-}
-
-func compare(a, b []rune, name string, t *testing.T) {
- if len(a) != len(b) {
- t.Errorf(`"%s" != "%s" in %s"`, string(a), string(b), name)
- return
- }
- for i := range a {
- if a[i] != b[i] {
- t.Errorf(`"%s" != "%s" in %s"`, string(a), string(b), name)
- return
- }
- }
-}
-
-func TestPrefixGlyphs(t *testing.T) {
- for i := 0; i <= len(testString); i++ {
- iter := strconv.Itoa(i)
- out := getPrefixGlyphs(testString, i)
- compare(out, testString[:i], "ascii prefix "+iter, t)
- out = getPrefixGlyphs(accent(testString), i)
- compare(out, accent(testString[:i]), "accent prefix "+iter, t)
- }
- out := getPrefixGlyphs(testString, 999)
- compare(out, testString, "ascii prefix overflow", t)
- out = getPrefixGlyphs(accent(testString), 999)
- compare(out, accent(testString), "accent prefix overflow", t)
-
- out = getPrefixGlyphs(testString, -3)
- if len(out) != 0 {
- t.Error("ascii prefix negative")
- }
- out = getPrefixGlyphs(accent(testString), -3)
- if len(out) != 0 {
- t.Error("accent prefix negative")
- }
-}
-
-func TestSuffixGlyphs(t *testing.T) {
- for i := 0; i <= len(testString); i++ {
- iter := strconv.Itoa(i)
- out := getSuffixGlyphs(testString, i)
- compare(out, testString[len(testString)-i:], "ascii suffix "+iter, t)
- out = getSuffixGlyphs(accent(testString), i)
- compare(out, accent(testString[len(testString)-i:]), "accent suffix "+iter, t)
- }
- out := getSuffixGlyphs(testString, 999)
- compare(out, testString, "ascii suffix overflow", t)
- out = getSuffixGlyphs(accent(testString), 999)
- compare(out, accent(testString), "accent suffix overflow", t)
-
- out = getSuffixGlyphs(testString, -3)
- if len(out) != 0 {
- t.Error("ascii suffix negative")
- }
- out = getSuffixGlyphs(accent(testString), -3)
- if len(out) != 0 {
- t.Error("accent suffix negative")
- }
-}