Skip to main content

Modules/readline.c

Source:

cpython 3.14 @ ab2d84fe1023/Modules/readline.c

readline binds GNU Readline (or libedit on macOS) to provide line editing, history, and tab completion in the interactive REPL.

Map

LinesSymbolRole
1-80Module initDetect GNU Readline vs libedit; set _USING_LIBEDIT
81-200parse_and_bindPass a Readline init string (e.g. "tab: complete")
201-350set_completer / get_completerRegister a Python callable as the tab-completion function
351-500on_completionC callback glue: calls Python completer, manages string memory
501-650History APIadd_history, get_history_length, read_history_file
651-800set_startup_hook / set_pre_input_hookHooks run at REPL prompt
801-1100PyOS_Readline hookOverride for interactive input used by the parser

Reading

parse_and_bind

// CPython: Modules/readline.c:190 readline_parse_and_bind_impl
static PyObject *
readline_parse_and_bind_impl(PyObject *module, const char *string)
{
/* Pass a Readline key binding or variable setting.
Examples:
"tab: complete" — bind Tab to completion
"set editing-mode vi" — vim key bindings
*/
char *copy = strdup(string);
if (!copy) return PyErr_NoMemory();
rl_parse_and_bind(copy);
free(copy);
Py_RETURN_NONE;
}

Completion callback

// CPython: Modules/readline.c:380 on_completion
static char *
on_completion(const char *text, int state)
{
/* Called by Readline for each successive completion.
state=0: first call; state>0: subsequent calls. */
if (state == 0) {
Py_XDECREF(readlinestate_global->completion_cache);
/* Call the Python completer: completer(text, state) */
PyObject *r = PyObject_CallFunction(
readlinestate_global->completer, "si", text, state);
readlinestate_global->completion_cache = r;
}
if (readlinestate_global->completion_cache == NULL ||
readlinestate_global->completion_cache == Py_None)
return NULL;
return strdup(PyUnicode_AsUTF8(readlinestate_global->completion_cache));
}

The Python completer protocol: f(text, 0) returns the first completion, f(text, 1) returns the second, etc. Returning None signals end of completions. rlcompleter.Completer implements this protocol.

History API

// CPython: Modules/readline.c:540 readline_add_history_impl
static PyObject *
readline_add_history_impl(PyObject *module, const char *line)
{
add_history(line); /* GNU Readline history API */
Py_RETURN_NONE;
}

// CPython: Modules/readline.c:610 readline_read_history_file_impl
static PyObject *
readline_read_history_file_impl(PyObject *module, PyObject *filename)
{
if (read_history(PyUnicode_AsUTF8(filename)) != 0) {
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filename);
return NULL;
}
Py_RETURN_NONE;
}

readline.read_history_file('~/.python_history') loads the session history.

PyOS_Readline integration

// CPython: Modules/readline.c:880 call_readline
/* readline installs this as PyOS_ReadlineFunctionPointer so the interactive
REPL uses Readline for input instead of fgets(). */
static char *
call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
{
rl_outstream = sys_stdout;
char *p = readline(prompt); /* blocks until user presses Enter */
if (p) {
add_history(p);
...
}
return p;
}

gopy notes

gopy does not ship readline by default. The interactive REPL uses os.Stdin directly for input. When readline is needed, users can import readline which loads this module via dlopen of the system libreadline. The PyOS_ReadlineFunctionPointer hook is vm.ReadlineFn in vm/readline.go.