readline

package module
v0.2.7 Latest Latest
Warning

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

Go to latest
Published: Nov 20, 2020 License: MIT Imports: 13 Imported by: 0

README

go-readline-ny

go-readline-ny is the readline library used in the command line shell NYAGOS.

  • Emacs-like key-bindings
  • On Windows Terminal
    • Surrogate-pair
    • Emoji (via clipboard)
    • Zero-Width-Joiner (via clipboard)

Zero-Width-Joiner sample on Windows-Terminal

example1.go

The most simple sample.

package main

import (
    "context"
    "fmt"

    "github.com/zetamatta/go-readline-ny"
)

func main() {
    editor := readline.Editor{}
    text, err := editor.ReadLine(context.Background())
    if err != nil {
        fmt.Printf("ERR=%s\n", err.Error())
    } else {
        fmt.Printf("TEXT=%s\n", text)
    }
}

If the target platform includes Windows, you have to import and use go-colorable like example2.go .

example2.go

Tiny Shell

package main

import (
    "context"
    "fmt"
    "os"
    "os/exec"
    "strings"

    "github.com/mattn/go-colorable"

    "github.com/zetamatta/go-readline-ny"
    "github.com/zetamatta/go-readline-ny/simplehistory"
)

func main() {
    history := simplehistory.New()

    editor := readline.Editor{
        Prompt:  func() (int, error) { return fmt.Print("$ ") },
        Writer:  colorable.NewColorableStdout(),
        History: history,
    }
    fmt.Println("Tiny Shell. Type Ctrl-D to quit.")
    for {
        text, err := editor.ReadLine(context.Background())

        if err != nil {
            fmt.Printf("ERR=%s\n", err.Error())
            return
        }

        fields := strings.Fields(text)
        if len(fields) <= 0 {
            continue
        }
        cmd := exec.Command(fields[0], fields[1:]...)
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr
        cmd.Stdin = os.Stdin

        cmd.Run()

        history.Add(text)
    }
}

Documentation

Index

Constants

View Source
const (
	K_BACKSPACE      = "BACKSPACE"
	K_CAPSLOCK       = "CAPSLOCK"
	K_CLEAR          = "CLEAR"
	K_CTRL           = "CTRL"
	K_CTRL_A         = "C_A"
	K_CTRL_B         = "C_B"
	K_CTRL_BREAK     = "C_BREAK"
	K_CTRL_C         = "C_C"
	K_CTRL_D         = "C_D"
	K_CTRL_E         = "C_E"
	K_CTRL_F         = "C_F"
	K_CTRL_G         = "C_G"
	K_CTRL_H         = "C_H"
	K_CTRL_I         = "C_I"
	K_CTRL_J         = "C_J"
	K_CTRL_K         = "C_K"
	K_CTRL_L         = "C_L"
	K_CTRL_M         = "C_M"
	K_CTRL_N         = "C_N"
	K_CTRL_O         = "C_O"
	K_CTRL_P         = "C_P"
	K_CTRL_Q         = "C_Q"
	K_CTRL_R         = "C_R"
	K_CTRL_S         = "C_S"
	K_CTRL_T         = "C_T"
	K_CTRL_U         = "C_U"
	K_CTRL_V         = "C_V"
	K_CTRL_W         = "C_W"
	K_CTRL_X         = "C_X"
	K_CTRL_Y         = "C_Y"
	K_CTRL_Z         = "C_Z"
	K_CTRL_UNDERBAR  = "C_UNDERBAR"
	K_CTRL_LBRACKET  = "C_["
	K_CTRL_RBRACKET  = "C_]"
	K_CTRL_BACKSLASH = "C_\\"
	K_CTRL_CARET     = "C_^"
	K_DELETE         = "DEL"
	K_DOWN           = "DOWN"
	K_CTRL_DOWN      = "C_DOWN"
	K_END            = "END"
	K_ENTER          = "ENTER"
	K_ESCAPE         = "ESCAPE"
	K_F1             = "F1"
	K_F10            = "F10"
	K_F11            = "F11"
	K_F12            = "F12"
	K_F13            = "F13"
	K_F14            = "F14"
	K_F15            = "F15"
	K_F16            = "F16"
	K_F17            = "F17"
	K_F18            = "F18"
	K_F19            = "F19"
	K_F2             = "F2"
	K_F20            = "F20"
	K_F21            = "F21"
	K_F22            = "F22"
	K_F23            = "F23"
	K_F24            = "F24"
	K_F3             = "F3"
	K_F4             = "F4"
	K_F5             = "F5"
	K_F6             = "F6"
	K_F7             = "F7"
	K_F8             = "F8"
	K_F9             = "F9"
	K_HOME           = "HOME"
	K_LEFT           = "LEFT"
	K_CTRL_LEFT      = "C_LEFT"
	K_PAGEDOWN       = "PAGEDOWN"
	K_PAGEUP         = "PAGEUP"
	K_PAUSE          = "PAUSE"
	K_RIGHT          = "RIGHT"
	K_CTRL_RIGHT     = "C_RIGHT"
	K_SHIFT          = "SHIFT"
	K_UP             = "UP"
	K_CTRL_UP        = "C_UP"
	K_ALT_A          = "M_A"
	K_ALT_B          = "M_B"
	K_ALT_BACKSPACE  = "M_BACKSPACE"
	K_ALT_BREAK      = "M_BREAK"
	K_ALT_C          = "M_C"
	K_ALT_D          = "M_D"
	K_ALT_E          = "M_E"
	K_ALT_F          = "M_F"
	K_ALT_G          = "M_G"
	K_ALT_H          = "M_H"
	K_ALT_I          = "M_I"
	K_ALT_J          = "M_J"
	K_ALT_K          = "M_K"
	K_ALT_L          = "M_L"
	K_ALT_M          = "M_M"
	K_ALT_N          = "M_N"
	K_ALT_O          = "M_O"
	K_ALT_P          = "M_P"
	K_ALT_Q          = "M_Q"
	K_ALT_R          = "M_R"
	K_ALT_S          = "M_S"
	K_ALT_T          = "M_T"
	K_ALT_U          = "M_U"
	K_ALT_V          = "M_V"
	K_ALT_W          = "M_W"
	K_ALT_X          = "M_X"
	K_ALT_Y          = "M_Y"
	K_ALT_Z          = "M_Z"
	K_ALT_OEM_2      = "M_OEM_2"
)
View Source
const (
	F_ACCEPT_LINE          = "ACCEPT_LINE"
	F_BACKWARD_CHAR        = "BACKWARD_CHAR"
	F_BACKWARD_WORD        = "BACKWARD_WORD"
	F_BACKWARD_DELETE_CHAR = "BACKWARD_DELETE_CHAR"
	F_BEGINNING_OF_LINE    = "BEGINNING_OF_LINE"
	F_CLEAR_SCREEN         = "CLEAR_SCREEN"
	F_DELETE_CHAR          = "DELETE_CHAR"
	F_DELETE_OR_ABORT      = "DELETE_OR_ABORT"
	F_END_OF_LINE          = "END_OF_LINE"
	F_FORWARD_CHAR         = "FORWARD_CHAR"
	F_FORWARD_WORD         = "FORWARD_WORD"
	F_HISTORY_DOWN         = "HISTORY_DOWN" // for compatible
	F_HISTORY_UP           = "HISTORY_UP"   // for compatible
	F_NEXT_HISTORY         = "NEXT_HISTORY"
	F_PREVIOUS_HISTORY     = "PREVIOUS_HISTORY"
	F_INTR                 = "INTR"
	F_ISEARCH_BACKWARD     = "ISEARCH_BACKWARD"
	F_KILL_LINE            = "KILL_LINE"
	F_KILL_WHOLE_LINE      = "KILL_WHOLE_LINE"
	F_PASS                 = "PASS"
	F_QUOTED_INSERT        = "QUOTED_INSERT"
	F_REPAINT_ON_NEWLINE   = "REPAINT_ON_NEWLINE"
	F_SWAPCHAR             = "SWAPCHAR"
	F_UNIX_LINE_DISCARD    = "UNIX_LINE_DISCARD"
	F_UNIX_WORD_RUBOUT     = "UNIX_WORD_RUBOUT"
	F_YANK                 = "YANK"
	F_YANK_WITH_QUOTE      = "YANK_WITH_QUOTE"
	F_UNDO                 = "UNDO"
)
View Source
const TreatAmbiguousWidthAsNarrow = false

Variables

View Source
var (
	SurrogatePairOk         = os.Getenv("WT_SESSION") != "" && os.Getenv("WT_PROFILE_ID") != ""
	ZeroWidthJoinSequenceOk = os.Getenv("WT_SESSION") != "" && os.Getenv("WT_PROFILE_ID") != ""
)
View Source
var CtrlC = errors.New("^C")
View Source
var Delimiters = "\"'"
View Source
var NAME2FUNC = map[string]func(context.Context, *Buffer) Result{
	F_ACCEPT_LINE:          keyFuncEnter,
	F_BACKWARD_CHAR:        keyFuncBackward,
	F_BACKWARD_WORD:        keyFuncBackwardWord,
	F_BACKWARD_DELETE_CHAR: keyFuncBackSpace,
	F_BEGINNING_OF_LINE:    keyFuncHead,
	F_CLEAR_SCREEN:         keyFuncCLS,
	F_DELETE_CHAR:          keyFuncDelete,
	F_DELETE_OR_ABORT:      keyFuncDeleteOrAbort,
	F_END_OF_LINE:          keyFuncTail,
	F_FORWARD_CHAR:         keyFuncForward,
	F_FORWARD_WORD:         keyFuncForwardWord,
	F_HISTORY_DOWN:         keyFuncHistoryDown,
	F_HISTORY_UP:           keyFuncHistoryUp,
	F_NEXT_HISTORY:         keyFuncHistoryDown,
	F_PREVIOUS_HISTORY:     keyFuncHistoryUp,
	F_INTR:                 keyFuncIntr,
	F_ISEARCH_BACKWARD:     keyFuncIncSearch,
	F_KILL_LINE:            keyFuncClearAfter,
	F_KILL_WHOLE_LINE:      keyFuncClear,
	F_PASS:                 nil,
	F_QUOTED_INSERT:        keyFuncQuotedInsert,
	F_UNIX_LINE_DISCARD:    keyFuncClearBefore,
	F_UNIX_WORD_RUBOUT:     keyFuncWordRubout,
	F_YANK:                 keyFuncPaste,
	F_YANK_WITH_QUOTE:      keyFuncPasteQuote,
	F_SWAPCHAR:             keyFuncSwapChar,
	F_REPAINT_ON_NEWLINE:   keyFuncRepaintOnNewline,
	F_UNDO:                 keyFuncUndo,
}

Functions

func GetKey added in v0.2.2

func GetKey(tty1 KeyGetter) (string, error)

GetKey reads one-key from tty.

func ResetCharWidth

func ResetCharWidth()

ResetCharWidth resets the cache for the width of characters.

func SetCharWidth

func SetCharWidth(c rune, width int)

SetCharWidth sets the width of the character into the cache.

Types

type Buffer

type Buffer struct {
	*Editor
	Buffer    []Moji
	TTY       KeyGetter
	ViewStart int

	HistoryPointer int
	// contains filtered or unexported fields
}

func (*Buffer) CurrentWord

func (this *Buffer) CurrentWord() (string, int)

func (*Buffer) CurrentWordTop

func (this *Buffer) CurrentWordTop() (wordTop int)

func (*Buffer) Delete

func (this *Buffer) Delete(pos int, n int) WidthT

Delete remove Buffer[pos:pos+n]. It returns the width to clear the end of line. It does not update screen.

func (*Buffer) DrawFromHead

func (buf *Buffer) DrawFromHead()

DrawFromHead draw all text in viewarea and move screen-cursor to the position where it should be.

func (*Buffer) Eraseline

func (this *Buffer) Eraseline()

func (*Buffer) GetKey

func (this *Buffer) GetKey() (string, error)

GetKey reads one-key from tty.

func (*Buffer) GetWidthBetween

func (this *Buffer) GetWidthBetween(from int, to int) WidthT

func (*Buffer) GotoHead

func (buf *Buffer) GotoHead()

GotoHead move screen-cursor to the top of the viewarea. It should be called before text is changed.

func (*Buffer) InsertAndRepaint

func (buf *Buffer) InsertAndRepaint(str string)

InsertAndRepaint inserts str and repaint the editline.

func (*Buffer) InsertString

func (this *Buffer) InsertString(pos int, s string) int

Insert String :s at :pos (Do not update screen) returns

count of rune

func (*Buffer) Repaint

func (buf *Buffer) Repaint(pos int, del WidthT)

Repaint buffer[pos:] + " \b"*del but do not rewind cursor position

func (*Buffer) RepaintAfterPrompt

func (buf *Buffer) RepaintAfterPrompt()

RepaintAfterPrompt repaints the all characters in the editline except for prompt.

func (*Buffer) RepaintAll

func (buf *Buffer) RepaintAll()

RepaintAll repaints the all characters in the editline including prompt.

func (*Buffer) ReplaceAndRepaint

func (buf *Buffer) ReplaceAndRepaint(pos int, str string)

ReplaceAndRepaint replaces the string between `pos` and cursor's position to `str`

func (*Buffer) ResetViewStart

func (this *Buffer) ResetViewStart()

ResetViewStart set ViewStart the new value which should be. It does not update screen.

func (Buffer) String

func (this Buffer) String() string

func (*Buffer) SubString

func (this *Buffer) SubString(start, end int) string

func (*Buffer) ViewWidth

func (this *Buffer) ViewWidth() WidthT

type CodePoint added in v0.2.1

type CodePoint rune

func (CodePoint) IsSpace added in v0.2.1

func (c CodePoint) IsSpace() bool

func (CodePoint) Put added in v0.2.1

func (c CodePoint) Put(w io.Writer)

func (CodePoint) Width added in v0.2.1

func (c CodePoint) Width() WidthT

func (CodePoint) WriteTo added in v0.2.1

func (c CodePoint) WriteTo(w io.Writer) (int64, error)

type Editor

type Editor struct {
	KeyMap
	History       IHistory
	Writer        io.Writer
	Out           *bufio.Writer
	Prompt        func() (int, error)
	Default       string
	Cursor        int
	LineFeed      func(Result)
	OpenKeyGetter func() (KeyGetter, error)
}

func (*Editor) ReadLine

func (editor *Editor) ReadLine(ctx context.Context) (string, error)

Call LineEditor - ENTER typed -> returns TEXT and nil - CTRL-C typed -> returns "" and readline.CtrlC - CTRL-D typed -> returns "" and io.EOF

type EmptyHistory

type EmptyHistory struct{}

func (*EmptyHistory) At

func (*EmptyHistory) At(int) string

At always returns empty-string because the receiver is dummy.

func (*EmptyHistory) Len

func (*EmptyHistory) Len() int

Len always returns zero because the receiver is dummy.

type IHistory

type IHistory interface {
	Len() int
	At(int) string
}

type KeyFuncT

type KeyFuncT interface {
	Call(ctx context.Context, buffer *Buffer) Result
}

func GetFunc

func GetFunc(funcName string) (KeyFuncT, error)

type KeyGetter added in v0.2.7

type KeyGetter interface {
	Raw() (func() error, error)
	ReadRune() (rune, error)
	Buffered() bool
	GetChangeWidthEvent() func() int
	Close() error
	Size() (int, int, error)
}

type KeyGoFuncT

type KeyGoFuncT struct {
	Func func(ctx context.Context, buffer *Buffer) Result
	Name string
}

func (*KeyGoFuncT) Call

func (this *KeyGoFuncT) Call(ctx context.Context, buffer *Buffer) Result

func (KeyGoFuncT) String

func (this KeyGoFuncT) String() string

type KeyMap

type KeyMap struct {
	KeyMap map[string]KeyFuncT
}
var GlobalKeyMap KeyMap

func (*KeyMap) BindKeyClosure

func (editor *KeyMap) BindKeyClosure(name string, f func(context.Context, *Buffer) Result) error

func (*KeyMap) BindKeyFunc

func (editor *KeyMap) BindKeyFunc(key string, f KeyFuncT) error

func (*KeyMap) BindKeySymbol

func (editor *KeyMap) BindKeySymbol(keyName, funcName string) error

func (*KeyMap) GetBindKey

func (editor *KeyMap) GetBindKey(key string) KeyFuncT

type Moji added in v0.2.1

type Moji interface {
	Width() WidthT
	WriteTo(io.Writer) (int64, error)
	Put(io.Writer)
	IsSpace() bool
}

type Range added in v0.2.1

type Range []Moji

func (Range) Width added in v0.2.1

func (s Range) Width() (w WidthT)

type Result

type Result int

Result is the type for readline's result.

const (
	CONTINUE Result = iota
	ENTER    Result = iota
	ABORT    Result = iota
	INTR     Result = iota
)

func (Result) String

func (this Result) String() string

String makes Result to fmt.Stringer

type WidthT added in v0.2.2

type WidthT int

WidthT means the width type

func GetCharWidth

func GetCharWidth(n rune) WidthT

GetCharWidth returns the width of the character.

func GetStringWidth

func GetStringWidth(s string) WidthT

GetStringWidth returns the width of the string.

type ZeroWidthJoinSequence added in v0.2.1

type ZeroWidthJoinSequence string

func (ZeroWidthJoinSequence) IsSpace added in v0.2.1

func (s ZeroWidthJoinSequence) IsSpace() bool

func (ZeroWidthJoinSequence) Put added in v0.2.1

func (s ZeroWidthJoinSequence) Put(w io.Writer)

func (ZeroWidthJoinSequence) Width added in v0.2.1

func (s ZeroWidthJoinSequence) Width() WidthT

func (ZeroWidthJoinSequence) WriteTo added in v0.2.1

func (s ZeroWidthJoinSequence) WriteTo(w io.Writer) (int64, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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