repl

package
v0.0.2-alpha Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package repl is a Bubble Tea REPL component: a prompt line with arrow-key editing, up/down command history, styled output, and a caller-supplied evaluator callback.

The component renders ONLY the input line via View(). Everything else — banner, echoed input, evaluator output, errors — is pushed into the terminal's scrollback via tea.Println. This matches how native REPLs (psql, iex, python) behave: the prompt stays at the bottom, output flows above it, and the terminal handles scroll, selection, and history natively.

m := repl.New(repl.Options{
    Prompt:    "myapp(teal)> ",
    Banner:    "hex repl — teal mode. Ctrl+D or \"exit\" to quit.",
    Evaluator: func(line string) repl.Result {
        return repl.Result{Output: "hi"}
    },
})

if _, err := tea.NewProgram(m).Run(); err != nil { ... }

The evaluator runs synchronously inside Update, so slow operations block the render loop — acceptable for the REPL case where users wait on each line anyway.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Candidate

type Candidate struct {
	// Text is the full text that should replace the range from
	// PrefixStart to the cursor when this candidate is chosen.
	Text string

	// Display is an optional label shown in a completion popup.
	// v1 doesn't render a popup; Text is used everywhere. Reserved
	// for future use.
	Display string

	// Kind is an optional semantic tag ("function", "table",
	// "module", ...). Currently informational only.
	Kind string
}

Candidate is a single tab-completion suggestion.

type Completer

type Completer func(mode, input string, cursorPos int) (candidates []Candidate, prefixStart int)

Completer produces tab-completion candidates for the given input.

input      the full current input line
cursorPos  the byte position of the cursor within input

Returns the candidates and the byte offset at which the current prefix begins. The REPL replaces input[prefixStart:cursorPos] with the chosen candidate's Text.

Empty candidates means "no completion available here"; the Tab key falls through to whatever textinput does with it (usually nothing, since Tab is not a typing character).

type Evaluator

type Evaluator func(mode, line string) Result

Evaluator is the callback invoked for every submitted line. Mode carries the name of the active Mode at submission time, letting callers dispatch to different runtimes (e.g. Teal vs Lua) without juggling closures per mode.

type Mode

type Mode struct {
	// Name is what gets passed to the Evaluator. Required and
	// unique within Options.Modes.
	Name string

	// Activator is the rune that switches TO this mode when typed
	// on an empty prompt. Zero means the mode is not
	// user-selectable (e.g. a default that only reachable via
	// backspace).
	Activator rune

	// Prompt is the string rendered before the input line while
	// this mode is active, e.g. "myapp(teal)> ".
	Prompt string

	// ContinuationPrompt is rendered when the previous submission
	// returned Result.Incomplete, so the user sees that their input
	// is being buffered. When empty, defaults to Prompt — typically
	// callers pass a same-width variant that swaps "> " for ". "
	// or "... " so column alignment is preserved.
	ContinuationPrompt string

	// PromptColor, when non-nil, overrides the base Styles.Prompt's
	// foreground for this mode. Any nil defers to the base style.
	PromptColor lipgloss.TerminalColor
}

Mode describes a REPL mode — a language or command surface the user can switch to. Julia's REPL popularised this pattern with `?` (help), `;` (shell), `]` (pkg); we generalise it: any rune pressed at an empty prompt swaps modes, and backspace at an empty prompt in a non-default mode reverts to the default.

type Model

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

Model is the bubble tea model for the REPL.

func New

func New(opts Options) Model

New builds a Model.

func (Model) CurrentMode

func (m Model) CurrentMode() string

CurrentMode returns the active mode's Name. Useful for tests and callers that want to observe or persist the mode across sessions.

func (Model) Echoes

func (m Model) Echoes() []string

Echoes returns every line the model would push into the terminal via tea.Println: banner, echoed prompts+input, evaluator output, evaluator errors — in order. Used by tests.

func (Model) History

func (m Model) History() []string

History returns a copy of the current in-memory command history. Useful for persisting between sessions.

func (Model) InContinuation

func (m Model) InContinuation() bool

InContinuation reports whether the REPL is currently waiting for the user to finish a multi-line input.

func (Model) Init

func (m Model) Init() tea.Cmd

Init satisfies tea.Model. Emits the banner (if any) into scrollback and starts the cursor blink.

func (Model) SetHistory

func (m Model) SetHistory(h []string) Model

SetHistory replaces the in-memory history. Useful for restoring a previous session's log on startup.

func (Model) SetStyles

func (m Model) SetStyles(s Styles) Model

SetStyles replaces the style set. Return the modified model — Bubble Tea models are value types.

func (Model) Styles

func (m Model) Styles() Styles

Styles returns the current style set for read-only inspection.

func (Model) Submissions

func (m Model) Submissions() []string

Submissions returns lines that were submitted to the evaluator (empty lines excluded). Used by tests to assert behaviour without intercepting tea.Cmd streams.

func (Model) Update

func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update handles messages: key presses (submit, history navigation, exit) and forwards the rest to the textinput. Never mutates fields via pointer-only builders — everything is copy-safe.

func (Model) View

func (m Model) View() string

View renders ONLY the prompt + input line. All output — banner, echoed submissions, evaluator results — goes into the terminal's scrollback via tea.Println, so scroll wheel, selection, and shell history all continue to work as the user expects.

type Options

type Options struct {
	// Prompt is the string shown before the input line when Modes
	// is empty (single-mode REPL). Defaults to "> ". Ignored when
	// Modes is set — each mode carries its own prompt.
	Prompt string

	// ContinuationPrompt is used in single-mode configurations when
	// the previous submission returned Result.Incomplete. Defaults
	// to Prompt (so continuation is visually indistinguishable
	// unless the caller sets this to something like "... ").
	ContinuationPrompt string

	// Completer, when non-nil, is called on Tab to compute
	// completions for the current input line. See Completer's
	// godoc for the contract.
	Completer Completer

	// Banner is optional multi-line text printed above the first
	// prompt. Newlines are respected.
	Banner string

	// Evaluator is called for each submitted line. Required.
	Evaluator Evaluator

	// Modes are the switchable modes. The first mode is the
	// default; users switch to another mode by typing its
	// Activator rune on an empty prompt, and return to the default
	// by pressing Backspace on an empty prompt.
	//
	// Empty means single-mode: the evaluator sees mode="" and
	// Prompt/Banner behave as before.
	Modes []Mode

	// HistoryLimit caps the in-memory command history. 0 or
	// negative means unlimited.
	HistoryLimit int
}

Options configures a new Model.

type Result

type Result struct {
	// Output is normal (stdout-like) content, rendered in the
	// default style.
	Output string

	// Err is error-like content, rendered in the error style
	// (a subdued red by default).
	Err string

	// Exit requests the REPL loop to terminate cleanly.
	Exit bool

	// Incomplete signals that the submitted input is syntactically
	// incomplete — e.g. an unclosed function block or table literal.
	// The REPL switches to a continuation prompt and buffers the
	// user's next line onto the current one instead of evaluating.
	// Output and Err are ignored when Incomplete is true.
	Incomplete bool
}

Result is what the evaluator returns for one submitted line.

type Styles

type Styles struct {
	Prompt lipgloss.Style
	Input  lipgloss.Style
	Output lipgloss.Style
	Error  lipgloss.Style
	Banner lipgloss.Style
}

Styles groups the lipgloss styles the component uses.

func DefaultStyles

func DefaultStyles() Styles

DefaultStyles returns hex's default palette, tuned for readability against both light and dark terminals via AdaptiveColor.

Prompt: a calm cyan-blue (bold), matching the charm accent line. Error: a muted red (not the alarming bright red). Banner: dim gray.

Jump to

Keyboard shortcuts

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