readline clib CLI / Interactive

GNU readline interactive line editor for PascalAI. Build polished interactive CLI tools with cursor movement, command history, Tab completion, vi/emacs key bindings, and history persistence — the same engine used by bash, Python REPL, psql, and mysql.

ppm install readline

Overview

readline wraps GNU Readline — the interactive line-editing library that powers the bash shell, the Python REPL, PostgreSQL's psql, MySQL's mysql client, and hundreds of other CLI tools. It gives users the editing experience they already know from their shell, for free.

Key features: cursor movement within a line (not just backspace), searchable history (Ctrl+R), programmable Tab completion, persistent history files, and switchable vi/emacs key binding modes. All of this with a handful of function calls.

CLib package

Requires libreadline-dev. Ubuntu/Debian: sudo apt install libreadline-dev

Quick Start

Simple REPL

uses readline;

LoadHistory('/home/user/.myapp_history');

while True do
begin
  var line := ReadLineHistory('myapp> ');
  if line = '' then Break;   { Ctrl+D = EOF }

  { Process command... }
  WriteLn('You entered: ' + line);
end;

SaveHistory('/home/user/.myapp_history', 1000);

Custom Tab completion

uses readline;

SetWordList(['help', 'quit', 'load', 'save', 'list', 'show', 'delete']);

while True do
begin
  var cmd := ReadLineHistory('cmd> ');
  if cmd = 'quit' then Break;
  { Tab completes from the word list }
end;

Reading Input API

The core input functions. ReadLineHistory is the most common — it reads a line, adds it to history automatically, and lets the user edit with full cursor movement.

FunctionDescription
ReadLine(prompt)Display prompt and read a line. No history integration. Returns empty string on EOF (Ctrl+D).
ReadLineHistory(prompt)Like ReadLine but automatically adds non-empty lines to the in-memory history. The most common function.
ReadLineNoEcho(prompt)Read a line without echoing characters — use for passwords. History is not recorded.
ReadLineDefault(prompt, defaultText)Pre-fill the input buffer with defaultText; user can edit or accept with Enter
IsEOFReturns True if the last ReadLine call received EOF (Ctrl+D)
uses readline;

{ Pre-fill with a default value the user can edit }
var name := ReadLineDefault('Your name: ', 'Alice');

{ Password prompt — no echo }
var pass := ReadLineNoEcho('Password: ');

{ Loop until clean EOF }
var line := ReadLineHistory('> ');
while not IsEOF do
begin
  WriteLn('Got: ' + line);
  line := ReadLineHistory('> ');
end;

History API

Readline maintains an in-memory list of previous inputs. Users navigate it with the Up/Down arrow keys or Ctrl+R (reverse search). Persist it across sessions with LoadHistory / SaveHistory.

FunctionDescription
AddHistory(line)Manually add a line to the in-memory history list
LoadHistory(path)Load history from a file into memory (call at startup)
SaveHistory(path, maxLines)Write the current in-memory history to a file, keeping at most maxLines entries
AppendHistory(path, count)Append only the count most recent entries to an existing history file (efficient for long sessions)
ClearHistoryRemove all entries from the in-memory history list
HistoryLengthReturn the number of entries currently in memory
GetHistoryEntry(index)Return the history line at position index (0-based, oldest first)
RemoveHistoryEntry(index)Delete a specific entry from the history list
SetHistoryMaxLength(n)Limit the in-memory list to n entries; older entries are dropped automatically
uses readline;

LoadHistory('/home/user/.myapp_history');
SetHistoryMaxLength(500);

{ Run REPL... }

{ At exit: append new entries only }
AppendHistory('/home/user/.myapp_history', 50);
WriteLn('Session history: ' + IntToStr(HistoryLength) + ' entries');

Completion API

Tab completion is one of readline's most valuable features. The simplest approach is providing a static word list; the library handles prefix matching automatically.

FunctionDescription
SetWordList(words)Provide a static list of completion candidates. Tab cycles through words that match what the user has typed so far.
AddCompletionWord(word)Add a single word to the current completion list
ClearCompletionWordsRemove all completion words (e.g. to swap context-sensitive lists)
SetFilenameCompletionSwitch to readline's built-in filename/path completion (the default bash behavior)
DisableCompletionTurn off Tab completion entirely
uses readline;

{ Static word list }
SetWordList(['connect', 'disconnect', 'status',
             'list-topics', 'subscribe', 'publish', 'exit']);

{ Switch to filename completion when user types "load " }
var cmd := ReadLineHistory('broker> ');
if cmd = 'load' then
begin
  SetFilenameCompletion;
  var path := ReadLineHistory('file> ');
  SetWordList(['connect', 'disconnect', 'status']);  { restore }
end;

Configuration API

Configure readline behavior at startup. Settings persist for the process lifetime unless changed.

FunctionDescription
SetEditMode(mode)Key binding mode: 'emacs' (default) or 'vi'
SetBellStyle(style)Bell on ambiguous completion: 'audible', 'visible', or 'none'
SetCompleteOnTab(enable)If False, Tab lists completions instead of cycling through them (default: True)
SetHorizontalScroll(enable)Scroll long lines horizontally instead of wrapping (default: False)
SetColoredCompletion(enable)Colorize completion matches (requires a terminal with ANSI support)
ReadInitFile(path)Load a readline init file (.inputrc format) for user-specific customization

Key Bindings API

Bind custom key sequences to named readline functions, or query what is currently bound. This is an advanced feature; most apps do not need it.

FunctionDescription
BindKey(keySeq, func)Bind a key sequence (e.g. '\\C-t') to a named readline function (e.g. 'transpose-chars')
UnbindKey(keySeq)Remove the binding for a key sequence
GetKeyBinding(keySeq)Return the function name currently bound to a key sequence, or empty string if unbound
ListBindingsReturn all current bindings as a newline-delimited string of key: function pairs

Utilities API

FunctionDescription
RLVersionReturn the readline library version string (e.g. '8.2')
GetTerminalWidthCurrent terminal column width (refreshed on SIGWINCH)
SetPromptColor(color)Wrap the prompt in ANSI color escape codes. Pass one of: 'red', 'green', 'blue', 'yellow', 'cyan', 'magenta', 'white', 'reset'
ResetTerminalRestore terminal settings if your program is interrupted while readline is active
RedisplayPromptRedraw the current prompt and input buffer (useful after asynchronous output)
uses readline;

SetPromptColor('cyan');
WriteLn('readline v' + RLVersion + ', terminal width: '
  + IntToStr(GetTerminalWidth) + ' cols');

var line := ReadLineHistory('> ');
{ If background thread prints output during input, redraw the prompt }
RedisplayPrompt;

Key Bindings Reference

Default emacs mode bindings (active by default). All standard shell shortcuts work out of the box.

KeyAction
Ctrl+AMove cursor to beginning of line
Ctrl+EMove cursor to end of line
Ctrl+WDelete word before cursor
Ctrl+KDelete from cursor to end of line (kill)
Ctrl+UDelete from cursor to beginning of line
Ctrl+RReverse incremental history search
Ctrl+SForward incremental history search
Ctrl+YYank (paste) last killed text
Ctrl+LClear screen and redisplay prompt
Ctrl+DEOF / delete character under cursor (EOF if line is empty)
Ctrl+CInterrupt (raises SIGINT)
Up / DownNavigate history (previous / next entry)
Left / RightMove cursor one character left / right
Alt+B / Alt+FMove cursor one word backward / forward
TabComplete current word (cycles or lists depending on SetCompleteOnTab)

vi mode commands

Enable with SetEditMode('vi'). Input starts in insert mode; press Esc to enter command mode.

Key (command mode)Action
h / lMove cursor left / right
w / bMove forward / backward one word
0 / $Move to beginning / end of line
xDelete character under cursor
dw / dbDelete word forward / backward
ddDelete entire line
i / aReturn to insert mode (before / after cursor)
k / jPrevious / next history entry
/Search history forward
?Search history backward
Async output tip

If your program writes output to stdout while readline is waiting for input (e.g. from a background goroutine or agent), call RedisplayPrompt after the write to keep the prompt and partial input visible and correctly positioned.

Package Info

Version1.0.0
Typeclib
C Librarylibreadline-dev
Authorgustavo

System Requirements

libreadline-dev

Ubuntu/Debian:
sudo apt install libreadline-dev

Used by

bash • zsh • Python REPL
psql • mysql • gdb
irb (Ruby) • node REPL

Functions

  • ReadLine
  • ReadLineHistory
  • ReadLineNoEcho
  • ReadLineDefault
  • IsEOF
  • AddHistory
  • LoadHistory / SaveHistory
  • AppendHistory
  • ClearHistory
  • HistoryLength
  • GetHistoryEntry
  • RemoveHistoryEntry
  • SetHistoryMaxLength
  • SetWordList
  • AddCompletionWord
  • ClearCompletionWords
  • SetFilenameCompletion
  • DisableCompletion
  • SetEditMode
  • SetBellStyle
  • SetCompleteOnTab
  • SetHorizontalScroll
  • SetColoredCompletion
  • ReadInitFile
  • BindKey / UnbindKey
  • GetKeyBinding
  • ListBindings
  • RLVersion
  • GetTerminalWidth
  • SetPromptColor
  • ResetTerminal
  • RedisplayPrompt

See Also