Readline

Compilacion

Para poder utilizar la funciΓ³n readline() en un programa de C, es necesario tener instalada la biblioteca GNU Readline o editline en el sistema. Estas bibliotecas proporcionan la funcionalidad de readline() y otras funciones adicionales.

Para incluir la biblioteca en el cΓ³digo, es necesario incluir la cabecera #include <readline/readline.h> o #include <editline/readline.h> dependiendo de la biblioteca que se tenga instalada, en el archivo fuente donde se quiere usar readline().

Para compilar el programa, es necesario indicar al compilador que se desea vincular con la biblioteca de readline. Esto se puede hacer utilizando la opciΓ³n -lreadline o -leditline dependiendo de la biblioteca que se tenga instalada. Por ejemplo, si se estΓ‘ usando GCC, el comando para compilar el programa serΓ­a algo similar a esto:

gcc -o programa programa.c -leditline

Instalar readline

Por otro lado para poder utilizar otras fucniones como rl_clear_history() o rl_replace_line() es necesariao tener instalada la libreria readline. Para ello tan solo tenemos que instalarla con brew, brew install readline, y depues aΓ±adir su cabezera a nuestro fichero. #include<readline/readline.h>.

Ademas es necesariao hacer referencia a dicha libreria a la hora de compilar:

gcc programa.c  -lreadline -L /Users/$(USER)/.brew/opt/readline/lib -I /Users/$(USER)/.brew/opt/readline/include

Readline

La funciΓ³n readline() es una funciΓ³n de biblioteca que permite a los programas de C leer lΓ­neas de entrada del usuario de una manera conveniente.

char * readline(const char * prompt)

La funciΓ³n toma un solo argumento, que es una cadena de caracteres que se utiliza como un prompt para indicar al usuario que debe ingresar informaciΓ³n. La funciΓ³n devuelve un puntero a una cadena de caracteres que contiene la lΓ­nea de entrada del usuario.

La forma en que la funciΓ³n readline() funciona es mediante la lectura de caracteres desde el flujo de entrada estΓ‘ndar (stdin) hasta que se encuentra un carΓ‘cter de nueva lΓ­nea ('\n') o se alcanza el final de archivo (EOF). Cada carΓ‘cter leΓ­do se agrega a un buffer temporal, hasta que se alcanza el carΓ‘cter de nueva lΓ­nea o el final del archivo.

Una vez que se ha leΓ­do una lΓ­nea completa, la funciΓ³n readline() asigna memoria dinΓ‘mica para almacenar una copia de la lΓ­nea de entrada. Esta memoria se debe liberar manualmente despuΓ©s de usarla con la funciΓ³n free() para evitar fugas de memoria.

AquΓ­ tienes un ejemplo de cΓ³mo usar la funciΓ³n readline() en un programa de C:

#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>

int main() {
    char *line;

    // Mostrar el prompt al usuario y leer la lΓ­nea de entrada
    line = readline("Ingresa una lΓ­nea de texto: ");

    // Imprimir la lΓ­nea de entrada
    printf("La lΓ­nea ingresada es: %s\n", line);

    // Liberar la memoria asignada para la lΓ­nea de entrada
    free(line);

    return 0;
}

En este ejemplo, se incluyen las cabeceras necesarias para usar la funciΓ³n readline(), que en este caso es readline/readline.h. La funciΓ³n readline() se llama con un prompt "Ingresa una lΓ­nea de texto: " y el resultado se almacena en una variable char* llamada "line". El contenido de la linea se imprime con printf y luego se libera la memoria con free.

Historial

El historial en readline() es una funcionalidad que permite al usuario recuperar lΓ­neas de entrada previamente ingresadas usando las flechas arriba y abajo. Esto es ΓΊtil cuando el usuario desea volver a ingresar una lΓ­nea de comando que ya ha utilizado previamente, o si desea verificar una lΓ­nea de comando anterior.

Cada vez que se utiliza la funciΓ³n readline() para leer una lΓ­nea de entrada del usuario, esa lΓ­nea se agrega automΓ‘ticamente al historial. El usuario puede navegar por el historial de lΓ­neas utilizando las flechas arriba y abajo. Cada vez que se presiona la flecha arriba, readline() mostrarΓ‘ la lΓ­nea anterior en el historial, y cada vez que se presiona la flecha abajo, readline() mostrarΓ‘ la lΓ­nea siguiente en el historial.

AdemΓ‘s, el usuario tambiΓ©n puede buscar en el historial de lΓ­neas ingresadas mediante el uso de comandos como ctrl + R, esto le permitirΓ‘ buscar una lΓ­nea especΓ­fica en el historial.

La capacidad de guardar el historial de lΓ­neas es configurable, el usuario puede limitar la cantidad de lΓ­neas que se guardan en el historial o deshabilitarlo completamente. TambiΓ©n se puede cambiar la ubicaciΓ³n donde se guarda el historial, ya sea en un archivo o en memoria.

