mirror of https://github.com/chzyer/readline.git
Update Prompt type form string to fmt.Stringer.
On branch master Your branch is up to date with 'origin/master'. Changes to be committed: modified: example/readline-demo/readline-demo.go modified: example/readline-im/readline-im.go modified: example/readline-multiline/readline-multiline.go modified: example/readline-pass-strength/readline-pass-strength.go modified: example/readline-remote/readline-remote-server/server.go modified: operation.go new file: prompt.go modified: readline.go modified: runebuf.go modified: std.go
This commit is contained in:
parent
2972be24d4
commit
ee7dbdffca
|
@ -72,7 +72,7 @@ func filterInput(r rune) (rune, bool) {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
l, err := readline.NewEx(&readline.Config{
|
l, err := readline.NewEx(&readline.Config{
|
||||||
Prompt: "\033[31m»\033[0m ",
|
Prompt: readline.StaticPrompt("\033[31m»\033[0m "),
|
||||||
HistoryFile: "/tmp/readline.tmp",
|
HistoryFile: "/tmp/readline.tmp",
|
||||||
AutoComplete: completer,
|
AutoComplete: completer,
|
||||||
InterruptPrompt: "^C",
|
InterruptPrompt: "^C",
|
||||||
|
@ -88,7 +88,7 @@ func main() {
|
||||||
|
|
||||||
setPasswordCfg := l.GenPasswordConfig()
|
setPasswordCfg := l.GenPasswordConfig()
|
||||||
setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
|
setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
|
||||||
l.SetPrompt(fmt.Sprintf("Enter password(%v): ", len(line)))
|
l.SetPrompt(readline.StaticPrompt(fmt.Sprintf("Enter password(%v): ", len(line))))
|
||||||
l.Refresh()
|
l.Refresh()
|
||||||
return nil, 0, false
|
return nil, 0, false
|
||||||
})
|
})
|
||||||
|
@ -124,7 +124,7 @@ func main() {
|
||||||
println("current mode: emacs")
|
println("current mode: emacs")
|
||||||
}
|
}
|
||||||
case line == "login":
|
case line == "login":
|
||||||
pswd, err := l.ReadPassword("please enter your password: ")
|
pswd, err := l.ReadPassword(readline.StaticPrompt("please enter your password: "))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ func main() {
|
||||||
log.Println("setprompt <prompt>")
|
log.Println("setprompt <prompt>")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
l.SetPrompt(line[10:])
|
l.SetPrompt(readline.StaticPrompt(line[10:]))
|
||||||
case strings.HasPrefix(line, "say"):
|
case strings.HasPrefix(line, "say"):
|
||||||
line := strings.TrimSpace(line[3:])
|
line := strings.TrimSpace(line[3:])
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
|
|
|
@ -18,7 +18,7 @@ func main() {
|
||||||
}
|
}
|
||||||
defer rl.Close()
|
defer rl.Close()
|
||||||
|
|
||||||
rl.SetPrompt("username: ")
|
rl.SetPrompt(readline.StaticPrompt("username: "))
|
||||||
username, err := rl.Readline()
|
username, err := rl.Readline()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -27,7 +27,7 @@ func main() {
|
||||||
log.SetOutput(rl.Stderr())
|
log.SetOutput(rl.Stderr())
|
||||||
|
|
||||||
fmt.Fprintln(rl, "Hi,", username+"! My name is Dave.")
|
fmt.Fprintln(rl, "Hi,", username+"! My name is Dave.")
|
||||||
rl.SetPrompt(username + "> ")
|
rl.SetPrompt(readline.StaticPrompt(username + "> "))
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
rl, err := readline.NewEx(&readline.Config{
|
rl, err := readline.NewEx(&readline.Config{
|
||||||
Prompt: "> ",
|
Prompt: readline.StaticPrompt("> "),
|
||||||
HistoryFile: "/tmp/readline-multiline",
|
HistoryFile: "/tmp/readline-multiline",
|
||||||
DisableAutoSaveHistory: true,
|
DisableAutoSaveHistory: true,
|
||||||
})
|
})
|
||||||
|
@ -29,12 +29,12 @@ func main() {
|
||||||
}
|
}
|
||||||
cmds = append(cmds, line)
|
cmds = append(cmds, line)
|
||||||
if !strings.HasSuffix(line, ";") {
|
if !strings.HasSuffix(line, ";") {
|
||||||
rl.SetPrompt(">>> ")
|
rl.SetPrompt(readline.StaticPrompt(">>> "))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cmd := strings.Join(cmds, " ")
|
cmd := strings.Join(cmds, " ")
|
||||||
cmds = cmds[:0]
|
cmds = cmds[:0]
|
||||||
rl.SetPrompt("> ")
|
rl.SetPrompt(readline.StaticPrompt("> "))
|
||||||
rl.SaveHistory(cmd)
|
rl.SaveHistory(cmd)
|
||||||
println(cmd)
|
println(cmd)
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ func createStrengthPrompt(password []rune) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
rl, err := readline.New("")
|
rl, err := readline.New(readline.StaticPrompt(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ func main() {
|
||||||
|
|
||||||
setPasswordCfg := rl.GenPasswordConfig()
|
setPasswordCfg := rl.GenPasswordConfig()
|
||||||
setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
|
setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
|
||||||
rl.SetPrompt(createStrengthPrompt(line))
|
rl.SetPrompt(readline.StaticPrompt(createStrengthPrompt(line)))
|
||||||
rl.Refresh()
|
rl.Refresh()
|
||||||
return nil, 0, false
|
return nil, 0, false
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfg := &readline.Config{
|
cfg := &readline.Config{
|
||||||
Prompt: "readline-remote: ",
|
Prompt: readline.StaticPrompt("readline-remote: "),
|
||||||
}
|
}
|
||||||
handleFunc := func(rl *readline.Instance) {
|
handleFunc := func(rl *readline.Instance) {
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
@ -89,7 +90,7 @@ func NewOperation(t *Terminal, cfg *Config) *Operation {
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) SetPrompt(s string) {
|
func (o *Operation) SetPrompt(s fmt.Stringer) {
|
||||||
o.buf.SetPrompt(s)
|
o.buf.SetPrompt(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +399,7 @@ func (o *Operation) Runes() ([]rune, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) PasswordEx(prompt string, l Listener) ([]byte, error) {
|
func (o *Operation) PasswordEx(prompt fmt.Stringer, l Listener) ([]byte, error) {
|
||||||
cfg := o.GenPasswordConfig()
|
cfg := o.GenPasswordConfig()
|
||||||
cfg.Prompt = prompt
|
cfg.Prompt = prompt
|
||||||
cfg.Listener = l
|
cfg.Listener = l
|
||||||
|
@ -417,7 +418,7 @@ func (o *Operation) PasswordWithConfig(cfg *Config) ([]byte, error) {
|
||||||
return o.Slice()
|
return o.Slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) Password(prompt string) ([]byte, error) {
|
func (o *Operation) Password(prompt fmt.Stringer) ([]byte, error) {
|
||||||
return o.PasswordEx(prompt, nil)
|
return o.PasswordEx(prompt, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package readline
|
||||||
|
|
||||||
|
type StaticPrompt string
|
||||||
|
|
||||||
|
func (s StaticPrompt) String() string {
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStaticPrompt(s string) StaticPrompt {
|
||||||
|
return StaticPrompt(s)
|
||||||
|
}
|
19
readline.go
19
readline.go
|
@ -17,7 +17,10 @@
|
||||||
//
|
//
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import "io"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
Config *Config
|
Config *Config
|
||||||
|
@ -27,7 +30,7 @@ type Instance struct {
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// prompt supports ANSI escape sequence, so we can color some characters even in windows
|
// prompt supports ANSI escape sequence, so we can color some characters even in windows
|
||||||
Prompt string
|
Prompt fmt.Stringer
|
||||||
|
|
||||||
// readline will persist historys to file where HistoryFile specified
|
// readline will persist historys to file where HistoryFile specified
|
||||||
HistoryFile string
|
HistoryFile string
|
||||||
|
@ -175,7 +178,11 @@ func NewEx(cfg *Config) (*Instance, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(prompt string) (*Instance, error) {
|
type Prompter interface {
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(prompt fmt.Stringer) (*Instance, error) {
|
||||||
return NewEx(&Config{Prompt: prompt})
|
return NewEx(&Config{Prompt: prompt})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +190,7 @@ func (i *Instance) ResetHistory() {
|
||||||
i.Operation.ResetHistory()
|
i.Operation.ResetHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) SetPrompt(s string) {
|
func (i *Instance) SetPrompt(s fmt.Stringer) {
|
||||||
i.Operation.SetPrompt(s)
|
i.Operation.SetPrompt(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,11 +231,11 @@ func (i *Instance) ReadPasswordWithConfig(cfg *Config) ([]byte, error) {
|
||||||
return i.Operation.PasswordWithConfig(cfg)
|
return i.Operation.PasswordWithConfig(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) ReadPasswordEx(prompt string, l Listener) ([]byte, error) {
|
func (i *Instance) ReadPasswordEx(prompt fmt.Stringer, l Listener) ([]byte, error) {
|
||||||
return i.Operation.PasswordEx(prompt, l)
|
return i.Operation.PasswordEx(prompt, l)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) ReadPassword(prompt string) ([]byte, error) {
|
func (i *Instance) ReadPassword(prompt fmt.Stringer) ([]byte, error) {
|
||||||
return i.Operation.Password(prompt)
|
return i.Operation.Password(prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
runebuf.go
19
runebuf.go
|
@ -3,6 +3,7 @@ package readline
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -17,7 +18,7 @@ type runeBufferBck struct {
|
||||||
type RuneBuffer struct {
|
type RuneBuffer struct {
|
||||||
buf []rune
|
buf []rune
|
||||||
idx int
|
idx int
|
||||||
prompt []rune
|
prompt fmt.Stringer
|
||||||
w io.Writer
|
w io.Writer
|
||||||
|
|
||||||
hadClean bool
|
hadClean bool
|
||||||
|
@ -35,7 +36,7 @@ type RuneBuffer struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r* RuneBuffer) pushKill(text []rune) {
|
func (r *RuneBuffer) pushKill(text []rune) {
|
||||||
r.lastKill = append([]rune{}, text...)
|
r.lastKill = append([]rune{}, text...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ func (r *RuneBuffer) Restore() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRuneBuffer(w io.Writer, prompt string, cfg *Config, width int) *RuneBuffer {
|
func NewRuneBuffer(w io.Writer, prompt fmt.Stringer, cfg *Config, width int) *RuneBuffer {
|
||||||
rb := &RuneBuffer{
|
rb := &RuneBuffer{
|
||||||
w: w,
|
w: w,
|
||||||
interactive: cfg.useInteractive(),
|
interactive: cfg.useInteractive(),
|
||||||
|
@ -99,7 +100,7 @@ func (r *RuneBuffer) PromptLen() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RuneBuffer) promptLen() int {
|
func (r *RuneBuffer) promptLen() int {
|
||||||
return runes.WidthAll(runes.ColorFilter(r.prompt))
|
return runes.WidthAll(runes.ColorFilter([]rune(r.prompt.String())))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RuneBuffer) RuneSlice(i int) []rune {
|
func (r *RuneBuffer) RuneSlice(i int) []rune {
|
||||||
|
@ -221,7 +222,7 @@ func (r *RuneBuffer) DeleteWord() {
|
||||||
}
|
}
|
||||||
for i := init + 1; i < len(r.buf); i++ {
|
for i := init + 1; i < len(r.buf); i++ {
|
||||||
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
|
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
|
||||||
r.pushKill(r.buf[r.idx:i-1])
|
r.pushKill(r.buf[r.idx : i-1])
|
||||||
r.Refresh(func() {
|
r.Refresh(func() {
|
||||||
r.buf = append(r.buf[:r.idx], r.buf[i-1:]...)
|
r.buf = append(r.buf[:r.idx], r.buf[i-1:]...)
|
||||||
})
|
})
|
||||||
|
@ -350,7 +351,7 @@ func (r *RuneBuffer) Yank() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.Refresh(func() {
|
r.Refresh(func() {
|
||||||
buf := make([]rune, 0, len(r.buf) + len(r.lastKill))
|
buf := make([]rune, 0, len(r.buf)+len(r.lastKill))
|
||||||
buf = append(buf, r.buf[:r.idx]...)
|
buf = append(buf, r.buf[:r.idx]...)
|
||||||
buf = append(buf, r.lastKill...)
|
buf = append(buf, r.lastKill...)
|
||||||
buf = append(buf, r.buf[r.idx:]...)
|
buf = append(buf, r.buf[r.idx:]...)
|
||||||
|
@ -478,7 +479,7 @@ func (r *RuneBuffer) print() {
|
||||||
|
|
||||||
func (r *RuneBuffer) output() []byte {
|
func (r *RuneBuffer) output() []byte {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
buf.WriteString(string(r.prompt))
|
buf.WriteString(r.prompt.String())
|
||||||
if r.cfg.EnableMask && len(r.buf) > 0 {
|
if r.cfg.EnableMask && len(r.buf) > 0 {
|
||||||
buf.Write([]byte(strings.Repeat(string(r.cfg.MaskRune), len(r.buf)-1)))
|
buf.Write([]byte(strings.Repeat(string(r.cfg.MaskRune), len(r.buf)-1)))
|
||||||
if r.buf[len(r.buf)-1] == '\n' {
|
if r.buf[len(r.buf)-1] == '\n' {
|
||||||
|
@ -582,9 +583,9 @@ func (r *RuneBuffer) Set(buf []rune) {
|
||||||
r.SetWithIdx(len(buf), buf)
|
r.SetWithIdx(len(buf), buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RuneBuffer) SetPrompt(prompt string) {
|
func (r *RuneBuffer) SetPrompt(prompt fmt.Stringer) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
r.prompt = []rune(prompt)
|
r.prompt = prompt //[]rune(prompt)
|
||||||
r.Unlock()
|
r.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
std.go
5
std.go
|
@ -1,6 +1,7 @@
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -54,13 +55,13 @@ func AddHistory(content string) error {
|
||||||
return ins.SaveHistory(content)
|
return ins.SaveHistory(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Password(prompt string) ([]byte, error) {
|
func Password(prompt fmt.Stringer) ([]byte, error) {
|
||||||
ins := getInstance()
|
ins := getInstance()
|
||||||
return ins.ReadPassword(prompt)
|
return ins.ReadPassword(prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// readline with global configs
|
// readline with global configs
|
||||||
func Line(prompt string) (string, error) {
|
func Line(prompt fmt.Stringer) (string, error) {
|
||||||
ins := getInstance()
|
ins := getInstance()
|
||||||
ins.SetPrompt(prompt)
|
ins.SetPrompt(prompt)
|
||||||
return ins.Readline()
|
return ins.Readline()
|
||||||
|
|
Loading…
Reference in New Issue