mirror of https://github.com/chzyer/readline.git
treat `Ctrl+D` + EmptyLine = EOF, `Ctrl+C` = ErrInterrupt
This commit is contained in:
parent
9364259fb1
commit
7a18498f5b
38
operation.go
38
operation.go
|
@ -1,6 +1,7 @@
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -8,11 +9,16 @@ import (
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInterrupt = errors.New("Interrupt")
|
||||||
|
)
|
||||||
|
|
||||||
type Operation struct {
|
type Operation struct {
|
||||||
cfg *Config
|
cfg *Config
|
||||||
t *Terminal
|
t *Terminal
|
||||||
buf *RuneBuffer
|
buf *RuneBuffer
|
||||||
outchan chan []rune
|
outchan chan []rune
|
||||||
|
errchan chan error
|
||||||
w io.Writer
|
w io.Writer
|
||||||
|
|
||||||
*opHistory
|
*opHistory
|
||||||
|
@ -55,6 +61,7 @@ func NewOperation(t *Terminal, cfg *Config) *Operation {
|
||||||
t: t,
|
t: t,
|
||||||
buf: NewRuneBuffer(t, cfg.Prompt),
|
buf: NewRuneBuffer(t, cfg.Prompt),
|
||||||
outchan: make(chan []rune),
|
outchan: make(chan []rune),
|
||||||
|
errchan: make(chan error),
|
||||||
}
|
}
|
||||||
op.SetHistoryPath(cfg.HistoryFile)
|
op.SetHistoryPath(cfg.HistoryFile)
|
||||||
op.opVim = newVimMode(op)
|
op.opVim = newVimMode(op)
|
||||||
|
@ -141,10 +148,6 @@ func (o *Operation) ioloop() {
|
||||||
o.buf.MoveToLineStart()
|
o.buf.MoveToLineStart()
|
||||||
case CharLineEnd:
|
case CharLineEnd:
|
||||||
o.buf.MoveToLineEnd()
|
o.buf.MoveToLineEnd()
|
||||||
case CharDelete:
|
|
||||||
if !o.buf.Delete() {
|
|
||||||
o.t.Bell()
|
|
||||||
}
|
|
||||||
case CharBackspace, CharCtrlH:
|
case CharBackspace, CharCtrlH:
|
||||||
if o.IsSearchMode() {
|
if o.IsSearchMode() {
|
||||||
o.SearchBackspace()
|
o.SearchBackspace()
|
||||||
|
@ -190,6 +193,18 @@ func (o *Operation) ioloop() {
|
||||||
} else {
|
} else {
|
||||||
o.t.Bell()
|
o.t.Bell()
|
||||||
}
|
}
|
||||||
|
case CharDelete:
|
||||||
|
if o.buf.Len() > 0 || !o.IsNormalMode() {
|
||||||
|
o.t.KickRead()
|
||||||
|
if !o.buf.Delete() {
|
||||||
|
o.t.Bell()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// treat as EOF
|
||||||
|
o.buf.WriteString("^D\n")
|
||||||
|
o.errchan <- io.EOF
|
||||||
case CharInterrupt:
|
case CharInterrupt:
|
||||||
if o.IsSearchMode() {
|
if o.IsSearchMode() {
|
||||||
o.t.KickRead()
|
o.t.KickRead()
|
||||||
|
@ -205,7 +220,7 @@ func (o *Operation) ioloop() {
|
||||||
o.buf.MoveToLineEnd()
|
o.buf.MoveToLineEnd()
|
||||||
o.buf.Refresh(nil)
|
o.buf.Refresh(nil)
|
||||||
o.buf.WriteString("^C\n")
|
o.buf.WriteString("^C\n")
|
||||||
o.outchan <- nil
|
o.errchan <- ErrInterrupt
|
||||||
default:
|
default:
|
||||||
if o.IsSearchMode() {
|
if o.IsSearchMode() {
|
||||||
o.SearchChar(r)
|
o.SearchChar(r)
|
||||||
|
@ -259,11 +274,12 @@ func (o *Operation) Runes() ([]rune, error) {
|
||||||
|
|
||||||
o.buf.Refresh(nil) // print prompt
|
o.buf.Refresh(nil) // print prompt
|
||||||
o.t.KickRead()
|
o.t.KickRead()
|
||||||
r := <-o.outchan
|
select {
|
||||||
if r == nil {
|
case r := <-o.outchan:
|
||||||
return nil, io.EOF
|
|
||||||
}
|
|
||||||
return r, nil
|
return r, nil
|
||||||
|
case err := <-o.errchan:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) Password(prompt string) ([]byte, error) {
|
func (o *Operation) Password(prompt string) ([]byte, error) {
|
||||||
|
@ -302,3 +318,7 @@ func (o *Operation) SetHistoryPath(path string) {
|
||||||
o.cfg.HistoryFile = path
|
o.cfg.HistoryFile = path
|
||||||
o.opHistory = newOpHistory(o.cfg)
|
o.opHistory = newOpHistory(o.cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Operation) IsNormalMode() bool {
|
||||||
|
return !o.IsInCompleteMode() && !o.IsSearchMode()
|
||||||
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ func (t *Terminal) ioloop() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
isEscape = true
|
isEscape = true
|
||||||
case CharInterrupt, CharEnter, CharCtrlJ:
|
case CharInterrupt, CharEnter, CharCtrlJ, CharDelete:
|
||||||
expectNextChar = false
|
expectNextChar = false
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue