Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

REPL

basalt repl is an interactive session: type a statement, see its result, and keep the session’s connections and functions from one entry to the next.

Results

The REPL is where a person looks at data, so there the table is fitted to the terminal: a row of types under the names, numbers right-aligned, NULL spelled out, cells cut at 40 columns, and … for what does not fit — the middle columns, in the manner of pandas, and the middle rows past 40. The footer always gives the true size:

 id  customer_name       amount  …  country  last_col
int  string               float  …  string   string
---  ------------------  ------  …  -------  --------
  0  customer number 0        0  …  BR       tail-0
  …  …                        …  …  …        …
 99  customer number 99   148.5  …  BR       tail-99
(100 rows × 10 columns, 5 shown — \view scrolls it)

A REPL result keeps its first 10,000 rows (and the last 20) rather than all of it. Values are coloured by their column’s type — numbers cyan and a negative one red, dates and times magenta, true green and false red, arrays and structs yellow, NULL dim — with the names bold and the types dim; only foreground colours, so a light terminal reads it as well as a dark one. Set NO_COLOR to drop all of it.

Viewing a result

In the REPL, \view (or \v) opens the last result full-screen, the names and types pinned. ←/→ move a column cursor (its name lit; the view follows it), ↑/↓ scroll by row, Ctrl-arrows and PgUp/PgDn move a screenful, Home/End jump to the first and last columns, g/G to the first and last rows, q leaves. s sorts by the cursor’s column — ascending, again descending, again off; by value for a number, as text otherwise (which orders ISO dates rightly), NULL last either way. / filters it as you type: text keeps the rows containing it in any case, !text those that do not, and >= 100, < 2026-01-01, = SP, != 0 compare — by value on a number column. Filters on several columns all apply; the header marks a filtered column ≈ and the sorted one ↑/↓. Enter keeps a filter, Esc while typing puts it back, Esc after clears the filters and then the sort. f finds text across every column: type the search and press Enter, and the rows narrow to those holding it, each match highlighted where it shows. Words are AND-ed and may be in any column, -word keeps the rows without it, col:word looks in that column only, and "two words" is one phrase — all in any case, the rules of the language’s search, which runs the same search over a whole result in a query. a makes the find and the filters ignore accents as well as case (the status line says so), as search(…, true) does. f searches the rows kept; F searches the whole result instead: it runs the query that made it again — that SELECT alone, not the rest of its entry — narrowed by the search, and opens the view on what it finds. Esc clears a find before the filters and the sort. Sorting, filtering and f rearrange the rows kept and never run the query again — so on a result larger than 10,000 rows they see only the first 10,000, and the status line says so; F is the way past them.

Commands

basalt repl executes on a top-level ; and carries CREATE CONNECTION / CREATE FUNCTION / PARAM declarations across entries (re-declaring a name replaces it). Meta commands: \connections list the session’s declarations · \reset drop them · \clear (or clear, cls, ^L) clear the screen · \format table|json|csv|tsv switch result output · \view scroll, sort and filter the last result · \help · \q. Short forms: \c for \connections, \e for \edit, \f for \format, \v for \view, \source for \i; \h, help or ? for help, and \quit, :q, quit or exit to leave.

Editing

The entry is a small text editor rather than a single line, with an editor’s habits. Enter runs the entry when it ends in a top-level ; and the cursor is at its end; anywhere else it opens a line — and after ( it steps in and puts the ) on a line of its own. Ctrl+J runs the entry as it stands, ; or not (Ctrl+Enter too, where the terminal delivers it). Brackets and quotes close themselves, typing the closer steps over it, and over a selection they wrap it; the matching bracket is underlined. Alt+Up/Down move the line or selected lines, Shift+Alt+Up/Down duplicate them, Tab and Shift+Tab indent and dedent a selection, Ctrl+/ comments lines out with -- and back in, Esc drops the selection. The entry is coloured as you type (keywords, strings, numbers, comments, $params; NO_COLOR turns it off), a multi-line entry gets line numbers in its gutter, and a parse error is shown with a caret under the column it names.

Making a connection

\connect [type] makes a connection with a form: the type picked from a list (↑/↓, its number, or the first letters of its name), then the fields its connector needs on one screen — host with the type’s usual port, database, user, password (blank means the env(NAME_USER) / env(NAME_PASS) convention; env:VAR names another variable). ↑/↓ and Tab move between fields, ←/→ turn a choice such as tls or auth, a field edits with the entry’s own keys, Enter goes on and submits from the last field, Esc cancels with nothing made. A field only some answers need, such as the Kerberos realm, shows only then. It shows the CREATE CONNECTION it built (a typed password masked), registers it, and offers to reach it and to save it to the startup file. ^R searches the history incrementally (type to narrow, ^R for an older match, Enter keeps it). A session starts by running ~/.config/basalt/repl.sql (or $XDG_CONFIG_HOME/basalt/repl.sql) when it exists — the place for the connections you always want, with env() for the secrets — and \save writes the session’s declarations there (or to a named file); \i <file> runs any file so its declarations join the session; \connections shows them as a table with host, database and whether the session has reached them (\c test reaches each now); \edit opens the last entry in $EDITOR and runs what comes back.

Completion

Tab completes the word under the cursor: keywords (in the case you are typing), the session’s connections, functions and $params, the entry’s CTEs, a path inside an unclosed quote, conn. followed by that connection’s tables, the columns of every table and file the entry names, and the built-in functions — scalar, aggregate and window. Tables and columns are asked of the source once per session, on first use, through the same information_schema queries SHOW TABLES and DESCRIBE run. A lone match is taken; several fill in what they share and come up as a row of choices that Tab cycles through. Arrows travel the whole entry — Ctrl+arrows by word, Home/End the line, Ctrl+Home/End the entry — and Up or Down past its edge recall history, where an entry comes back whole however many lines it had (~/.basalt_history). Shift with any of those selects; typing, Backspace and Delete replace the selection. ^A selects all, ^C copies a selection (and drops the entry when there is none), ^X cuts, ^V pastes, ^Z/^Y undo and redo. A paste is inserted as text, never run line by line, and a copy reaches the system clipboard where the terminal supports OSC 52. Two things a terminal cannot deliver: the mouse, and Ctrl+Enter, which arrives as plain Enter.