readline

package module
v0.0.0-...-44ccc71 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 27, 2016 License: MIT Imports: 17 Imported by: 0

README

readline

Software License Build Status GoDoc Gitter

Readline is A Pure Go Implementation of a libreadline-style Library.
The goal is to be a powerful alternater for GNU-Readline.

WHY: Readline will support most of features which GNU Readline is supported, and provide a pure go environment and a MIT license.

It can also provides shell-like interactives by using flagly (demo: flagly-shell)

Demo

demo

Also works fine in windows

demo windows

Todo

  • Vi Mode is not completely finish
  • More funny examples
  • Support dumb/eterm-color terminal in emacs

Features

  • Support emacs/vi mode, almost all basic features that GNU-Readline is supported
  • zsh-style backward/forward history search
  • zsh-style completion
  • Readline auto refresh when others write to Stdout while editing (it needs specify the Stdout/Stderr provided by *readline.Instance to others).
  • Support colourful prompt in all platforms.

Usage

  • Import package
go get gopkg.in/readline.v1

or

go get github.com/chzyer/readline
  • Simplest example
import "gopkg.in/readline.v1"

rl, err := readline.New("> ")
if err != nil {
	panic(err)
}
defer rl.Close()

for {
	line, err := rl.Readline()
	if err != nil { // io.EOF, readline.ErrInterrupt
		break
	}
	println(line)
}
  • Example with durable history
rl, err := readline.NewEx(&readline.Config{
	Prompt: "> ",
	HistoryFile: "/tmp/readline.tmp",
})
if err != nil {
	panic(err)
}
defer rl.Close()

for {
	line, err := rl.Readline()
	if err != nil { // io.EOF, readline.ErrInterrupt
		break
	}
	println(line)
}
  • Example with auto completion
import (
	"gopkg.in/readline.v1"
)

var completer = readline.NewPrefixCompleter(
	readline.PcItem("say",
		readline.PcItem("hello"),
		readline.PcItem("bye"),
	),
	readline.PcItem("help"),
)

rl, err := readline.NewEx(&readline.Config{
	Prompt:       "> ",
	AutoComplete: completer,
})
if err != nil {
	panic(err)
}
defer rl.Close()

for {
	line, err := rl.Readline()
	if err != nil { // io.EOF, readline.ErrInterrupt
		break
	}
	println(line)
}

Shortcut

Meta+B means press Esc and n separately.
Users can change that in terminal simulator(i.e. iTerm2) to Alt+B
Notice: Meta+B is equals with Alt+B in windows.

  • Shortcut in normal mode
Shortcut Comment
Ctrl+A Beginning of line
Ctrl+B / Backward one character
Meta+B Backward one word
Ctrl+C Send io.EOF
Ctrl+D Delete one character
Meta+D Delete one word
Ctrl+E End of line
Ctrl+F / Forward one character
Meta+F Forward one word
Ctrl+G Cancel
Ctrl+H Delete previous character
Ctrl+I / Tab Command line completion
Ctrl+J Line feed
Ctrl+K Cut text to the end of line
Ctrl+L Clean screen (TODO)
Ctrl+M Same as Enter key
Ctrl+N / Next line (in history)
Ctrl+P / Prev line (in history)
Ctrl+R Search backwards in history
Ctrl+S Search forwards in history
Ctrl+T Transpose characters
Meta+T Transpose words (TODO)
Ctrl+U Cut text to the beginning of line
Ctrl+W Cut previous word
Backspace Delete previous character
Meta+Backspace Cut previous word
Enter Line feed
  • Shortcut in Search Mode (Ctrl+S or Ctrl+r to enter this mode)
Shortcut Comment
Ctrl+S Search forwards in history
Ctrl+R Search backwards in history
Ctrl+C / Ctrl+G Exit Search Mode and revert the history
Backspace Delete previous character
Other Exit Search Mode
  • Shortcut in Complete Select Mode (double Tab to enter this mode)
Shortcut Comment
Ctrl+F Move Forward
Ctrl+B Move Backward
Ctrl+N Move to next line
Ctrl+P Move to previous line
Ctrl+A Move to the first candicate in current line
Ctrl+E Move to the last candicate in current line
Tab / Enter Use the word on cursor to complete
Ctrl+C / Ctrl+G Exit Complete Select Mode
Other Exit Complete Select Mode

Tested with

Environment $TERM
Mac OS X iTerm2 xterm
Mac OS X default Terminal.app xterm
Mac OS X iTerm2 Screen screen
Mac OS X iTerm2 Tmux screen
Ubuntu Server 14.04 LTS linux
Centos 7 linux
Windows 10 -
Notice:
  • Ctrl+A is not working in screen because it used as a control command by default

If you test it otherwhere, whether it works fine or not, please let me know!

Who is using Readline

Feedback

If you have any questions, please submit a github issue and any pull requests is welcomed :)

Documentation

Overview

Readline is a pure go implementation for GNU-Readline kind library.

WHY: Readline will support most of features which GNU Readline is supported, and provide a pure go environment and a MIT license.

example:

rl, err := readline.New("> ")
if err != nil {
	panic(err)
}
defer rl.Close()

for {
	line, err := rl.Readline()
	if err != nil { // io.EOF
		break
	}
	println(line)
}

Index

Constants

View Source
const (
	CharLineStart = 1
	CharBackward  = 2
	CharInterrupt = 3
	CharDelete    = 4
	CharLineEnd   = 5
	CharForward   = 6
	CharBell      = 7
	CharCtrlH     = 8
	CharTab       = 9
	CharCtrlJ     = 10
	CharKill      = 11
	CharEnter     = 13
	CharNext      = 14
	CharPrev      = 16
	CharBckSearch = 18
	CharFwdSearch = 19
	CharTranspose = 20
	CharCtrlU     = 21
	CharCtrlW     = 23
	CharEsc       = 27
	CharEscapeEx  = 91
	CharBackspace = 127
)
View Source
const (
	MetaBackward rune = -iota - 1
	MetaForward
	MetaDelete
	MetaBackspace
	MetaTranspose
)
View Source
const (
	S_STATE_FOUND = iota
	S_STATE_FAILING
)
View Source
const (
	S_DIR_BCK = iota
	S_DIR_FWD
)
View Source
const (
	VIM_NORMAL = iota
	VIM_INSERT
	VIM_VISUAL
)

Variables

View Source
var (
	Stdin  io.ReadCloser  = os.Stdin
	Stdout io.WriteCloser = os.Stdout
	Stderr io.WriteCloser = os.Stderr
)
View Source
var (
	StdinFd  = int(uintptr(syscall.Stdin))
	StdoutFd = int(uintptr(syscall.Stdout))
)
View Source
var (
	ErrInterrupt = errors.New("Interrupt")
)

Functions

func AddHistory

func AddHistory(content string) error

func Debug

func Debug(o ...interface{})

append log info to another file

func Do

func Do(p PrefixCompleterInterface, line []rune, pos int) (newLine [][]rune, offset int)

func GetInt

func GetInt(s []string, def int) int

func IsPrintable

func IsPrintable(key rune) bool

func IsTerminal

func IsTerminal(fd int) bool

IsTerminal returns true if the given file descriptor is a terminal.

func IsWordBreak

func IsWordBreak(i rune) bool

func Line

func Line(prompt string) (string, error)

func LineCount

func LineCount(stdoutFd int, w int) int

calculate how many lines for N character

func MakeRaw

func MakeRaw(fd int) (*terminal.State, error)

func Print

func Print(p PrefixCompleterInterface, prefix string, level int, buf *bytes.Buffer)

func Restore

func Restore(fd int, state *terminal.State) error

func SetAutoComplete

func SetAutoComplete(completer AutoCompleter)

func SetHistoryPath

func SetHistoryPath(fp string)

Types

type AutoCompleter

type AutoCompleter interface {
	// Readline will pass the whole line and current offset to it
	// Completer need to pass all the candidates, and how long they shared the same characters in line
	// Example:
	//   Do("g", 1) => ["o", "it", "it-shell", "rep"], 1
	//   Do("gi", 2) => ["t", "t-shell"], 1
	//   Do("git", 3) => ["", "-shell"], 0
	Do(line []rune, pos int) (newLine [][]rune, length int)
}

type Config

type Config struct {
	// prompt supports ANSI escape sequence, so we can color some characters even in windows
	Prompt string

	// readline will persist historys to file where HistoryFile specified
	HistoryFile string
	// specify the max length of historys, it's 500 by default, set it to -1 to disable history
	HistoryLimit           int
	DisableAutoSaveHistory bool

	// AutoCompleter will called once user press TAB
	AutoComplete AutoCompleter

	// Any key press will pass to Listener
	// NOTE: Listener will be triggered by (nil, 0, 0) immediately
	Listener Listener

	// If VimMode is true, readline will in vim.insert mode by default
	VimMode bool

	InterruptPrompt string
	EOFPrompt       string

	Stdin  FdReader
	Stdout io.Writer
	Stderr io.Writer

	MaskRune rune

	UniqueEditLine bool

	// force use interactive even stdout is not a tty
	StdinFd             int
	StdoutFd            int
	ForceUseInteractive bool
	// contains filtered or unexported fields
}

func (Config) Clone

func (c Config) Clone() *Config

func (*Config) Init

func (c *Config) Init() error

func (*Config) SetListener

func (c *Config) SetListener(f func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool))

type Conn

type Conn struct {
	Conn     net.Conn
	Terminal *Terminal
	// contains filtered or unexported fields
}

func Dial

func Dial(network string, address string) (*Conn, error)

func NewConn

func NewConn(conn net.Conn, t *Terminal) (*Conn, error)

func (*Conn) Run

func (c *Conn) Run() error

type DumpListener

type DumpListener struct {
	// contains filtered or unexported fields
}

func (*DumpListener) OnChange

func (d *DumpListener) OnChange(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)

type FdReader

type FdReader interface {
	io.Reader
	Fd() uintptr
}

type Instance

type Instance struct {
	Config    *Config
	Terminal  *Terminal
	Operation *Operation
}

func New

func New(prompt string) (*Instance, error)

func NewEx

func NewEx(cfg *Config) (*Instance, error)

func (*Instance) Close

func (i *Instance) Close() error

we must make sure that call Close() before process exit.

func (*Instance) GenPasswordConfig

func (i *Instance) GenPasswordConfig() *Config

func (*Instance) IsVimMode

func (i *Instance) IsVimMode() bool

func (*Instance) ReadPassword

func (i *Instance) ReadPassword(prompt string) ([]byte, error)

func (*Instance) ReadPasswordEx

func (i *Instance) ReadPasswordEx(prompt string, l Listener) ([]byte, error)

func (*Instance) ReadPasswordWithConfig

func (i *Instance) ReadPasswordWithConfig(cfg *Config) ([]byte, error)

we can generate a config by `i.GenPasswordConfig()`

func (*Instance) ReadSlice

func (i *Instance) ReadSlice() ([]byte, error)

same as readline

func (*Instance) Readline

func (i *Instance) Readline() (string, error)

err is one of (nil, io.EOF, readline.ErrInterrupt)

func (*Instance) Refresh

func (i *Instance) Refresh()

func (*Instance) SaveHistory

func (i *Instance) SaveHistory(content string) error

func (*Instance) SetConfig

func (i *Instance) SetConfig(cfg *Config) *Config

func (*Instance) SetHistoryPath

func (i *Instance) SetHistoryPath(p string)

change hisotry persistence in runtime

func (*Instance) SetMaskRune

func (i *Instance) SetMaskRune(r rune)

func (*Instance) SetPrompt

func (i *Instance) SetPrompt(s string)

func (*Instance) SetVimMode

func (i *Instance) SetVimMode(on bool)

switch VimMode in runtime

func (*Instance) Stderr

func (i *Instance) Stderr() io.Writer

readline will refresh automatic when write through Stdout()

func (*Instance) Stdout

func (i *Instance) Stdout() io.Writer

readline will refresh automatic when write through Stdout()

type Listener

type Listener interface {
	OnChange(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)
}

func FuncListener

func FuncListener(f func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)) Listener

type Operation

type Operation struct {
	// contains filtered or unexported fields
}

func NewOperation

func NewOperation(t *Terminal, cfg *Config) *Operation

func (*Operation) Close

func (o *Operation) Close()

func (Operation) CompleteRefresh

func (o Operation) CompleteRefresh()

func (Operation) EnterCompleteMode

func (o Operation) EnterCompleteMode(offset int, candidate [][]rune)

func (Operation) EnterCompleteSelectMode

func (o Operation) EnterCompleteSelectMode()

func (Operation) EnterPasswordMode

func (o Operation) EnterPasswordMode(cfg *Config) (err error)

func (Operation) EnterVimInsertMode

func (o Operation) EnterVimInsertMode()

func (Operation) ExitCompleteMode

func (o Operation) ExitCompleteMode(revent bool)

func (Operation) ExitCompleteSelectMode

func (o Operation) ExitCompleteSelectMode()

func (Operation) ExitPasswordMode

func (o Operation) ExitPasswordMode()

func (Operation) ExitSearchMode

func (o Operation) ExitSearchMode(revert bool)

func (Operation) ExitVimInsertMode

func (o Operation) ExitVimInsertMode()

func (Operation) ExitVimMode

func (o Operation) ExitVimMode()

func (*Operation) GenPasswordConfig

func (o *Operation) GenPasswordConfig() *Config

func (Operation) HandleCompleteSelect

func (o Operation) HandleCompleteSelect(r rune) bool

func (Operation) HandleVim

func (o Operation) HandleVim(r rune, readNext func() rune) rune

func (Operation) HandleVimNormal

func (o Operation) HandleVimNormal(r rune, readNext func() rune) (t rune)

func (Operation) IsEnableVimMode

func (o Operation) IsEnableVimMode() bool

func (Operation) IsInCompleteMode

func (o Operation) IsInCompleteMode() bool

func (Operation) IsInCompleteSelectMode

func (o Operation) IsInCompleteSelectMode() bool

func (*Operation) IsNormalMode

func (o *Operation) IsNormalMode() bool

func (Operation) IsSearchMode

func (o Operation) IsSearchMode() bool

func (Operation) OnComplete

func (o Operation) OnComplete()

func (*Operation) Password

func (o *Operation) Password(prompt string) ([]byte, error)

func (Operation) PasswordConfig

func (o Operation) PasswordConfig() *Config

func (*Operation) PasswordEx

func (o *Operation) PasswordEx(prompt string, l Listener) ([]byte, error)

func (*Operation) PasswordWithConfig

func (o *Operation) PasswordWithConfig(cfg *Config) ([]byte, error)

func (*Operation) Refresh

func (o *Operation) Refresh()

func (*Operation) Runes

func (o *Operation) Runes() ([]rune, error)

func (*Operation) SaveHistory

func (o *Operation) SaveHistory(content string) error

if err is not nil, it just mean it fail to write to file other things goes fine.

func (Operation) SearchBackspace

func (o Operation) SearchBackspace()

func (Operation) SearchChar

func (o Operation) SearchChar(r rune)

func (Operation) SearchMode

func (o Operation) SearchMode(dir int)

func (Operation) SearchRefresh

func (o Operation) SearchRefresh(x int)

func (*Operation) SetConfig

func (op *Operation) SetConfig(cfg *Config) (*Config, error)

func (*Operation) SetHistoryPath

func (o *Operation) SetHistoryPath(path string)

func (*Operation) SetMaskRune

func (o *Operation) SetMaskRune(r rune)

func (*Operation) SetPrompt

func (o *Operation) SetPrompt(s string)

func (*Operation) SetTitle

func (o *Operation) SetTitle(t string)

func (Operation) SetVimMode

func (o Operation) SetVimMode(on bool)

func (*Operation) Slice

func (o *Operation) Slice() ([]byte, error)

func (*Operation) Stderr

func (o *Operation) Stderr() io.Writer

func (*Operation) Stdout

func (o *Operation) Stdout() io.Writer

func (*Operation) String

func (o *Operation) String() (string, error)

type PrefixCompleter

type PrefixCompleter struct {
	Name     []rune
	Children []PrefixCompleterInterface
}

func NewPrefixCompleter

func NewPrefixCompleter(pc ...PrefixCompleterInterface) *PrefixCompleter

func PcItem

func PcItem(name string, pc ...PrefixCompleterInterface) *PrefixCompleter

func (*PrefixCompleter) Do

func (p *PrefixCompleter) Do(line []rune, pos int) (newLine [][]rune, offset int)

func (*PrefixCompleter) GetChildren

func (p *PrefixCompleter) GetChildren() []PrefixCompleterInterface

func (*PrefixCompleter) GetName

func (p *PrefixCompleter) GetName() []rune

func (*PrefixCompleter) Print

func (p *PrefixCompleter) Print(prefix string, level int, buf *bytes.Buffer)

func (*PrefixCompleter) Tree

func (p *PrefixCompleter) Tree(prefix string) string

type PrefixCompleterInterface

type PrefixCompleterInterface interface {
	Print(prefix string, level int, buf *bytes.Buffer)
	Do(line []rune, pos int) (newLine [][]rune, length int)
	GetName() []rune
	GetChildren() []PrefixCompleterInterface
}

type RuneBuffer

type RuneBuffer struct {
	// contains filtered or unexported fields
}

func NewRuneBuffer

func NewRuneBuffer(w io.Writer, prompt string, mask rune, cfg *Config) *RuneBuffer

func (*RuneBuffer) BackEscapeWord

func (r *RuneBuffer) BackEscapeWord()

func (*RuneBuffer) Backspace

func (r *RuneBuffer) Backspace()

func (*RuneBuffer) Backup

func (r *RuneBuffer) Backup()

func (*RuneBuffer) Clean

func (r *RuneBuffer) Clean()

func (*RuneBuffer) CurrentWidth

func (r *RuneBuffer) CurrentWidth(x int) int

func (*RuneBuffer) CursorLineCount

func (r *RuneBuffer) CursorLineCount() int

func (*RuneBuffer) Delete

func (r *RuneBuffer) Delete() (success bool)

func (*RuneBuffer) DeleteWord

func (r *RuneBuffer) DeleteWord()

func (*RuneBuffer) Erase

func (r *RuneBuffer) Erase()

func (*RuneBuffer) IdxLine

func (r *RuneBuffer) IdxLine() int

func (*RuneBuffer) IsCursorInEnd

func (r *RuneBuffer) IsCursorInEnd() bool

func (*RuneBuffer) Kill

func (r *RuneBuffer) Kill()

func (*RuneBuffer) KillFront

func (r *RuneBuffer) KillFront()

func (*RuneBuffer) Len

func (r *RuneBuffer) Len() int

func (*RuneBuffer) LineCount

func (r *RuneBuffer) LineCount() int

func (*RuneBuffer) MoveBackward

func (r *RuneBuffer) MoveBackward()

func (*RuneBuffer) MoveForward

func (r *RuneBuffer) MoveForward()

func (*RuneBuffer) MoveTo

func (r *RuneBuffer) MoveTo(ch rune, prevChar, reverse bool) (success bool)

func (*RuneBuffer) MoveToLineEnd

func (r *RuneBuffer) MoveToLineEnd()

func (*RuneBuffer) MoveToLineStart

func (r *RuneBuffer) MoveToLineStart()

func (*RuneBuffer) MoveToNextWord

func (r *RuneBuffer) MoveToNextWord()

func (*RuneBuffer) MoveToPrevWord

func (r *RuneBuffer) MoveToPrevWord() (success bool)

func (*RuneBuffer) Pos

func (r *RuneBuffer) Pos() int

func (*RuneBuffer) PromptLen

func (r *RuneBuffer) PromptLen() int

func (*RuneBuffer) Refresh

func (r *RuneBuffer) Refresh(f func())

func (*RuneBuffer) Replace

func (r *RuneBuffer) Replace(ch rune)

func (*RuneBuffer) Reset

func (r *RuneBuffer) Reset() []rune

func (*RuneBuffer) Restore

func (r *RuneBuffer) Restore()

func (*RuneBuffer) RuneSlice

func (r *RuneBuffer) RuneSlice(i int) []rune

func (*RuneBuffer) Runes

func (r *RuneBuffer) Runes() []rune

func (*RuneBuffer) Set

func (r *RuneBuffer) Set(buf []rune)

func (*RuneBuffer) SetConfig

func (r *RuneBuffer) SetConfig(cfg *Config)

func (*RuneBuffer) SetMask

func (r *RuneBuffer) SetMask(m rune)

func (*RuneBuffer) SetPrompt

func (r *RuneBuffer) SetPrompt(prompt string)

func (*RuneBuffer) SetStyle

func (r *RuneBuffer) SetStyle(start, end int, style string)

func (*RuneBuffer) SetWithIdx

func (r *RuneBuffer) SetWithIdx(idx int, buf []rune)

func (*RuneBuffer) Transpose

func (r *RuneBuffer) Transpose()

func (*RuneBuffer) WriteRune

func (r *RuneBuffer) WriteRune(s rune)

func (*RuneBuffer) WriteRunes

func (r *RuneBuffer) WriteRunes(s []rune)

func (*RuneBuffer) WriteString

func (r *RuneBuffer) WriteString(s string)

type Terminal

type Terminal struct {
	// contains filtered or unexported fields
}

func NewTerminal

func NewTerminal(cfg *Config) (*Terminal, error)

func (*Terminal) Bell

func (t *Terminal) Bell()

func (*Terminal) Close

func (t *Terminal) Close() error

func (*Terminal) EnterRawMode

func (t *Terminal) EnterRawMode() (err error)

func (*Terminal) ExitRawMode

func (t *Terminal) ExitRawMode() (err error)

func (*Terminal) IsReading

func (t *Terminal) IsReading() bool

func (*Terminal) KickRead

func (t *Terminal) KickRead()

func (*Terminal) Print

func (t *Terminal) Print(s string)

func (*Terminal) PrintRune

func (t *Terminal) PrintRune(r rune)

func (*Terminal) ReadRune

func (t *Terminal) ReadRune() rune

return rune(0) if meet EOF

func (*Terminal) Readline

func (t *Terminal) Readline() *Operation

func (*Terminal) SetConfig

func (t *Terminal) SetConfig(c *Config) error

func (*Terminal) Write

func (t *Terminal) Write(b []byte) (int, error)

Directories

Path Synopsis
example
readline-pass-strength
This is a small example using readline to read a password and check it's strength while typing using the zxcvbn library.
This is a small example using readline to read a password and check it's strength while typing using the zxcvbn library.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL