terminal

package module
v0.0.0-...-9348621 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2022 License: Unlicense Imports: 12 Imported by: 0

README

go-terminal

Lightweight golang terminal library, for creating your own REPL's.

Features:

  • session history
  • redraw of line buffer upon resize
  • common edit and movement commands:
    • Right/Left-arrow: move cursor one char at a time
    • Up/Down-arrow: cycle through history
    • Backspace: works as expected
    • Ctrl-a or Home: move to start of line
    • Ctrl-e or End: move to end of line
    • Ctrl-w: delete preceding word
    • Ctrl-v: paste contents of xclip (only linux, only if installed)
    • Ctrl + Right/Left-arrow: move cursor one word at a time
    • Ctrl-c or Esc: ignore line
    • Ctrl-d: quit
    • Ctrl-u: clear line to start
    • Ctrl-l: clear screen

Usage

Fetch this library with the following command:

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

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

type Handler interface {
  Eval(line string) (out string, hist string)
}

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

package main

import (
  "fmt"
  "log"
  "strconv"
  "strings"

  terminal "github.com/openengineer/go-terminal"
)

var helpMessage = `help: display this message
add <int> <int>: add two numbers`

// implements terminal.Handler interface
type REPL struct {
}

func main() {
  fmt.Println("Welcome, type \"help\" for more info")

  repl := &REPL{}

  t := terminal.NewTerminal(repl)
  t.SetPrompt("$") // default is ">", terminal always adds one space after the prompt

  // start the terminal loop
  if err := t.Run(); err != nil {
    log.Fatal(err)
  }
}

// first return value is for stdout, second return value is for history
func (r *REPL) Eval(line string) (string, string) {
  fields := strings.Fields(line)

  if len(fields) == 0 {
    return "", ""
  } else {
    cmd, args := fields[0], fields[1:]

    switch cmd {
    case "help":
      return helpMessage, line
    case "add":
      if len(args) != 2 {
        return "\"add\" expects 2 args", line
      } else {
        return add(args[0], args[1]), line
      }
    default:
      return fmt.Sprintf("unrecognized command \"%s\"", cmd), line
    }
  }
}

func add(a_ string, b_ string) string {
  a, err := strconv.Atoi(a_)
  if err != nil {
    return "first arg is not an integer"
  }

  b, err := strconv.Atoi(b_)
  if err != nil {
    return "second arg is not an integer"
  }

  return strconv.Itoa(a + b)
}

Documentation

Index

Constants

View Source
const ESC = "\033"
View Source
const MACHINE_INTERVAL = time.Millisecond

Variables

View Source
var (
	EFFICIENT = true // false -> redraw upon every action, true -> use the terminal efficiently

	// human reaction times are an order of magnitude slower than this
	// and auto generated stdin bytes are an order of magnitude faster than this
	WIDTH_POLLING_INTERVAL = 10 * time.Millisecond

	XCLIP = "/usr/bin/xclip"
)

Functions

This section is empty.

Types

type Canvas

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

structure the terminal window as a rectangle of characters

func NewCanvas

func NewCanvas() *Canvas

func (*Canvas) ClearLine

func (c *Canvas) ClearLine()

func (*Canvas) ClearScreen

func (c *Canvas) ClearScreen()

func (*Canvas) ClearStatus

func (c *Canvas) ClearStatus()

func (*Canvas) CursorDown

func (c *Canvas) CursorDown()

func (*Canvas) CursorLeft

func (c *Canvas) CursorLeft()

func (*Canvas) CursorRight

func (c *Canvas) CursorRight()

func (*Canvas) CursorUp

func (c *Canvas) CursorUp()

func (*Canvas) HighlightBytes

func (c *Canvas) HighlightBytes(bs []byte)

for the selection state

func (*Canvas) Pos

func (c *Canvas) Pos() (int, int)

func (*Canvas) SyncCursor

func (c *Canvas) SyncCursor()

func (*Canvas) UpdatePos

func (c *Canvas) UpdatePos(col int, row int)

func (*Canvas) UpdateSize

func (c *Canvas) UpdateSize(w int, h int)

func (*Canvas) Width

func (c *Canvas) Width() int

func (*Canvas) WriteByte

func (c *Canvas) WriteByte(b byte)

type Handler

type Handler interface {
	Eval(line string) (out string, hist string) // empty return strings are not stored in history
}

type StdinReader

type StdinReader struct {
	Chan chan []byte
	// contains filtered or unexported fields
}

InputReader collects inputs

func NewStdinReader

func NewStdinReader() *StdinReader

func (*StdinReader) Read

func (r *StdinReader) Read()

func (*StdinReader) Start

func (r *StdinReader) Start()

type Terminal

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

custom terminal prompt, because the existing discoverable terminal libraries suck

func NewTerminal

func NewTerminal(handler Handler) *Terminal

func (*Terminal) Run

func (t *Terminal) Run() error

func (*Terminal) SetPrompt

func (t *Terminal) SetPrompt(p string)

func (*Terminal) SetRaw

func (t *Terminal) SetRaw() error

func (*Terminal) UnsetRaw

func (t *Terminal) UnsetRaw()

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

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