Es importante tener en cuenta que esta funcionalidad solo estarΓ‘ disponible si se tiene una biblioteca como GNU Readline o editline instalada y se incluye en el cΓ³digo.

add_history()

add_history() es una funciΓ³n proporcionada por la biblioteca GNU Readline que permite agregar una lΓ­nea al historial.

void add_history(const char *line);

La funciΓ³n add_history() tiene un solo argumento, que es un puntero a una cadena de caracteres que representa la lΓ­nea que se desea agregar al historial. Este argumento es obligatorio, si no se proporciona una cadena de caracteres la funciΓ³n no agregarΓ‘ nada al historial.

  • line es un puntero a una cadena de caracteres, es la lΓ­nea que se desea agregar al historial.

La funciΓ³n add_history() se utiliza para agregar una lΓ­nea al historial, esta lΓ­nea se agrega al final del historial y se convierte en la lΓ­nea actual. Esto es ΓΊtil cuando el usuario desea agregar una lΓ­nea al historial despuΓ©s de haber utilizado readline() o cuando se quieren agregar lΓ­neas de forma programΓ‘tica al historial. Es importante tener en cuenta que esta funciΓ³n no afecta al archivo de historial, si se tiene un archivo de historial configurado sigue existiendo.

La funciΓ³n read_history() y write_history() permiten trabajar con el archivo de historial, permitiendo cargarlo o guardarlo en disco, respectivamente.

AquΓ­ te dejo un ejemplo de cΓ³mo utilizar el historial de lΓ­neas utilizando readline() y add_history() en un programa:

#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>

int main() {
    char *line;
    int i;
    for(i = 0; i < 5; i++) {
        line = readline("Ingresa una lΓ­nea de texto: ");
        add_history(line);
    }
    while(1) {
        line = readline("Ingresa una lΓ­nea de texto (o presiona ctrl + c para salir): ");
        if(line != NULL) {
            printf("La lΓ­nea ingresada es: %s\n", line);
        } else {
            break;
        }
    }
    return 0;
}

rl_clear_history

rl_clear_history() es una funciΓ³n proporcionada por la biblioteca GNU Readline que permite limpiar todas las lΓ­neas almacenadas en el historial. Esta funciΓ³n no requiere ningΓΊn parΓ‘metro y no devuelve ningΓΊn valor.

La funcionalidad de esta funciΓ³n es eliminar todas las lΓ­neas almacenadas en el historial. Una vez que se llama a esta funciΓ³n, el historial quedarΓ‘ vacΓ­o y no habrΓ‘ lΓ­neas disponibles para recuperar con las flechas arriba y abajo. Es importante tener en cuenta que esta funciΓ³n no afecta al archivo de historial, si se tiene un archivo de historial configurado sigue existiendo.

AquΓ­ te dejo un ejemplo de cΓ³mo utilizar esta funciΓ³n en un programa:

#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>

int main() {
    char *line;
    int i;
    for(i = 0; i<10; i++) {
        line = readline("Ingresa una lΓ­nea de texto: ");
        add_history(line);
    }
    printf("Historial antes de limpiar: %d\n", history_length);
    rl_clear_history();
    printf("Historial despues de limpiar: %d\n", history_length);
    return 0;
}

En este ejemplo se agrega 10 lΓ­neas al historial, luego se llama a la funciΓ³n rl_clear_history() y se imprime el tamaΓ±o del historial antes y despuΓ©s de limpiarlo. El resultado seria "Historial antes de limpiar: 10" y "Historial despues de limpiar: 0"

rl_on_new_line

rl_on_new_line() es una funciΓ³n proporcionada por la biblioteca de lectura GNU que se utiliza para indicar al sistema que se ha movido a una nueva lΓ­nea vacΓ­a. Esto es ΓΊtil para actualizar el estado interno del sistema de lectura de lΓ­nea de comandos, ya que permite realizar tareas como la actualizaciΓ³n del historial de comandos, la limpieza de la pantalla, la actualizaciΓ³n de la posiciΓ³n del cursor, entre otras.

La firma de la funciΓ³n es:

void rl_on_new_line(void);

La funciΓ³n no recibe argumentos.

Un ejemplo de uso de rl_on_new_line() podrΓ­a ser el siguiente:

#include <stdio.h>
#include <readline/readline.h>

int main(void) {
    while (1) {
        char *input = readline("Enter a command: ");
        printf("You entered: %s\n", input);
        rl_on_new_line();
    }
    return 0;
}

En este ejemplo, la funciΓ³n rl_on_new_line() se llama despuΓ©s de que el usuario ingresa un comando y se imprime en pantalla. Esto indica al sistema que se ha movido a una nueva lΓ­nea vacΓ­a y permite que el sistema actualice su estado interno para el prΓ³ximo comando del usuario. Sin embargo, es importante tener en cuenta que esta funciΓ³n no ejecuta ninguna acciΓ³n especΓ­fica, sΓ³lo indica al sistema que se ha movido a una nueva lΓ­nea vacΓ­a.

Si en el ejemplo anterior no se utiliza la funciΓ³n rl_on_new_line(), el sistema de lectura de lΓ­nea de comandos no serΓ­a capaz de actualizar su estado interno correctamente. Esto podrΓ­a tener varias consecuencias, dependiendo de las funcionalidades que se estΓ©n utilizando. Algunas posibles consecuencias incluyen:

  • El historial de comandos podrΓ­a no actualizarse correctamente, lo que podrΓ­a dificultar el acceso a comandos previamente ingresados.

  • La posiciΓ³n del cursor podrΓ­a no actualizarse correctamente, lo que podrΓ­a causar problemas al ingresar nuevos comandos.

  • La pantalla podrΓ­a no limpiarse correctamente, lo que podrΓ­a causar problemas de visualizaciΓ³n al ingresar nuevos comandos.

En general, la falta de llamada a la funciΓ³n rl_on_new_line() puede causar problemas en la funcionalidad del sistema de lectura de lΓ­nea de comandos y afectar al uso de la aplicaciΓ³n. Es importante tener en cuenta que esta funciΓ³n es necesaria para actualizar el estado interno del sistema de lectura de lΓ­nea de comandos, y su omisiΓ³n puede causar problemas en el funcionamiento de la aplicaciΓ³n.

rl_replace_line

La funciΓ³n rl_replace_line() es una funciΓ³n de la biblioteca de lectura de lΓ­nea de comandos de GNU (readline) que se utiliza para reemplazar el contenido actual de la lΓ­nea de comandos con una nueva cadena de texto. Esta funciΓ³n se utiliza para actualizar la lΓ­nea de comandos con nueva informaciΓ³n, por ejemplo, cuando se desea mostrar informaciΓ³n adicional al usuario mientras se ingresa un comando.

La cabecera de esta funciΓ³n es la siguiente:

void rl_replace_line (const char *string, int clear_undo)

Los argumentos de esta funciΓ³n son:

  • string: Es un puntero a una cadena de caracteres que contiene el nuevo texto que se desea utilizar para reemplazar la lΓ­nea actual.

  • clear_undo: es un valor booleano que indica si se debe limpiar el historial de deshacer al reemplazar la lΓ­nea de comandos.

La funciΓ³n rl_replace_line() funciona reemplazando el contenido actual de la lΓ­nea de comandos con la cadena de texto especificada en el argumento string. Si se especifica 1 en el argumento clear_undo, el historial de deshacer se limpia automΓ‘ticamente al reemplazar la lΓ­nea de comandos. Si se especifica 0, el historial de deshacer no se limpia.

AquΓ­ te dejo un ejemplo de cΓ³digo que utiliza solo la funciΓ³n rl_replace_line:

#include <stdio.h>
#include <readline/readline.h>

int main() {
    char *input;
    input = readline("Enter a line of text: ");
    printf("You entered: %s\n", input);
    rl_replace_line("This is the new line", 0);
    rl_redisplay();
    input = readline("Enter another line of text: ");
    printf("You entered: %s\n", input);
    return 0;
}

En este ejemplo, primero se solicita al usuario que ingrese una lΓ­nea de texto a travΓ©s de la funciΓ³n readline(). Luego, se imprime el valor introducido y se reemplaza la lΓ­nea actual con el texto "This is the new line" utilizando la funciΓ³n rl_replace_line. Se llama a rl_redisplay() para actualizar la pantalla y se vuelve a solicitar al usuario que ingrese otra lΓ­nea de texto. En este caso, no se utiliza la variable rl_line_buffer, pero se esta usando rl_replace_line para reemplazar el texto en la lΓ­nea actual y rl_redisplay para actualizar el prompt.

El output del ejemplo anterior serΓ­a algo similar a esto:

Enter a line of text: Hello World!
You entered: Hello World!
This is the new line
Enter another line of text: 
You entered: 

La funciΓ³n rl_replace_line reemplaza el contenido actual de la lΓ­nea de entrada en readline con el texto especificado en el primer argumento. El segundo argumento indica si se mueve el cursor al principio de la lΓ­nea despuΓ©s del reemplazo.

En el ejemplo que te di, despuΓ©s de llamar a rl_replace_line con el texto "This is the new line", la prΓ³xima vez que se llame a readline() el buffer de entrada tendrΓ‘ ese texto en lugar del que fue ingresado previamente. Por eso se muestra en la siguiente llamada a readline(). Esto se puede apreciar en el sigueinte ejemplo:

