Documentation
¶
Overview ¶
Package reline is a pure-Go (CGO=0) port of MRI 4.0.5's Reline line-editor core: the editing state machine (line buffer, cursor, keymap dispatch, editing commands, history, kill-ring, completion) plus the pure rendering computation. The terminal raw-mode I/O is a host seam (see io.go) wired by the embedder (e.g. rbgo for a pure-Go IRB).
Index ¶
- Variables
- func CalculateWidth(str string, allowEscapeCode bool) int
- func CommonPrefix(list []string, ignoreCase bool) string
- func EscapeForPrint(str string) string
- func SplitByWidth(str string, maxWidth int) ([]string, int)
- func SplitLineByWidth(str string, maxWidth, offset int) []string
- type CompletionProc
- type Config
- type EditingMode
- type History
- func (h *History) Append(val string)
- func (h *History) Clear()
- func (h *History) DeleteAt(index int) (string, error)
- func (h *History) Empty() bool
- func (h *History) Get(index int) (string, error)
- func (h *History) Push(vals ...string)
- func (h *History) Set(index int, val string) error
- func (h *History) Size() int
- type HistoryError
- type IO
- type Key
- type KillRing
- type LineEditor
- func (le *LineEditor) BytePointer() int
- func (le *LineEditor) CurrentLine() string
- func (le *LineEditor) DeleteText(start, length int, hasArgs bool)
- func (le *LineEditor) EOF() bool
- func (le *LineEditor) Finished() bool
- func (le *LineEditor) History() *History
- func (le *LineEditor) InsertMultilineText(text string)
- func (le *LineEditor) InsertText(text string)
- func (le *LineEditor) Line() (string, bool)
- func (le *LineEditor) LineIndex() int
- func (le *LineEditor) MenuInfo() ([]string, bool)
- func (le *LineEditor) MultilineOff()
- func (le *LineEditor) MultilineOn()
- func (le *LineEditor) Render(width int, promptProc PromptProc) RenderState
- func (le *LineEditor) Reset(prompt string)
- func (le *LineEditor) ResetLine()
- func (le *LineEditor) SearchingPrompt() (string, bool)
- func (le *LineEditor) SetBytePointer(v int)
- func (le *LineEditor) SetCompletionAppendCharacter(s string)
- func (le *LineEditor) SetCompletionProc(p CompletionProc)
- func (le *LineEditor) SetConfirmMultilineTermination(p func(buffer string) bool)
- func (le *LineEditor) SetPastingState(inPasting bool)
- func (le *LineEditor) Update(key Key) bool
- func (le *LineEditor) WholeBuffer() string
- func (le *LineEditor) WholeLines() []string
- type NullIO
- type PromptProc
- type RenderState
Constants ¶
This section is empty.
Variables ¶
var ( CompleterWordBreakCharacters = " \t\n`><=;|&{(" CompleterQuoteCharacters = "\"'" )
CompleterWordBreakCharacters and CompleterQuoteCharacters mirror Reline's defaults; they delimit the word under the cursor for completion.
var AmbiguousWidth = 1
AmbiguousWidth is the display width used for East-Asian "ambiguous" width characters. MRI resolves this at runtime from the terminal probe; the default is 1 (mirrors Reline.ambiguous_width when STDOUT is not a tty / dumb).
var LastIncrementalSearch = ""
LastIncrementalSearch holds the last incremental search word (MRI Reline.last_incremental_search), shared across searches.
Functions ¶
func CalculateWidth ¶
CalculateWidth returns the display width of str. When allowEscapeCode is true, CSI/OSC escape sequences and non-printing markers are excluded from the count (MRI Reline::Unicode.calculate_width).
func CommonPrefix ¶
CommonPrefix returns the longest common grapheme-cluster prefix of list, optionally case-insensitively (MRI Reline::Unicode.common_prefix).
func EscapeForPrint ¶
EscapeForPrint converts control characters to their printable caret escapes, keeping newline and expanding tab to two spaces (MRI escape_for_print).
func SplitByWidth ¶
SplitByWidth wraps str into display lines no wider than maxWidth and returns the lines plus their count (MRI Reline::Unicode.split_by_width, used by IRB).
func SplitLineByWidth ¶
SplitLineByWidth wraps str into display lines no wider than maxWidth, starting at the given column offset, carrying CSI color state across wraps (MRI Reline::Unicode.split_line_by_width).
Types ¶
type CompletionProc ¶
CompletionProc computes completion candidates for the word `target`, given the text before (`pre`) and after (`post`) it. Returning nil means "no completion" (MRI's completion_proc that may return non-Array).
type Config ¶
type Config struct {
HistorySize int // -1 unlimited (default), 0 drop-all, >0 cap
CompletionIgnoreCase bool // case-fold completion matching
ShowAllIfAmbiguous bool // show menu immediately on ambiguous completion
DisableCompletion bool
Autocompletion bool
KeyseqTimeout int // ms; ESC ambiguity timeout
IsearchTerminators string
// contains filtered or unexported fields
}
Config holds the editor configuration relevant to the pure editing core (MRI Reline::Config, trimmed to the state-machine-relevant fields).
func NewConfig ¶
func NewConfig() *Config
NewConfig returns a Config with MRI's defaults (emacs mode, unlimited history, 500ms keyseq timeout) and the standard emacs/vi keymaps loaded.
func (*Config) EditingMode ¶
func (c *Config) EditingMode() EditingMode
EditingMode returns the current mode.
func (*Config) EditingModeIs ¶
func (c *Config) EditingModeIs(modes ...EditingMode) bool
EditingModeIs reports whether the current mode is any of the given modes.
func (*Config) SetEditingMode ¶
func (c *Config) SetEditingMode(m EditingMode)
SetEditingMode switches the active keymap.
type EditingMode ¶
type EditingMode int
EditingMode selects the active keymap (MRI @editing_mode_label).
const ( // ModeEmacs is the default emacs keymap. ModeEmacs EditingMode = iota // ModeViInsert is vi insert mode. ModeViInsert // ModeViCommand is vi command (normal) mode. ModeViCommand )
type History ¶
type History struct {
MaxSize int
// contains filtered or unexported fields
}
History is the line-edit history (MRI Reline::History, a size-capped Array). MaxSize > 0 caps the number of entries (oldest dropped); 0 drops everything; negative means unlimited.
func NewHistory ¶
NewHistory returns an empty history with the given size cap (-1 = unlimited, the MRI default).
func (*History) Get ¶
Get returns the entry at index (supporting negative indices), mirroring Reline::History#[].
func (*History) Push ¶
Push appends one or more entries, enforcing the size cap. Mirrors Reline::History#push (and #concat, which is push applied per element).
type HistoryError ¶
type HistoryError struct {
// contains filtered or unexported fields
}
HistoryError is raised for out-of-range/out-of-bounds history index access, mirroring MRI's RangeError / IndexError from Reline::History#check_index.
func (*HistoryError) Error ¶
func (e *HistoryError) Error() string
type IO ¶
type IO interface {
// GetC returns the next input byte, or -1 on timeout/EOF. timeoutMs < 0
// means block indefinitely.
GetC(timeoutMs int) int
// UngetC pushes a byte back to be returned by the next GetC.
UngetC(c int)
// GetScreenSize returns the terminal size as (rows, cols).
GetScreenSize() (rows, cols int)
// Write emits already-rendered output (escape sequences + text) to the tty.
Write(s string)
// MoveCursorColumn moves the cursor to an absolute column.
MoveCursorColumn(col int)
// EraseAfterCursor clears from the cursor to the end of the line.
EraseAfterCursor()
// ClearScreen clears the whole screen.
ClearScreen()
}
IO is the terminal host seam. Everything that touches a real tty lives behind this interface so the editing core stays pure and fully testable. The embedder (e.g. rbgo) supplies a concrete implementation backed by the host terminal in raw mode; tests supply a scripted/recording fake.
The pure core only needs three capabilities from the host: read a raw key byte, learn the terminal size, and write rendered output. Cursor positioning and screen clears are expressed as writes by the renderer, but are surfaced here too for embedders that drive the screen directly.
type Key ¶
Key is a decoded key event: Char is the input string and MethodSymbol the command it dispatches to (MRI Reline::Key). A nil/empty Char with empty MethodSymbol represents EOF.
type KillRing ¶
type KillRing struct {
// contains filtered or unexported fields
}
KillRing is the emacs kill ring (MRI Reline::KillRing): kill commands append text, yank pastes the most recent entry, and yank-pop rotates backward.
func NewKillRing ¶
NewKillRing returns an empty kill ring holding up to max entries.
func (*KillRing) Append ¶
Append adds killed text. When beforeP is true the text is prepended to the current accumulating entry (used by backward kills).
func (*KillRing) Each ¶
Each iterates the ring from most-recent to least-recent (MRI KillRing#each).
func (*KillRing) Process ¶
func (k *KillRing) Process()
Process advances the kill-accumulation state machine once per dispatched key, so that two consecutive kills merge but a kill after another command starts a new entry (MRI KillRing#process).
type LineEditor ¶
type LineEditor struct {
// contains filtered or unexported fields
}
LineEditor is the MRI Reline::LineEditor editing state machine: a multiline rune-aware buffer with a byte cursor, the full emacs+vi command set, history navigation + incremental search, kill-ring, completion, and undo/redo. It is driven purely by Keys (Update) and exposes the buffer/cursor for rendering.
func NewLineEditor ¶
func NewLineEditor(config *Config, io IO, hist *History) *LineEditor
NewLineEditor returns a LineEditor wired to config and the terminal seam io. hist is the shared history (Reline::HISTORY).
func (*LineEditor) BytePointer ¶
func (le *LineEditor) BytePointer() int
BytePointer returns the cursor's byte offset within the current line.
func (*LineEditor) CurrentLine ¶
func (le *LineEditor) CurrentLine() string
CurrentLine returns the line the cursor is on.
func (*LineEditor) DeleteText ¶
func (le *LineEditor) DeleteText(start, length int, hasArgs bool)
DeleteText deletes a range of the current line, or (with hasArgs=false) deletes the current line / merges per MRI delete_text() with no args.
func (*LineEditor) EOF ¶
func (le *LineEditor) EOF() bool
EOF reports whether the read ended via end-of-input (e.g. Ctrl-D on empty).
func (*LineEditor) Finished ¶
func (le *LineEditor) Finished() bool
Finished reports whether the current read has terminated (Enter or EOF).
func (*LineEditor) History ¶
func (le *LineEditor) History() *History
History returns the editor's shared history.
func (*LineEditor) InsertMultilineText ¶
func (le *LineEditor) InsertMultilineText(text string)
InsertMultilineText inserts text that may contain newlines, splitting the current line (MRI insert_multiline_text).
func (*LineEditor) InsertText ¶
func (le *LineEditor) InsertText(text string)
InsertText inserts text at the cursor (MRI insert_text), advancing the cursor.
func (*LineEditor) Line ¶
func (le *LineEditor) Line() (string, bool)
Line returns the submitted line (whole buffer), or "" with ok=false at EOF (MRI LineEditor#line returns nil on eof).
func (*LineEditor) LineIndex ¶
func (le *LineEditor) LineIndex() int
LineIndex returns the index of the current line in a multiline buffer.
func (*LineEditor) MenuInfo ¶
func (le *LineEditor) MenuInfo() ([]string, bool)
MenuInfo returns the pending completion menu candidates (and whether a menu is active). Rendering of the menu is the embedder's concern; the state lives here.
func (*LineEditor) MultilineOff ¶
func (le *LineEditor) MultilineOff()
MultilineOff restricts editing to a single line (Enter finishes).
func (*LineEditor) MultilineOn ¶
func (le *LineEditor) MultilineOn()
MultilineOn enables multiline editing (Enter inserts a newline until the termination predicate accepts).
func (*LineEditor) Render ¶
func (le *LineEditor) Render(width int, promptProc PromptProc) RenderState
Render lays out the buffer for a terminal `width` wide using promptProc (which may be nil), returning the wrapped lines and cursor position. Pure: no IO.
func (*LineEditor) Reset ¶
func (le *LineEditor) Reset(prompt string)
Reset re-initializes the editor for a new read with the given prompt and refreshes the screen size from the IO seam.
func (*LineEditor) ResetLine ¶
func (le *LineEditor) ResetLine()
ResetLine clears the buffer to a single empty line with the cursor at home.
func (*LineEditor) SearchingPrompt ¶
func (le *LineEditor) SearchingPrompt() (string, bool)
SearchingPrompt returns the active incremental-search prompt and whether a search is in progress (exposed for the embedder's renderer).
func (*LineEditor) SetBytePointer ¶
func (le *LineEditor) SetBytePointer(v int)
SetBytePointer sets the cursor's byte offset (MRI byte_pointer=).
func (*LineEditor) SetCompletionAppendCharacter ¶
func (le *LineEditor) SetCompletionAppendCharacter(s string)
SetCompletionAppendCharacter sets the character appended after a unique completion (typically a space).
func (*LineEditor) SetCompletionProc ¶
func (le *LineEditor) SetCompletionProc(p CompletionProc)
SetCompletionProc installs the completion candidate generator.
func (*LineEditor) SetConfirmMultilineTermination ¶
func (le *LineEditor) SetConfirmMultilineTermination(p func(buffer string) bool)
SetConfirmMultilineTermination installs the predicate that decides whether Enter on the last line submits the buffer (true) or inserts a newline. The embedder (e.g. IRB) supplies one that checks for a complete Ruby expression.
func (*LineEditor) SetPastingState ¶
func (le *LineEditor) SetPastingState(inPasting bool)
SetPastingState toggles bracketed-paste batching: text typed while pasting is accumulated and force-inserted on exit (MRI set_pasting_state).
func (*LineEditor) Update ¶
func (le *LineEditor) Update(key Key) bool
Update feeds one key event through the dispatch + post-processing pipeline and returns whether the buffer changed (MRI update/input_key).
func (*LineEditor) WholeBuffer ¶
func (le *LineEditor) WholeBuffer() string
WholeBuffer returns the whole multiline buffer joined by newlines.
func (*LineEditor) WholeLines ¶
func (le *LineEditor) WholeLines() []string
WholeLines returns a copy of every buffer line.
type NullIO ¶
NullIO is a recording IO with a fixed default 24x80 screen, suitable as a default when no real terminal is wired (the pure state machine never blocks on it in tests). It captures writes and cursor ops for inspection.
func (*NullIO) EraseAfterCursor ¶
func (n *NullIO) EraseAfterCursor()
EraseAfterCursor records an erase request as a sentinel write.
func (*NullIO) GetScreenSize ¶
GetScreenSize returns the configured size (defaulting to 24x80).
func (*NullIO) MoveCursorColumn ¶
MoveCursorColumn records the requested cursor column.
type PromptProc ¶
PromptProc, when set, maps the buffer lines to per-line prompts (MRI prompt_proc). When nil, a single prompt is used for line 0 and "" for the rest.
type RenderState ¶
type RenderState struct {
// Lines are wrapped display rows as (prompt, content) pairs.
Lines [][2]string
// CursorX is the cursor column within its wrapped row.
CursorX int
// CursorY is the cursor row index into Lines.
CursorY int
}
RenderState is the pure result of laying out the current buffer for a terminal of the given width: the visible (prompt, content) line pairs after word wrapping, and the cursor's (x, y) in that wrapped grid. This is the "rendering-to-output" computation; writing it to the tty is the IO seam.
