Don't quit ioloop on NUL
character (#940)
* dont quit ioloop on 0 rune * check for closed channel * remove unused error on `Close()`
This commit is contained in:
parent
c0dcea1398
commit
4748609611
4 changed files with 38 additions and 37 deletions
|
@ -45,7 +45,7 @@ func (b *Buffer) MoveLeft() {
|
||||||
if b.Pos%b.LineWidth == 0 {
|
if b.Pos%b.LineWidth == 0 {
|
||||||
fmt.Printf(CursorUp + CursorBOL + cursorRightN(b.Width))
|
fmt.Printf(CursorUp + CursorBOL + cursorRightN(b.Width))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(CursorLeft)
|
fmt.Print(CursorLeft)
|
||||||
}
|
}
|
||||||
b.Pos -= 1
|
b.Pos -= 1
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ func (b *Buffer) MoveRight() {
|
||||||
if b.Pos%b.LineWidth == 0 {
|
if b.Pos%b.LineWidth == 0 {
|
||||||
fmt.Printf(CursorDown + CursorBOL + cursorRightN(b.PromptSize()))
|
fmt.Printf(CursorDown + CursorBOL + cursorRightN(b.PromptSize()))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(CursorRight)
|
fmt.Print(CursorRight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ func (b *Buffer) MoveToStart() {
|
||||||
currLine := b.Pos / b.LineWidth
|
currLine := b.Pos / b.LineWidth
|
||||||
if currLine > 0 {
|
if currLine > 0 {
|
||||||
for cnt := 0; cnt < currLine; cnt++ {
|
for cnt := 0; cnt < currLine; cnt++ {
|
||||||
fmt.Printf(CursorUp)
|
fmt.Print(CursorUp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Printf(CursorBOL + cursorRightN(b.PromptSize()))
|
fmt.Printf(CursorBOL + cursorRightN(b.PromptSize()))
|
||||||
|
@ -118,12 +118,12 @@ func (b *Buffer) MoveToEnd() {
|
||||||
totalLines := b.Size() / b.LineWidth
|
totalLines := b.Size() / b.LineWidth
|
||||||
if currLine < totalLines {
|
if currLine < totalLines {
|
||||||
for cnt := 0; cnt < totalLines-currLine; cnt++ {
|
for cnt := 0; cnt < totalLines-currLine; cnt++ {
|
||||||
fmt.Printf(CursorDown)
|
fmt.Print(CursorDown)
|
||||||
}
|
}
|
||||||
remainder := b.Size() % b.LineWidth
|
remainder := b.Size() % b.LineWidth
|
||||||
fmt.Printf(CursorBOL + cursorRightN(b.PromptSize()+remainder))
|
fmt.Printf(CursorBOL + cursorRightN(b.PromptSize()+remainder))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(cursorRightN(b.Size() - b.Pos))
|
fmt.Print(cursorRightN(b.Size() - b.Pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Pos = b.Size()
|
b.Pos = b.Size()
|
||||||
|
@ -173,15 +173,15 @@ func (b *Buffer) drawRemaining() {
|
||||||
if b.Pos > 0 {
|
if b.Pos > 0 {
|
||||||
place = b.Pos % b.LineWidth
|
place = b.Pos % b.LineWidth
|
||||||
}
|
}
|
||||||
fmt.Printf(CursorHide)
|
fmt.Print(CursorHide)
|
||||||
|
|
||||||
// render the rest of the current line
|
// render the rest of the current line
|
||||||
currLine := remainingText[:min(b.LineWidth-place, len(remainingText))]
|
currLine := remainingText[:min(b.LineWidth-place, len(remainingText))]
|
||||||
if len(currLine) > 0 {
|
if len(currLine) > 0 {
|
||||||
fmt.Printf(ClearToEOL + currLine)
|
fmt.Printf(ClearToEOL + currLine)
|
||||||
fmt.Printf(cursorLeftN(len(currLine)))
|
fmt.Print(cursorLeftN(len(currLine)))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(ClearToEOL)
|
fmt.Print(ClearToEOL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// render the other lines
|
// render the other lines
|
||||||
|
@ -195,12 +195,12 @@ func (b *Buffer) drawRemaining() {
|
||||||
}
|
}
|
||||||
fmt.Printf("%c", c)
|
fmt.Printf("%c", c)
|
||||||
}
|
}
|
||||||
fmt.Printf(ClearToEOL)
|
fmt.Print(ClearToEOL)
|
||||||
fmt.Printf(cursorUpN(totalLines))
|
fmt.Print(cursorUpN(totalLines))
|
||||||
fmt.Printf(CursorBOL + cursorRightN(b.Width-len(currLine)))
|
fmt.Printf(CursorBOL + cursorRightN(b.Width-len(currLine)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf(CursorShow)
|
fmt.Print(CursorShow)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Buffer) Remove() {
|
func (b *Buffer) Remove() {
|
||||||
|
@ -305,12 +305,12 @@ func (b *Buffer) ClearScreen() {
|
||||||
targetLine := currPos / b.LineWidth
|
targetLine := currPos / b.LineWidth
|
||||||
if targetLine > 0 {
|
if targetLine > 0 {
|
||||||
for cnt := 0; cnt < targetLine; cnt++ {
|
for cnt := 0; cnt < targetLine; cnt++ {
|
||||||
fmt.Printf(CursorDown)
|
fmt.Print(CursorDown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
remainder := currPos % b.LineWidth
|
remainder := currPos % b.LineWidth
|
||||||
if remainder > 0 {
|
if remainder > 0 {
|
||||||
fmt.Printf(cursorRightN(remainder))
|
fmt.Print(cursorRightN(remainder))
|
||||||
}
|
}
|
||||||
if currPos%b.LineWidth == 0 {
|
if currPos%b.LineWidth == 0 {
|
||||||
fmt.Printf(CursorBOL + b.Prompt.AltPrompt)
|
fmt.Printf(CursorBOL + b.Prompt.AltPrompt)
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,8 +17,6 @@ type Prompt struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Terminal struct {
|
type Terminal struct {
|
||||||
m sync.Mutex
|
|
||||||
wg sync.WaitGroup
|
|
||||||
outchan chan rune
|
outchan chan rune
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +49,7 @@ func (i *Instance) Readline() (string, error) {
|
||||||
if i.Prompt.UseAlt {
|
if i.Prompt.UseAlt {
|
||||||
prompt = i.Prompt.AltPrompt
|
prompt = i.Prompt.AltPrompt
|
||||||
}
|
}
|
||||||
fmt.Printf(prompt)
|
fmt.Print(prompt)
|
||||||
|
|
||||||
termios, err := SetRawMode(syscall.Stdin)
|
termios, err := SetRawMode(syscall.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -78,13 +75,13 @@ func (i *Instance) Readline() (string, error) {
|
||||||
fmt.Printf(ColorGrey + ph + fmt.Sprintf(CursorLeftN, len(ph)) + ColorDefault)
|
fmt.Printf(ColorGrey + ph + fmt.Sprintf(CursorLeftN, len(ph)) + ColorDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := i.Terminal.ReadRune()
|
r, err := i.Terminal.Read()
|
||||||
if buf.IsEmpty() {
|
if err != nil {
|
||||||
fmt.Printf(ClearToEOL)
|
return "", io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
if r == 0 { // io.EOF
|
if buf.IsEmpty() {
|
||||||
break
|
fmt.Print(ClearToEOL)
|
||||||
}
|
}
|
||||||
|
|
||||||
if escex {
|
if escex {
|
||||||
|
@ -112,7 +109,11 @@ func (i *Instance) Readline() (string, error) {
|
||||||
case CharBracketedPaste:
|
case CharBracketedPaste:
|
||||||
var code string
|
var code string
|
||||||
for cnt := 0; cnt < 3; cnt++ {
|
for cnt := 0; cnt < 3; cnt++ {
|
||||||
r = i.Terminal.ReadRune()
|
r, err = i.Terminal.Read()
|
||||||
|
if err != nil {
|
||||||
|
return "", io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
code += string(r)
|
code += string(r)
|
||||||
}
|
}
|
||||||
if code == CharBracketedPasteStart {
|
if code == CharBracketedPasteStart {
|
||||||
|
@ -149,6 +150,8 @@ func (i *Instance) Readline() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r {
|
switch r {
|
||||||
|
case CharNull:
|
||||||
|
continue
|
||||||
case CharEsc:
|
case CharEsc:
|
||||||
esc = true
|
esc = true
|
||||||
case CharInterrupt:
|
case CharInterrupt:
|
||||||
|
@ -206,11 +209,10 @@ func (i *Instance) Readline() (string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) Close() error {
|
func (i *Instance) Close() {
|
||||||
return i.Terminal.Close()
|
i.Terminal.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) HistoryEnable() {
|
func (i *Instance) HistoryEnable() {
|
||||||
|
@ -240,22 +242,18 @@ func (t *Terminal) ioloop() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
t.outchan <- r
|
t.outchan <- r
|
||||||
if r == 0 { // EOF
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) ReadRune() rune {
|
func (t *Terminal) Read() (rune, error) {
|
||||||
r, ok := <-t.outchan
|
r, ok := <-t.outchan
|
||||||
if !ok {
|
if !ok {
|
||||||
return rune(0)
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
return r
|
|
||||||
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) Close() error {
|
func (t *Terminal) Close() {
|
||||||
close(t.outchan)
|
close(t.outchan)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
//go:build aix || darwin || dragonfly || freebsd || (linux && !appengine) || netbsd || openbsd || os400 || solaris
|
||||||
// +build aix darwin dragonfly freebsd linux,!appengine netbsd openbsd os400 solaris
|
// +build aix darwin dragonfly freebsd linux,!appengine netbsd openbsd os400 solaris
|
||||||
|
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
CharNull = 0
|
||||||
CharLineStart = 1
|
CharLineStart = 1
|
||||||
CharBackward = 2
|
CharBackward = 2
|
||||||
CharInterrupt = 3
|
CharInterrupt = 3
|
||||||
|
|
Loading…
Reference in a new issue