#include <stdio.h>
#include <readline/readline.h>

int main() {
    char *input = "";
    char *new_line = "This is the new line content";

    // get initial input
    input = readline("Enter some text: ");
    printf("Original input: %s\n", input);

    // replace the current line with new content
    rl_replace_line(new_line, 0);
    printf("New input: %s\n", rl_line_buffer);

    return 0;
}

En este ejemplo, primero se solicita al usuario que ingrese una lΓ­nea de texto a travΓ©s de la funciΓ³n readline(). Luego, se imprime el valor introducido y se reemplaza la lΓ­nea actual con el texto "This is the new line" utilizando la funciΓ³n rl_replace_line. Se llama a rl_redisplay() para actualizar la pantalla y se vuelve a solicitar al usuario que ingrese otra lΓ­nea de texto. En este caso, no se utiliza la variable rl_line_buffer, pero se esta usando rl_replace_line para reemplazar el texto en la lΓ­nea actual y rl_redisplay para actualizar el prompt.

rl_line_buffer es una variable global proporcionada por el encabezado readline/readline.h. No es necesario inicializarla ya que ya estΓ‘ inicializada por defecto al momento de incluir el encabezado. Puede ser utilizada en cualquier parte de tu programa despuΓ©s de incluir el encabezado readline/readline.h. Esta variable almacena el contenido actual de la lΓ­nea de comando y se actualiza automΓ‘ticamente cada vez que se llama a una funciΓ³n de readline, como rl_replace_line.

rl_line_buffer guarda el ΓΊltimo valor introducido a travΓ©s de una funciΓ³n de readline, como readline() o rl_replace_line().

Buffer de entarda

En el contexto de la biblioteca readline, el buffer de entrada es una variable que contiene la lΓ­nea de texto que el usuario ha ingresado. Cada vez que se llama a la funciΓ³n readline(), el usuario ingresa una lΓ­nea de texto y esta lΓ­nea se almacena en el buffer de entrada. La funciΓ³n readline() devuelve un puntero al buffer de entrada, por lo que se puede acceder al contenido de la lΓ­nea ingresada mediante este puntero.

La funciΓ³n rl_replace_line(), permite modificar el contenido del buffer de entrada, permitiendo al programador reemplazar el contenido anterior con uno nuevo. Una vez llamada esta funcion, se debe llamar a rl_redisplay() para que el nuevo contenido sea mostrado en pantalla.

rl_redisplay

La funciΓ³n rl_redisplay() es una funciΓ³n de la biblioteca readline que se utiliza para actualizar la lΓ­nea de entrada mostrada en la pantalla. Esta funciΓ³n no tiene argumentos y no devuelve ningΓΊn valor.

La funciΓ³n rl_redisplay() se utiliza despuΓ©s de haber realizado cambios en la lΓ­nea de entrada mediante otras funciones de la biblioteca readline, como rl_replace_line(). Sin llamar a esta funciΓ³n, los cambios realizados en la lΓ­nea de entrada no se mostrarΓ­an en pantalla.

Esta funciΓ³n no tiene argumentos y no tiene un valor de retorno. La cabecera de la funciΓ³n es la siguiente

void rl_redisplay (void);

En cuanto a un ejemplo de uso, si tienes el siguiente cΓ³digo:

#include <stdio.h>
#include <readline/readline.h>

int main() {
    char *input;
    input = readline("Enter a line of text: ");
    printf("You entered: %s\n", input);
    rl_replace_line("This is the new line", 0);
    rl_redisplay();
    input = readline("Enter another line of text: ");
    printf("You entered: %s\n", input);
    return 0;
}

El output serΓ­a:

Enter a line of text: AAAA
You entered: AAAA
This is the new line
Enter another line of text: SSS
You entered: SSS

En este ejemplo, se utiliza la funciΓ³n rl_replace_line para reemplazar el contenido de la lΓ­nea actual con el texto "This is the new line". Luego se llama a rl_redisplay() para actualizar la lΓ­nea en la terminal. En la siguiente llamada a readline(), se mostrarΓ‘ el nuevo contenido de la lΓ­nea en lugar del valor anterior. Si no se llama a rl_redisplay() despuΓ©s de usar rl_replace_line(), el nuevo contenido de la lΓ­nea no se mostrarΓ‘ en la terminal.

Si no utilizas la funciΓ³n rl_redisplay, entonces la lΓ­nea actual de texto no se actualizarΓ‘ en la interfaz de lΓ­nea de comandos. Es decir, el texto que reemplazaste con la funciΓ³n rl_replace_line no se mostrarΓ‘ en pantalla, y el usuario seguirΓ­a viendo el texto anterior. Sin la llamada a rl_redisplay, la funciΓ³n rl_replace_line solo actualiza el buffer interno de readline, pero no actualiza lo que se ve en la pantalla.

Last updated