Skip to content

Repository files navigation

go-repl

Lightweight Golang REPL library, inspired by GNU Readline. You provide the Eval function, and go-repl does the rest.

Your REPLs that use this library will enjoy the following features:

  • Session history with reverse-search
    • Ctrl-R to start reverse-search
    • Most edit commands, except the most basic ones, exit the reverse-search mode
    • Use Up/Down to cycle through a filtered list of history entries
  • The input buffer is redrawn when a resize is detected
  • Status bar at bottom with current working dir and other info
  • Truncation of very long inputs (status bar displays info about cursor position)
  • Common edit and movement commands:
    • Right/Left: move cursor one character at a time
    • Ctrl-Right/Left: move cursor one word at a time
    • Up/Down: cycle through history
    • Backspace/Delete: works as expected
    • Shift-Enter: insert newline into buffer without invoking Eval
    • Ctrl-A or Home: move to start of buffer
    • Ctrl-E or End: move to end of buffer
    • Ctrl-W: delete preceding word
    • Ctrl-Q: delete following word
    • Ctrl-C or Esc: ignore current input and reset buffer
    • Ctrl-D: quit REPL
    • Ctrl-U: clear buffer to start
    • Ctrl-K: clear buffer to end
    • Ctrl-L: reset prompt at top and redraw buffer
    • Ctrl-Y: insert previous deletion (from Ctrl-K, Ctrl-U, Ctrl-Q or Ctrl-W)

Notes:

  • Doesn't depend on ncurses
  • Performance hasn't yet been optimized and I haven't yet tested all corner cases exhaustively
  • Might not work in Windows command prompt (keystroke codes could differ, ANSI escape sequences might not be supported, the method that sets terminal to raw mode might not work)
  • No vi edit mode
  • No support for clipboards yet

Usage

Fetch this library with the following command:

$ go get -u github.com/openengineer/go-repl

In order to create your own REPL you have to define a type that implements the Handler interface:

typeHandlerinterface {
Prompt() stringTab(bufferstring) stringEval(linestring) string
}

Here is a complete example (can also be found in ./examples/basic_repl.go):

package main
import (
"fmt""log""strconv""strings"
repl "github.com/openengineer/go-repl"
)
varhelpMessage=`help display this messageadd <int> <int> add two numbersquit quit this program`// implements repl.Handler interfacetypeMyHandlerstruct {
r*repl.Repl
}
funcmain() {
fmt.Println("Welcome, type \"help\" for more info")
h:=&MyHandler{}
h.r=repl.NewRepl(h)
// start the terminal loopiferr:=h.r.Loop(); err!=nil {
log.Fatal(err)
}
}
func (h*MyHandler) Prompt() string {
return"> " }
func (h*MyHandler) Tab(bufferstring) string {
return""// do nothing
}
func (h*MyHandler) Eval(linestring) string {
fields:=strings.Fields(line)
iflen(fields) ==0 {
return""
} else {
cmd, args:=fields[0], fields[1:]
switchcmd {
case"help":
returnhelpMessagecase"add":
iflen(args) !=2 {
return"\"add\" expects 2 args"
} else {
returnadd(args[0], args[1])
}
case"quit":
h.r.Quit()
return""default:
returnfmt.Sprintf("unrecognized command \"%s\"", cmd)
}
}
}
funcadd(a_string, b_string) string {
a, err:=strconv.Atoi(a_)
iferr!=nil {
return"first arg is not an integer"
}
b, err:=strconv.Atoi(b_)
iferr!=nil {
return"second arg is not an integer"
}
returnstrconv.Itoa(a+b)
}

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages