readline.c File Reference

Line editing support with history. More...

#include "readline.h"
#include <cfg/compiler.h>
#include <string.h>
#include <cfg/debug.h>
#include <stdio.h>

Go to the source code of this file.

Defines

#define DEBUG_UNIT_TEST   0
 Enable compilation of the unit test code.
#define DEBUG_DUMP_HISTORY   0
 Enable dump of the history after each line.
#define IS_WORD_SEPARATOR(c)   ((c) == ' ' || (c) == '\0')
 Check if c is a separator between words.

Enumerations

enum  RL_KEYS
 

Special keys (escape sequences converted to a single code).


Functions

void rl_puts (const struct RLContext *ctx, const char *txt)
 Write the string txt to the IO output (without any kind of termination).
void rl_putc (const struct RLContext *ctx, char ch)
 Write character ch to the IO output.
static bool rl_getc (const struct RLContext *ctx, int *ch)
 Read a character from the IO into ch.
bool is_history_begin (struct RLContext *ctx, int i)
 Check if index i points to the begin of the history.
bool is_history_end (struct RLContext *ctx, int i)
 Check if index i points to the (exclusive) end of history.
bool is_history_past_end (struct RLContext *ctx, int i)
 Check if index i points to the (exclusive) end of history, or somewhere past the end.
static bool insert_chars (struct RLContext *ctx, size_t *curpos, const char *ch, int num_chars)
 Insert num_chars characters from ch into the history buffer at the position indicated by curpos.
static bool insert_char (struct RLContext *ctx, size_t *curpos, char ch)
 Insert a single character ch into the buffer (with the same semantic of insert_chars()).
static bool complete_word (struct RLContext *ctx, size_t *curpos)
 Complete the current word. Return false if no unambiguous completion was found.

Detailed Description

Line editing support with history.

Rationale for basic implementation choices:

  • The history is implemented storing consecutive ASCIIZ strings within an array of memory. When the history is full, the first (oldest) line is cancelled and the whole buffer is memmoved to overwrite it and make room. while this is is obviously not the fastest algorithm (which would require the use of a circular buffer) it is surely good enough for this module, which does not aim at fast performances (line editing does not require to be blazingly fast).
  • The first character in the history is always \0, and it is used as a guard. By 'wasting' it in this way, the code actually gets much simpler in that we remove many checks when moving backward (i>0 and similar).
  • While editing, the current index points to the position of the buffer which contains the last character typed in (exactly like a stack pointer). This also allows to simplify calculations and to make easier using the last byte of history.
  • While editing, the current line is always kept null-terminated. This is important because if the user press ENTER, we must have room to add a \0 to terminate the line. If the line is as long as the whole history buffer, there would not be space for it. By always keeping the \0 at the end, we properly ensure this without making index checks harder.
  • When removing a line from the history (see pop_history()), instead of updating all the indices we have around, we move backward the pointer to the history we use. This way, we don't have to update anything. This means that we keep two pointers to the history: real_history always points to the physical start, while history is the adjusted pointer (that is dereference to read/write to it).
Author:
Giovanni Bajo <rasky@develer.com>

Definition in file readline.c.


Define Documentation

#define IS_WORD_SEPARATOR (  )     ((c) == ' ' || (c) == '\0')

Check if c is a separator between words.

Note:
Parameter c is evaluated multiple times

Definition at line 139 of file readline.c.


Function Documentation

static bool insert_chars ( struct RLContext *  ctx,
size_t *  curpos,
const char *  ch,
int  num_chars 
) [static]

Insert num_chars characters from ch into the history buffer at the position indicated by curpos.

If needed, remove old history to make room. Returns true if everything was successful, false if there was no room to add the characters.

Note:
num_chars can be 0, in which case we just make sure the line is correctly zero-terminated (ASCIIZ format).

Definition at line 270 of file readline.c.

static bool rl_getc ( const struct RLContext *  ctx,
int *  ch 
) [static]

Read a character from the IO into ch.

This function also takes care of converting the ANSI escape sequences into one of the codes defined in RL_KEYS.

Definition at line 162 of file readline.c.