readline

package module
v1.0.14 Latest Latest
Warning

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

Go to latest
Published: Jan 30, 2024 License: Apache-2.0 Imports: 20 Imported by: 6

README


Readline

Github Actions (workflows) Go module version GoDoc reference Go Report Card codecov

This library is a modern, pure Go readline shell implementation, with full .inputrc and legacy readline command/option support, and extended with various commands, options and tools commonly found in modern shells. Its architecture and completion system is heavily inspired from Z-Shell. It is used, between others, to power the console library.

Features

Core

Emacs / Standard

  • Native Emacs commands
  • Emacs-style macro engine (not working across multiple calls)
  • Keywords switching (operators, booleans, hex/binary/digit) with iterations
  • Command/mode cursor status indicator
  • Complete undo/redo history
  • Command status/arg/iterations hint display

Vim

  • Near-native Vim mode
  • Vim text objects (code blocks, words/blank/shellwords)
  • Extended surround select/change/add functionality, with highlighting
  • Vim Visual/Operator pending mode & cursor styles indications
  • Vim Insert and Replace (once/many)
  • All Vim registers, with completion support
  • Vim-style macro recording (q<a>) and invocation (@<a>)

Interface

  • Support for PS1/PS2/RPROMPT/transient/tooltip prompts (compatible with oh-my-posh)
  • Extended completion system, keymap-based and configurable, easy to populate & use
  • Multiple completion display styles, with color support.
  • Completion & History incremental search system & highlighting (fuzzy-search).
  • Automatic & context-aware suffix removal for efficient flags/path/list completion.
  • Optional asynchronous autocomplete
  • Builtin & programmable syntax highlighting

Documentation

Readline is used by the console library and its example binary. To get a grasp of the functionality provided by readline and its default configuration, install and start the binary.

The documentation is available on the repository wiki, for both users and developers.

Showcases

- Emacs edition
(This extract is quite a pity, because its author is not using Emacs and does not know many of its shortcuts)
- Vim edition
- Undo/redo line history
- Keyword switching & selection
Switching various keywords
Using regexp-based selection to grab parts of words (here, URL components)
- Vim selection & movements (basic)
- Vim surround (selection and change)
Selecting/adding/changing surround regions
Surround and change in shellwords, matching brackets, etc.
- Vim registers (with completion)
- History movements/completion/use/search
History movement, completion and some other other widgets
- Completion
Classic mode & incremental search mode
Suffix-autoremoval
- Prompts
- Logging
- Inputrc init file reload
- Multiline edition
- Macros
Emacs
Vim

Status

This library is now in a release status, as it has underwent several major rewrites and is now considered mostly feature-complete, with a solid testing suite to ensure safe and smooth operation to the best extent possible. New releases will be regularly pushed when bugs are found and corrected.

Additionally:

  • Key dispatch/flushing, meta-key enable, etc might still contain some bugs/wrong behavior: 30 years of legacy support for 3000 different terminal emulators cannot be done right by me alone.
  • Please open a PR or an issue if you face any bug, and it will be promptly resolved.
  • Don't hesitate proposing a new feature or a PR if you deem it to be useful to most users.

Credits

  • @kenshaw for his .inputrc parsing package, which brings much wider compatibility to this library.
  • chzyer/readline for the Windows I/O code and everything related.
  • Some of the Vim code is inspired or translated from zsh-vi-mode.
  • lmorg/readline, for the line tokenizers.

Documentation

Overview

Package readline provides a modern, pure Go `readline` shell implementation, with full `.inputrc` and legacy readline command/option support, and extended with various commands,options and tools commonly found in more modern shells.

Example usage:

     // Create a new shell with a custom prompt.
		rl := readline.NewShell()
		rl.Prompt.Primary(func() string { return "> "} )

	 // Display the prompt, read user input.
	 for {
	     line, err := rl.Readline()
	     if err != nil {
	         break
	     }
	     fmt.Println(line)
	 }

Index

Constants

This section is empty.

Variables

View Source
var ErrInterrupt = errors.New(os.Interrupt.String())

ErrInterrupt is returned when the interrupt sequence is pressed on the keyboard. The sequence is usually Ctrl-C.

View Source
var NewHistoryFromFile = history.NewSourceFromFile

NewHistoryFromFile creates a new command history source writing to and reading from a file. The caller should bind the history source returned from this call to the readline instance, with shell.History.Add().

View Source
var NewInMemoryHistory = history.NewInMemoryHistory

NewInMemoryHistory creates a new in-memory command history source. The caller should bind the history source returned from this call to the readline instance, with shell.History.Add().

Functions

This section is empty.

Types

type Completion

type Completion = completion.Candidate

Completion represents a completion candidate.

type Completions

type Completions struct {

	// Initially this will be set to the part of the current word
	// from the beginning of the word up to the position of the cursor.
	// It may be altered to give a prefix for all matches.
	PREFIX string

	// Initially this will be set to the part of the current word,
	// starting from the cursor position up to the end of the word.
	// It may be altered so that inserted completions don't overwrite
	// entirely any suffix when completing in the middle of a word.
	SUFFIX string
	// contains filtered or unexported fields
}

Completions holds all completions candidates and their associated data, including usage strings, messages, and suffix matchers for autoremoval. Some of those additional settings will apply to all contained candidates, except when these candidates have their own corresponding settings.

func CompleteMessage added in v1.0.9

func CompleteMessage(msg string, args ...any) Completions

CompleteMessage ads a help message to display along with or in places where no completions can be generated.

func CompleteRaw

func CompleteRaw(values []Completion) Completions

CompleteRaw directly accepts a list of prepared Completion values.

func CompleteStyledValues

func CompleteStyledValues(values ...string) Completions

CompleteStyledValues is like CompleteValues but also accepts a style.

func CompleteStyledValuesDescribed

func CompleteStyledValuesDescribed(values ...string) Completions

CompleteStyledValuesDescribed is like CompleteValues but also accepts a style.

func CompleteValues

func CompleteValues(values ...string) Completions

CompleteValues completes arbitrary keywords (values).

func CompleteValuesDescribed

func CompleteValuesDescribed(values ...string) Completions

CompleteValuesDescribed completes arbitrary key (values) with an additional description (value, description pairs).

func Message

func Message(msg string, args ...any) Completions

Message displays a help messages in places where no completions can be generated.

func (Completions) DisplayList

func (c Completions) DisplayList(tags ...string) Completions

DisplayList forces the completions to be list below each other as a list. A series of tags can be passed to restrict this to these tags. If empty, will be applied to all completions.

func (*Completions) EachValue

func (c *Completions) EachValue(tagF func(comp Completion) Completion)

EachValue runs a function on each value, overwriting with the returned one.

func (Completions) Filter

func (c Completions) Filter(values []string) Completions

Filter filters given values (this should be done before any call to Prefix/Suffix as those alter the values being filtered)

a := CompleteValues("A", "B", "C").Invoke(c)
b := a.Filter([]string{"B"}) // ["A", "C"]

func (Completions) JustifyDescriptions

func (c Completions) JustifyDescriptions(tags ...string) Completions

JustifyDescriptions accepts a list of tags for which descriptions (if any), will be left justified. If no arguments are given, description justification (padding) will apply to all tags.

func (Completions) ListSeparator

func (c Completions) ListSeparator(seps ...string) Completions

ListSeparator accepts a custom separator to use between the candidates and their descriptions. If more than one separator is given, the list is considered to be a map of tag:separators, in which case it will fail if the list has an odd number of values.

If one only one value is given, will apply to all completions (and their tags if any). If no value is given, no modifications will be made.

func (Completions) Merge

func (c Completions) Merge(others ...Completions) Completions

Merge merges Completions (existing values are overwritten)

a := CompleteValues("A", "B").Invoke(c)
b := CompleteValues("B", "C").Invoke(c)
c := a.Merge(b) // ["A", "B", "C"]

func (Completions) NoSort

func (c Completions) NoSort(tags ...string) Completions

NoSort forces the completions not to sort the completions in alphabetical order. A series of tags can be passed to restrict this to these tags. If empty, will be applied to all completions.

func (Completions) NoSpace

func (c Completions) NoSpace(suffixes ...rune) Completions

NoSpace disables space suffix for given characters (or all if none are given). These suffixes will be used for all completions that have not specified their own suffix-matching patterns. This is used for slash-autoremoval in path completions, comma-separated completions, etc.

func (Completions) Prefix

func (c Completions) Prefix(prefix string) Completions

Prefix adds a prefix to values (only the ones inserted, not the display values)

a := CompleteValues("melon", "drop", "fall").Invoke(c)
b := a.Prefix("water") // ["watermelon", "waterdrop", "waterfall"] but display still ["melon", "drop", "fall"]

func (Completions) PreserveEscapes added in v1.0.9

func (c Completions) PreserveEscapes(tags ...string) Completions

PreserveEscapes forces the completion engine to keep all escaped characters in the inserted completion (c.Value of the Completion type). By default, those are stripped out and only kept in the completion.Display. If no arguments are given, escape sequence preservation will apply to all tags.

This has very few use cases: one of them might be when you want to read a string from the readline shell that might include color sequences to be preserved. In such cases, this function gives a double advantage: the resulting completion is still "color-displayed" in the input line, and returned to the readline with them. A classic example is where you want to read a prompt string configuration.

Note that this option might have various undefined behaviors when it comes to completion prefix matching, insertion, removal and related things.

func (Completions) Style

func (c Completions) Style(style string) Completions

Style sets the style, accepting cterm color codes, eg. 255, 30, etc.

CompleteValues("yes").Style("35")
CompleteValues("no").Style("255")

func (Completions) StyleF

func (c Completions) StyleF(f func(s string) string) Completions

StyleF sets the style using a function

CompleteValues("dir/", "test.txt").StyleF(myStyleFunc)
CompleteValues("true", "false").StyleF(styleForKeyword)

func (Completions) StyleR

func (c Completions) StyleR(style *string) Completions

StyleR sets the style using a reference

CompleteValues("value").StyleR(&style.Value)
CompleteValues("description").StyleR(&style.Value)

func (Completions) Suffix

func (c Completions) Suffix(suffix string) Completions

Suffix adds a suffx to values (only the ones inserted, not the display values)

a := CompleteValues("apple", "melon", "orange").Invoke(c)
b := a.Suffix("juice") // ["applejuice", "melonjuice", "orangejuice"] but display still ["apple", "melon", "orange"]

func (Completions) Suppress

func (c Completions) Suppress(expr ...string) Completions

Suppress suppresses specific error messages using regular expressions.

func (Completions) Tag

func (c Completions) Tag(tag string) Completions

Tag sets the tag.

CompleteValues("192.168.1.1", "127.0.0.1").Tag("interfaces").

func (Completions) TagF

func (c Completions) TagF(f func(value string) string) Completions

TagF sets the tag using a function.

CompleteValues("192.168.1.1", "127.0.0.1").TagF(func(value string) string {
	return "interfaces"
})

func (Completions) Usage

func (c Completions) Usage(usage string, args ...any) Completions

Usage sets the usage.

func (Completions) UsageF

func (c Completions) UsageF(f func() string) Completions

UsageF sets the usage using a function.

type History

type History = history.Source

History is an interface to allow you to write your own history logging tools. By default readline will just use an in-memory history satisfying this interface, which only logs the history to memory ([]string to be precise). Users who want an easy to use, file-based history should use NewHistoryFromFile().

type Shell

type Shell struct {
	Iterations *core.Iterations // Digit arguments for repeating commands.
	Buffers    *editor.Buffers  // buffers (Vim registers) and methods use/manage/query them.
	Keys       *core.Keys       // Keys is in charge of reading and managing buffered user input.
	Keymap     *keymap.Engine   // Manages main/local keymaps, binds, stores command functions, etc.
	History    *history.Sources // History manages all history types/sources (past commands and undo)
	Macros     *macro.Engine    // Record, use and display macros.

	// User interface
	Config *inputrc.Config  // Contains all keymaps, binds and per-application settings.
	Opts   []inputrc.Option // Inputrc file parsing options (app/term/values, etc).
	Prompt *ui.Prompt       // The prompt engine computes and renders prompt strings.
	Hint   *ui.Hint         // Usage/hints for completion/isearch below the input line.

	Display *display.Engine // Manages display refresh/update/clearing.

	// AcceptMultiline enables the caller to decide if the shell should keep reading
	// for user input on a new line (therefore, with the secondary prompt), or if it
	// should return the current line at the end of the `rl.Readline()` call.
	// This function should return true if the line is deemed complete (thus asking
	// the shell to return from its Readline() loop), or false if the shell should
	// keep reading input on a newline (thus, insert a newline and read).
	AcceptMultiline func(line []rune) (accept bool)

	// SyntaxHighlighter is a helper function to provide syntax highlighting.
	// Once enabled, set to nil to disable again.
	SyntaxHighlighter func(line []rune) string

	// Completer is a function that produces completions.
	// It takes the readline line ([]rune) and cursor pos as parameters,
	// and returns completions with their associated metadata/settings.
	Completer func(line []rune, cursor int) Completions
	// contains filtered or unexported fields
}

Shell is the main readline shell instance. It contains all the readline state and methods to run the line editor, manage the inputrc configuration, keymaps and commands. Although each instance contains everything needed to run a line editor, it is recommended to use a single instance per application, and to share it between all the goroutines that need to read user input. Please refer to the README and documentation for more details about the shell and its components, and how to use them.

func NewShell

func NewShell(opts ...inputrc.Option) *Shell

NewShell returns a readline shell instance initialized with a default inputrc configuration and binds, and with an in-memory command history. The constructor accepts an optional list of inputrc configuration options, which are used when parsing/loading and applying any inputrc configuration.

func (*Shell) Cursor

func (rl *Shell) Cursor() *core.Cursor

Cursor is the cursor position in the current line buffer. Contains methods to set, move, describe and check itself.

When the shell is in incremental-search mode, this cursor is the minibuffer's one. The cursor returned here is thus the input buffer cursor of interest at call time.

func (*Shell) Line

func (rl *Shell) Line() *core.Line

Line is the shell input line buffer. Contains methods to search and modify its contents, split itself with tokenizers, and displaying itself.

When the shell is in incremental-search mode, this line is the minibuffer. The line returned here is thus the input buffer of interest at call time.

func (*Shell) PrintTransientf

func (rl *Shell) PrintTransientf(msg string, args ...any) (n int, err error)

PrintTransientf prints a formatted string in place of the current prompt and input line, and then refreshes, or "pushes" the prompt/line below this printed message.

func (*Shell) Printf

func (rl *Shell) Printf(msg string, args ...any) (n int, err error)

Printf prints a formatted string below the current line and redisplays the prompt and input line (and possibly completions/hints if active) below the logged string. A newline is added to the message so that the prompt is correctly refreshed below.

func (*Shell) Readline

func (rl *Shell) Readline() (string, error)

Readline displays the readline prompt and reads user input. It can return from the call because of different things:

  • When the user accepts the line (generally with Enter).
  • If a particular keystroke mapping returns an error. (Ctrl-C returns ErrInterrupt, Ctrl-D returns io.EOF).

In all cases, the current input line is returned along with any error, and it is up to the caller to decide what to do with the line result. When the error is not nil, the returned line is not written to history.

func (*Shell) Selection

func (rl *Shell) Selection() *core.Selection

Selection contains all regions of an input line that are currently selected/marked with either a begin and/or end position. The main selection is the visual one, used with the default cursor mark and position, and contains a list of additional surround selections used to change/select multiple parts of the line at once.

Directories

Path Synopsis
Package inputrc parses readline inputrc files.
Package inputrc parses readline inputrc files.
internal
ui

Jump to

Keyboard shortcuts

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