This repository has been archived by the owner. It is now read-only.
A small, self-contained line editing library.
Switch branches/tags
Nothing to show
Clone or download
cyphar *: Cyphar -> Aleksa Sarai
Signed-off-by: Aleksa Sarai <>
Latest commit 1f860d0 Mar 28, 2016
Type Name Latest commit message Commit time
Failed to load latest commit information.
src *: Cyphar -> Aleksa Sarai Mar 28, 2016
tests *: Cyphar -> Aleksa Sarai Mar 28, 2016
.gitignore added some test code Sep 22, 2013
LICENSE *: relicensed under the MPLv2 Mar 23, 2016
Makefile *: Cyphar -> Aleksa Sarai Mar 28, 2016 *: relicensed under the MPLv2 Mar 23, 2016
TODO src: rawline: fixed prompt and escape code madness Dec 29, 2013


A small line editing library in C, intended to replace other "huge" libraries such as libedit and readline. Written in less than 1000 lines of MPLv2 licensed code.


  • Single line editing
  • History
  • Completion

Using rawline

Everything starts with a simple:

raw_t *raw_state = raw_new(<str>);

/* str is the string which raw_input() will return when
 * it recieves an abrubt return (ctrl-d, but not ctrl-c).
 * If str is NULL, then ctrl-d will act as a delete key. */

/* ... */


raw_state is the state of a rawline instance. You can have as many instances you want. rawline will handle all of the memory management inside of raw_state. raw_free will free all of the memory associated to raw_state.

It is important to understand that any allocated pointers returned by rawline (e.g. raw_hist_get() or raw_input()) are considered to be "part of" the raw_state structure, and shouldn't be touched. This means that you mustn't free it (which makes life easier for you), but it also means that the value will probably change with the next call to a rawline function. If you need the pointer for later use, memcpy (or strcpy) it to a safe location of your own.


By default, all options (except line editing) are disabled by default. The first argument and second argument are always the raw_state pointer and a bool reflecting whether you are enabling (1) or disabling (0) the option. When disabling an option, everything about that option is lost, including any buffers. This is noticable when working with history. Also, if you are disabling an option, the other arguments are ignored.


To (en/dis)able line history:

raw_hist(raw_state, <(en/dis)able>, <size of history buffer>);

/* If the number of lines of history is less than 1,
 * raw_hist will return -1, and nothing will change. */

You can also serialise (convert to a string) the entire history, and use a serialised string to replace an existing history.

char *history = raw_hist_get(raw_state); /* get the history */
raw_hist_set(raw_state, history); /* set the history */


Tab-completion requires a callback function, to give rawline a search table, based on input. There is no requirement for you to do any form of searching. Rawline uses a prefix completion search spec (see below).

To (en/dis)able tab-completion:

raw_comp(raw_state, <(en/dis)able>, search_callback, <search_cleanup or NULL>);

/* If search_cleanup is not defined, rawline will not attempt to free the pointer returned
 * by search_callback(input). If search_callback is not give (i.e. NULL), raw_comp() will
 * return -1 and nothing will change. */

Here are some sample search_callback() and search_cleanup() function definitions:

char **search_callback(char *input) {
	/* `input` is the input string when the user pressed <tab> */

	char **ret = NULL;

	/* If the returned search table is empty (the first item is NULL or
	 * the table itself is NULL), the input will be unaffected and the
	 * terminal will beep. */

	/* The search table *must* be terminated with a `NULL` pointer. This
	 * is used by rawline to find the end of the table (like '\0' terminators
	 * in C "strings" used to find the end by strlen(3) and others). */

	/* ... */

	return ret;

void search_cleanup(char **table) {
	/* This is the standard way to free (void **) */
	int i;
	for(i = 0; table[i] != NULL; i++)
Prefix completion?

Prefix completion is where the largest common "prefix" (starting from the input string) in a search table is matched, and no more. This is very similar to the technique bash uses. Here's some examples:

/* Assuming the following is the search table */
char **search_table = {
	"Hello, world!",
	"How many roads must a man walk down?",
	"How many streets must a man walk down?",
	"The only winning move is not to play."
	"This is a test",
	"This is a test of the emergency broadcast system.",

/* <input-before-tab-completion> ==> <input-after-tab-completion>*/

"H"					==> "H" (beep)
"He"				==> "Hello, world!"

"Ho"				==> "How many "
"How many r"		==> "How many roads must a man walk down?"
"How many s"		==> "How many streets must a man walk down?"

"T"					==> "T" (beep)
"Th"				==> "Th" (beep)
"The only winn"		==> "The only winning move is not to play."
"This "				==> "This is a test"
"This is a test "	==> "This is a test of the emergency broadcast system."

/* Dummy matches aren't modified */

""					==> "" (beep)
"A strange game."	==> "A strange game." (beep)