Tabla de contenido
Una vez más aquí. En esta ocasión vengo a dejar un pequeño tutorial para dejarme una nota a mi mismo (y para todo el que lo necesite) en el que vamos a ver algunos conceptos básicos de la utilidad dialog para utilizar el widget ncurses en nuestros scripts de shell. Veremos cómo instalar dialog en nuestro sistema Ubuntu, algunas de las opciones comunes que podemos usar para alterar el comportamiento del diálogo, cómo usar algunos widgets; entre otros: inputbox, checklist, radiolist y yesno. Para terminar veremos cómo usar los datos obtenidos por el procesamiento del widget.
Instalación de Dialog en Ubuntu
La utilidad de dialog está disponible en todos los repositorios predeterminados de las principales distribuciones de Gnu/Linux, por lo tanto, podemos usar nuestro administrador de paquetes favorito para instalarlo. En Ubuntu, solo tendremos que abrir una terminal (Ctrl+Alt+T) y escribir en ella el comando:
sudo apt install dialog
Opciones de dialog más comunes
Llamamos a estas opciones ‘comunes’ porque se pueden usar independientemente del tipo de widget que queremos utilizar. Solo vamos a ver la punta de iceberg, los que pueden ser quizás de mayor interés cuando comencemos a utilizar dialog.
Configurar un título de cuadro de widget: la opción –title
Al usar la opción –title podemos especificar una cadena que se usará como título del widget, que se mostrará en la parte superior del cuadro.
dialog --title "Título de ventana" --inputbox "Escribe tu nombre:" 0 0
Combinación de widgets: la opción –and-widget:
La opción –and-widget se puede usar para ‘encadenar’ más widgets, de modo que después de usar el primero, se nos solicite inmediatamente el segundo. La cadena se detiene cuando uno de los cuadros de diálogo devuelve un estado de existencia distinto de cero.
dialog \ --inputbox "Escribe tu nombre:" 0 0 \ --and-widget --inputbox "Escribe tu edad:" 0 0
Una vez que lancemos el comando anterior, se mostrará el primer widget de entrada utilizado para solicitarnos nuestro nombre. Cuando confirmemos la entrada haciendo clic en el botón Aceptar, se mostrará el siguiente widget y se nos pedirá que escribamos nuestra edad.
Borrar la pantalla con la opción –clear
Cuando usamos la opción –and-widget, el contenido creado por un widget anula el producido por el anterior. Si los widgets no ocupan exactamente el mismo espacio en la pantalla, los dos contenidos se mezclarían y esto crearía un desastre.
Para evitar la superposición de contenidos, podemos usar la opción –clear; cuando lo hacemos, el contenido de un widget se borra antes de que se muestre el siguiente widget, solo se conserva el color de fondo.
Configurar el botón a como se resalta de forma predeterminada: la opción –default-button
Dependiendo del widget que estemos usando, se puede mostrar más de un botón en la pantalla y uno de ellos se resalta de manera predeterminada, determinando la acción predeterminada que se realizará cuando el usuario pulse Intro.
Podemos anular el valor predeterminado del widget utilizando la opción –default-button seguida del nombre del botón; ok, yes, cancel, no, help o extra.
Esta opción puede ser realmente útil, por ejemplo, cuando se solicita confirmación antes de ejecutar una acción potencialmente peligrosa:
dialog --default-button "no" --yesno "Eliminar el contenido del disco?" 0 0
Como puede ver en la captura de pantalla, hicimos que el botón ‘no‘ esté seleccionado de forma predeterminada, de modo que el usuario debe seleccionar explícitamente ‘sí‘ para confirmar su elección.
Establecer el elemento seleccionado predeterminado en una lista con –default-item
Cuando usamos una lista de verificación o un widget de menú, el primer elemento de la lista de posibles opciones se selecciona de manera predeterminada. Al usar la opción –default-item y hacer referencia a un elemento, podemos usarlo como una alternativa predeterminada:
dialog --default-item 2 --checklist "Selecciona:" 0 0 5 \ 1 "Primer elemento" off \ 2 "Segundo elemento" off \ 3 "Tercer elemento" off
Como se puede ver en el ejemplo anterior, hicimos referencia al elemento por su etiqueta 2 en este caso.
Especificación de un retraso de tiempo después de la confirmación: la opción –sleep
A veces podemos querer que nuestra aplicación espere un cierto número de segundos después de procesar un cuadro de diálogo. Para alcanzar este comportamiento, podemos usar la opción –sleep y proporcionar el número de segundos para esperar como valor:
dialog --sleep 3 --inputbox "Escribe tu nombre:" 0 0
Como resultado del comando anterior, después de que se muestre el widget inputbox y el usuario presiona la tecla Intro, se esperan 3 segundos antes de que se ejecute el siguiente comando en el script de llamada.
Proporcionando un tiempo de espera de elección
En algunos casos podemos querer darle al usuario un número máximo de segundos para realizar su elección. La aplicación de diálogo proporciona la opción –timeout para obtener dicho comportamiento. El número de segundos de tiempo de espera debe pasarse como argumento de la opción. Si después de la cantidad de segundos especificada siempre que el usuario no realice su elección, la aplicación saldrá con un estado de error:
dialog --timeout 3 --inputbox "Escribe tu nombre:" 0 0
Establecer etiquetas alternativas para botones
La utilidad de diálogo proporciona una serie de opciones para anular la etiqueta predeterminada para los botones: podemos usar las etiquetas –exit-label, –extra-label, –help-label, –no-label, –ok-label, –yes-label para cambiar las etiquetas de los botones ‘exit’, ‘extra’, ‘help’, ‘no’, ‘ok’ y ‘yes’, respectivamente.
Cada una de las opciones mencionadas anteriormente toma una cadena como argumento, que se usa como etiqueta del botón. Aquí hay un ejemplo del uso de la opción:
dialog --default-button "no" \ --no-label "Mejor NO" \ --yes-label "Claro que si" \ --yesno "Quieres eliminar los datos del disco duro?" 0 0
Widgets de diálogo
Hasta ahora vimos algunas de las opciones ‘comunes‘ de diálogo más útiles. Ahora veremos cómo usar algunos de los widgets disponibles en detalles. Antes de continuar, debemos especificar la sintaxis general. Cuando iniciamos un diálogo, siempre debemos proporcionar tres parámetros:
- El texto que se mostrará en el widget.
- El ancho del widget.
- La altura del widget.
El widget inputbox
El widget inputbox se usa para solicitar al usuario que responda a una pregunta con una entrada de texto. El parámetro de texto se usa para proporcionar la pregunta: si la cadena es más larga que el cuadro de diálogo, este último será desplazable. Para usar este widget, invocamos el diálogo con la opción –inputbox.
Al salir, la entrada proporcionada por el usuario se muestra en la salida del diálogo, que por defecto es stderr.
El widget de lista de verificación
Ya vimos cómo se ve el widget de la lista de verificación en ejemplos anteriores: en este tipo de widget, se proporcionan al usuario una serie de opciones que pueden seleccionar uno o más de ellos. Para usar este widget, debemos usar la opción –checklist y, además de los tres parámetros estándar que deben pasarse a todos los widgets, debemos proporcionar también la altura de la lista y las opciones que se mostrarán.
El parámetro de altura de línea se usa para establecer cuántas líneas deben mostrarse a la vez. Si el número de líneas es menor que las opciones disponibles, el menú se desplazará. Si proporcionamos 0 como el valor de altura de línea, el número de líneas corresponderá al número de opciones.
Para cada elección debemos proporcionar un identificador (etiqueta), un nombre y un estado que puede estar encendido o apagado. Si el estado está activado, la opción se verificará de forma predeterminada. Una vez que confirmemos nuestras elecciones, las etiquetas relacionadas con la entrada que verificamos se mostrarán en stderr:
dialog --checklist "Selecciona los items:" 0 0 0 \ 1 "Selección número uno" off \ 2 "Selección número dos" on \ 3 "Selección número tres" off \ 4 "Selección número cuatro" on
Con el comando anterior, iniciamos el menú con 4 opciones y configuramos las opciones 2 y 4 marcadas por defecto.
El widget radiolista
El widget radiolist se inicia cuando se invoca el diálogo con la opción –radiolist. Funciona de manera similar al widget de lista de verificación, con la diferencia de que las opciones son mutuamente excluyentes, por lo que solo se puede seleccionar un elemento.
dialog --radiolist "Selecciona los items:" 0 0 0 \ 1 "Selección número uno" Off \ 2 "Selección número dos" on \ 3 "Selección número tres" off \ 4 "Selección número cuatro" Off
Dado que las opciones son mutuamente excluyentes, solo la primera opción establecida en activado se seleccionará como predeterminada.
Solicitar al usuario una contraseña con el widget de contraseña
El widget de contraseña se usa para permitir que un usuario ingrese una contraseña. Por razones de seguridad, el texto ingresado por el usuario no se muestra. Este comportamiento puede modificarse utilizando la opción –insecure: si lo hacemos, el widget mostrará un asterisco para cada letra de la contraseña ingresada en el campo correspondiente.
Usamos el widget iniciando el diálogo con la opción –passwordbox:
dialog --insecure --passwordbox "Escribe la contraseña:" 0 0
Mostrar un mensaje con el widget msgbox
El uso de este widget es realmente simple: se invoca llamando al diálogo con la opción –msgbox y muestra un mensaje que es el contenido del parámetro de texto. Se muestra un solo botón Aceptar:
dialog --msgbox "Esto es un mensaje importante que se debería leer con calma!" 0 0
El widget de calendario
Podemos usar el widget de calendario invocando la utilidad de dialog con la opción –calendar. El widget nos permite seleccionar una fecha eligiendo mes, día y año que se muestran en secciones separadas del widget. Es posible proporcionar una fecha predeterminada pasándola como parte del comando.
Para iniciar el widget con el ‘séptimo día de abril del año 2020‘ como la fecha predeterminada, por ejemplo, ejecutaremos el siguiente comando:
dialog --calendar "Selecciona una fecha:" 0 0 07 04 2020
Podemos movernos entre las secciones del widget con la tecla TAB y cambiar los parámetros con las teclas de flecha. Una vez que confirmamos la selección, se muestra a stderr en el formato día / mes / año. Esto se puede modificar utilizando la opción –date-format con un formato compatible con strftime especificado como argumento. Para hacer la salida en el formato año / mes / día, por ejemplo, utilizaríamos la opción de la siguente forma:
dialog --date-format %Y/%m/%d --calendar "Selecciona una fecha" 0 0 07 04 2020
Solicitar confirmación al usuario: el widget yesno
Este widget nos permite solicitar confirmación al usuario. Al usarlo, especificamos la pregunta que se debe hacer a través del parámetro de texto. Dependiendo de la elección del usuario, se devuelve un estado de salida: 0 si el usuario confirma haciendo clic en el botón Sí, 1 de lo contrario.
Para invocar este widget debemos usar la opción –yesno:
dialog --yesno "Lo confirmas?" 0 0
Administrar la salida producida por un widget
Por defecto, la salida producida por un widget se muestra en stderr, por ejemplo, para almacenar los datos obtenidos de un widget a un archivo, todo lo que tenemos que hacer es redirigir stderr a dicho archivo.
dialog --checklist "Selecciona:" 0 0 0 \ 1 "Selección número uno" off \ 2 "Selección número dos" on \ 3 "Selección número tres" off \ 4 "Selección número cuatro" on 2> seleccion.txt
Una vez que el usuario confirme sus elecciones, se escribirán, separadas por espacios en el archivo seleccion.txt.
¿Qué pasa si queremos almacenar la selección directamente en una variable? Para realizar la tarea, debemos usar la opción –stdout, de modo que la salida del widget se muestre en stdin en lugar de stderr:
seleccion="$(dialog --stdout --checklist "Selección:" 0 0 0 \ 1 "Selección número uno" off \ 2 "Selección número dos" on \ 3 "Selección número tres" off \ 4 "Selección número cuatro" on)"
En el ejemplo anterior, se podrá acceder al resultado del procesamiento del widget a través de la variable de opciones. Quizás podamos querer recorrerlos:
for seleccion in ${seleccion}; do echo "${seleccion}"; done
Para gestionar el proceso del widget yesno debemos comportarnos de manera diferente. Dicho widget, como ya vimos, no produce ningún resultado, pero cambia el código de salida del comando utilizado para liberarlo de acuerdo con la elección del usuario. Si el usuario confirma y responde afirmativamente a la pregunta, el código de salida se establece en 0, de lo contrario en 1 (esto puede parecer extraño, pero hay que recordar que 0 significa OK mientras que 1 es un estado de salida que significa que un comando no fue exitoso) . Sabiendo esto, podemos escribir algo como:
if dialog --yesno "Quieres abrir la instancia con gnome-terminal ?" 0 0; then clear gnome-terminal fi
En este post vimos cómo podemos usar la aplicación dialog para usar el widget ncurses en los scripts de shell. Primero vimos algunas opciones comunes que se pueden usar independientemente del tipo de widget, y luego echamos un vistazo a algunos widgets específicamente. Hay muchos más widgets que se pueden usar con dialog. Para obtener una lista completa resulta interesante consultar el manual de la aplicación.