Dialog para crear diálogos en el terminal

Este es uno de los capítulos del tutorial Diálogos para scripts. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.

Seguro que este primer capítulo del tutorial te va a sorprender, porque si bien está pensado para crear diálogos para scripts, lo cierto es que son diálogos en el terminal. Evidentemente, este primer caso no es para usuarios que no quieran recurrir al terminal. Este primer capítulo, está pensado para utilizar tus scripts con diálogos en un servidor, en una máquina sin interfaz gráfico o directamente en el terminal. Esta primera herramienta se llama dialog, y como te comento, te será de utilidad para crear diálogos en el terminal.

¿No se te ocurre donde puedes utilizar este tipo de diálogos?¿Tienes una Raspberry? Pues si tienes una Raspberry, ahí tienes el primer caso donde puedes utilizar este tipo de cuadros de diálogo. Y ¿que usos le puedes dar? Esto es como la imaginación, no tiene fin.

De cualquier manera, es una alternativa de cuadros de dialogo para script a tener en cuenta. Luego dependerá de ti, la solución que quieras o simplemente necesites adoptar.

Dialog para crear menús y diálogos en el terminal

Dialog para crear diálogos en el terminal

Como ya te comenté en el capítulo de introducción de este tutorial sobre cuadros de diálogo, mi intención es que este tutorial sea eminentemente práctico. Así, para conseguir este objetivo, mostraré cada una de las diferentes opciones que nos ofrece mediante un ejemplo.

Instalación de dialog

Lo primero, antes que te pongas a probar cada uno de los ejemplos que encontrarás a continuación, es instalar dialog. Así, para instalar esta herramienta en Ubuntu o Debian, simplemente ejecuta la siguiente instrucción,

sudo apt install dialog

En el caso de que la quieras instalar en Red Hat o CentOS, tendrías que ejecutar la siguiente instrucción,

sudo yum install dialog

Y ya lo tienes… a partir de aquí, solo te queda empezar a sacarle partido a la herramienta.

Un diálogo sencillo

El primer ejemplo es mostrar un cuadro de diálogo que simplemente te muestre un mensaje de información. Esto es algo realmente sencillo, tan solo tienes que utilizar el siguiente código,

dialog --title "https://www.atareao.es" \
       --infobox "Este es el mensaje que se muestra" 0 0

Este tipo de diálogo lo puedes mostrar al usuario para informarle de que se va a realizar alguna operación, y posteriormente, una vez terminada la operación, mostrar un segundo cuadro de diálogo que indique que el proceso ha concluido.

Un diálogo con aceptación

Si necesitas que el usuario confirme que ha leído el texto, puedes utilizar el tipo msgbox. Este añade un botón al cuadro de diálogo. Al contrario que en el caso anterior, hasta que no hayas pulsado el botón aceptar no continuará el script. Así, por ejemplo,

dialog --title "https://www.atareao.es" \
       --msgbox "Este es el mensaje que se muestra" 0 0 
dialogo sencillo

Esto te va a mostrar un sencillo cuadro de diálogo, con una caja de texto en la que te aparecerá el mensaje Este es el mensaje que se muestra, y un botón de aceptar. En el caso de que el mensaje sea muy largo, verás una barra de desplazamiento y un porcentaje que te indica cuanto has visto.

Los dos números que aparecen al final, indican el alto y el ancho del cuadro de diálogo. En el caso de que estén a cero, indica que serán autocalculados. Ojo, que al contrario a lo que es habitual, en este caso, aparece alto primero.

Pero además puede añadir algunas opciones adicionales, como por ejemplo, que aparezca un título de fondo, y también cambiar la ubicación del cuadro de diálogo. Es decir, en lugar de que el cuadro de diálogo aparezca centrada, puedes querer que aparezca ligeramente desplazada hacia la izquierda y hacia la parte superior. Esto, lo puedes conseguir con el siguiente ejemplo,

dialog --title "https://www.atareao.es" \
       --backtitle "Mensaje de fondo" \
       --begin 10 10 \
       --msgbox "Este es el mensaje que se muestra" 10 30

Preguntando al usuario

Ahora hay que dar un paso mas allá, hay que preguntar al usuario, algo para que te de una respuesta. Es necesario interactuar con el usuario, y para ello, puedes utilizar los diálogos en el terminal. Por ejemplo, preguntar si quieres continuar con el proceso, y a esto tiene que responder con un si o no. En este caso tienes que utilizar un cuadro de diálogo tipo yesno, como el que puedes ver en el siguiente ejemplo,

dialog --title "https://www.atareao.es" \
       --yesno "¿Quiere continuar?" 0 0

Perfecto, al fin puedo interactuar con el usuario. Pero ¿y como se que ha respondido? En el caso de que haya respondido afirmativamente, el resultado es un 0 mientras que si ha respondido negativamente, el resultado es 1. Así para el ejemplo anterior, se podría hacer de la siguiente manera,

dialog --title "https://www.atareao.es" \
       --yesno "¿Quiere continuar?" 0 0
ans=$?
if [ $ans -eq 0 ]
then
    echo "Respondió si"
else
    echo "Respondió no"
fi

Diálogo para introducir texto

Si ahora quieres preguntarle el nombre al usuario, tienes que utilizar un diálogo del tipo inputbox, como puedes ver en el ejemplo siguiente. Además, en este ejemplo, recoges el resultado en una variable y la muestras mediante un echo.

respuesta=$(dialog --title "https://www.atareao.es" \
                   --stdout \
                   --inputbox "¿Cual es tu nombre?" 0 0)
echo "Tu nombre es: $respuesta"

Como ves en el ejemplo anterior, e añadido una opción que no había incluido hasta el momento --stdout. Esta es la opción que te va a permitir recoger la respuesta en la variable respuesta, en este caso particular.

Pero ¿y si lo que quieres introducir es una contraseña que esté a salvo de miradas ajenas?. En este caso, la herramienta que tendrías que elegir es passwordbox, tal y como puedes ver en el siguiente ejemplo,

secreto=$(dialog --title "Secreto" \
                 --stdout \
                 --passwordbox "Introduce la contraseña:" 0 0)
echo "Esta es la contraseña que has introducido: ${secreto}"

Un cuadro de diálogo para seleccionar una opción

En el caso de que tengas que ofrecer al usuario distintas opciones para que seleccione una o varias de ellas, tienes que utilizar el cuadro de diálogo checklist. Por ejemplo,

respuesta=$(dialog --title "https://www.atareao.es" \
                   --stdout \
                   --checklist "Selecciona una opción:" 0 0 3 \
                               1 personal off\
                               2 profesional on\
                               3 otro off)
echo "Has elegido: $respuesta"

En este caso sigues utilizando la opción stdout para recoger la respuesta, y con la opción checklist tienes que pasar varios parámetros,

  • un texto que indique lo que tienes que elegir
  • las dimensiones del cuadro de diálogo (alto x ancho)
  • el número de opciones que se muestran. En el caso de que haya mas opciones, estas aparecerán ocultas, y tendrás que utilizar la barra de desplazamiento para mostrarlas.
  • cada una de las opciones formadas a su vez por tres parámetros
    • el resultado
    • el texto que se muestra
    • si está activada por defecto o no

También existe otro cuadro de diálogo alternativo al anterior, pero que en lugar de permitirte elegir varias opciones, solo te permite elegir una opción. Se trata del radiolist. Por ejemplo,

respuesta=$(dialog --title "https://www.atareao.es" \
                   --stdout \
                   --radiolist "Selecciona una opción:" 0 0 3 \
                               a personal off\
                               b profesional on\
                               c otro off)
echo "Has elegido: $respuesta"

Indicarte que si pulsas el botón Cancelar, el resultado será vacío.

Un cuadro de diálogo para seleccionar archivos

Otra interesante opción que pone al alcance de tus manos la herramienta dialog, para crear diálogos en el terminal, es un cuadro de diálogo para seleccionar archivos. Por ejemplo, puedes utilizar este diálogo para seleccionar un archivo que borrar, y confirmar que el usuario, realmente quiere borrar este archivo,

respuesta=$(dialog --title "Selecciona un archivo" \
                   --stdout \
                   --fselect $HOME/  14 70)
if [ -f "$respuesta" ]
then
    dialog --title "Borrar archivo" \
           --yesno "Estás seguro de borrar ${respuesta}" 0 0
    ans=$?
    if [ $ans -eq 0 ]
    then
        rm "$respuesta"
        dialog --msgbox "El archivo ${respuesta} fue borrado" 0 0
    fi
fi

Indicarte que así como en otros casos es posible calcular automáticamente las dimensiones del diálogo, en este caso, es necesario indicarlo de forma explícita. Así, los parámetros que definen este cuadro de diálogo son el directorio de inicio y las dimensiones del diálogo.

De la misma manera, si lo que quieres seleccionar es un directorio, podrías utilizar la opción dselect, tal y como te muestro en el siguiente ejemplo,

respuesta=$(dialog --title "Selecciona un directorio" \
                   --stdout \
                   --dselect $HOME/  14 70)
echo "Directorio seleccionado: ${respuesta}"

Una barra de progreso

Por supuesto, no podía faltar un cuadro de diálogo que fuera una barra de progreso, de forma que le indique al usuario que tiene que esperar hasta que el proceso termine, y que además, le indique una estimación del tiempo que le queda para que este proceso termine. Por ejemplo,

for i in $(seq 0 10 100)
do
    sleep 1
    echo $i | dialog --gauge "Espera hasta que termine\n por favor" 0 0 0
done

Este es un ejemplo, y el proceso que muestro solo espera un segundo, pero la cuestión es que en ese punto es donde tienes que realizar el proceso, y además estimar el tiempo que le queda.

Otra opción que tienes, es hacer que el usuario espere unos segundos hasta que termine el proceso, aunque aquí tienes que estimar tiempo, y también tienes el problema de que el usuario pulse el botón aceptar, en el cuyo caso se termina la cuenta regresiva de inmediato. Por ejemplo,

dialog --pause "Espera unos segundos" 0 0 5
ans=$?
if [ $ans -eq 0 ]
then
    echo "Si"
else
    echo "No"
fi

Eligiendo ingredientes

Una solución alternativa a la que te he mostrado anteriormente para seleccionar opciones, pero que además resulta tremendamente visual, es una buildlist. Esto te muestra un cuadro de diálogo con dos listas, una al lado de la otra. De esta forma, las opciones seleccionadas, se mostrarán en la derecha, mientras que las que no están seleccionadas, pero que están disponibles se mostrarán en la izquierda. Por ejemplo,

respuesta=$(dialog --title "Tu pizza" \
                   --stdout \
                   --buildlist "Elige los ingredientes de la pizza:" 0 0 0 \
                               1 queso off \
                               2 alcachofas on \
                               3 champiñones off \
                               4 anchoas off \
                               5 tomate off)
echo "Ingredientes elegidos: ${respuesta}"

Seleccionando fechas

Por supuesto, que tarde o temprano te tendrás que enfrentar con las fechas (malditas fechas). En este caso, la herramienta dialog también pone a tu disposición una herramienta perfecta. Se trata de calendar, y su uso es tan sencillo como te podrías imaginar,

respuesta=$(dialog --title "Selecciona tu cumpleaños" \
                   --stdout \
                   --calendar "¿Cuando es?" 0 0)

Por supuesto que al igual que puedes elegir fechas, también puedes elegir horas. Para ello tienes que utilizar timebox. Por ejemplo,

respuesta=$(dialog --title "Selecciona una hora" \
                   --stdout \
                   --timebox "la que prefieras" 0 0)

Un formulario

Pero, ¿que sucede si lo que necesites es un formulario para introducir los datos del usuario?¿Tendrás que mostrar un cuadro de diálogo para cada una de las preguntas que quieras formular?. No. Por supuesto, la herramienta dialog, también tiene una solución para esto, la opción form. Sin embargo, este tipo de solución, no es tan sencilla como lo que has visto hasta el momento. La cosa se complica ligeramente, sobre todo por el tratamiento que realiza Bash de los espacios, y esos detalles, que son realmente importantes, y que siempre tienes que tener en cuenta.

Sea como fuere, si lo que quieres es preguntar a tu usuario por algunos datos, como podría ser el nombre, el primer apellido y el correo electrónico, puedes utilizar una solución como la que te muestro en el ejemplo siguiente,

respuesta=$(dialog --title "atareao.es"                  \
                   --separate-widget $"\n"               \
                   --form  "Introduce tus datos"         \
                   0 0 0                                 \
                   "Nombre:"   1 1 "$nombre"   1 10 20 0 \
                   "Apellido:" 2 1 "$apellido" 2 10 20 0 \
                   "Email:"    3 1 "$mail"     3 10 20 0 \
                   3>&1 1>&2 2>&3 3>&-)
nombre=$(echo "$respuesta" | sed -n 1p)
apellido=$(echo "$respuesta" | sed -n 2p)
email=$(echo "$respuesta" | sed -n 3p)
echo "Nombre: $nombre"
echo "Apellido: $apellido"
echo "Email: $email"

Menús

Otra opción similar a alguna de las que hemos visto anteriormente, pero que deberías tener en cuenta, es el menu. Un posible ejemplo de menú sería el que te muestro a continuación,

respuesta=$(dialog --title "Ejemplo de menu" \
                  --stdout \
                  --menu "Opciones" 12 20 5 \
                         1 "Opción 1" \
                         2 "Opción 2" \
                         3 "Opción 3" \
                         4 "Opción 4")
echo $respuesta
highslide

Conclusiones

Como has podido ver tienes un gran número de opciones y posibilidades para crear tus diálogos en el terminal, y de esta manera interaccionar con los usuarios, mas allá de utilizar una línea de comandos. Cierto es que finalmente necesitas recurrir al terminal, que es posible que en tu caso, no represente mucho problema, pero a lo mejor, en otros casos, si que podría suponer un inconveniente. Para este segundo caso, en los siguientes capítulos del tutorial encontrarás otras opciones que seguro te resultarán interesante.

Sea como fuere, esta herramienta, dialog, es una opción que tienes que tener en mente, o al menos, tener presente que existe, por si en alguna ocasión tienes que recurrir a ella. No en todas las ocasiones tenemos una interfaz gráfica, como podría ser un servidor.


Más información,

Imagen de portada de Catherine Heath en Unsplash

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *