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