Lección 4: Seleccionables
Los campos seleccionables son aquellos donde el usuario no tiene la posibilidad de escribir, sino que debe elegir entre una serie de opciones. Aunque en Emacs, por su naturaleza de editor de texto, alguno de ellos se encuentran en una fina línea entre ser seleccionables o no.
Si ya has realizado formularios con anterioridad, te resultarán familiares algunos de ellos: select
, radio
, checkbox
, toggle
, color
… Pero en Emacs, además, tenemos otros que no son tan comunes, como menu-choice
o editable-list
.
menu-choice
(select o desplegable)
El widget es similar al select
de HTML, pero con la diferencia de que no se puede escribir en ciertos campos. Es decir, el usuario debe elegir una opción entre una serie de opciones, pero podemos añadir opcionalmente un campo de texto libre para que el usuario pueda escribir lo que quiera.
(widget-create 'menu-choice
:tag "¿Qué smartphone tienes?"
:help-string "Selecciona tu smartphone"
:value "Android"
:notify (lambda (widget &rest ignore)
(message "Seleccionado: %s" (widget-value widget)))
'(choice-item :tag "Android" :value "Android")
'(item :tag "iPhone" :value "iPhone")
'(item :tag "Blackberry" :value "Blackberry")
'(editable-field :value "Otro" :format "Otro: %v"))
Aquí podemos ver como se ha desplegado las opciones.
Y en esta ocasión se ha seleccionado el campo editable “Otro”.
Los atributos son similares a otros widgets, como puede ser el editable-field
, salvo que aquí demos añadir otros widgets dentro del menu-choice
.
choice-item
: Item seleccionado por defecto. Debes añadir el atributo:value
amenu-choice
con el mismo valor que elchoice-item
para que funcione. Revisa el ejemplo anterior.tag
es el texto que se muestra en el desplegable yvalue
es el valor que se asigna almenu-choice
cuando se selecciona.item
: Item que se puede seleccionar.tag
yvalue
se comportan igual quechoice-item
.editable-field
: Campo de texto editable. Ya que se comporta como uneditable-field
, puedes añadirle el atributo:format
para que se muestre un texto por defecto.
item
(texto)
El widget nació y existe para crear un elemento seleccionable dentro de un grupo de botones como menu-choice
o radio-button-choice
. Pero por su naturaleza, también lo podemos utilizar de forma independiente para mostrar un texto plano editable.
(widget-create 'item :value "Texto de ejemplo")
Es importante que siempre lo guardes en una variable para poder modificarlo posteriormente.
(setq my-item (widget-create 'item :value "Texto de ejemplo"))
A continuación pudes ver un ejemplo donde un botón incrementa un número que es mostrado en el item
de forma dinámica.
(setq number 0)
(widget-insert "\n")
(setq my-item (widget-create 'item :value "0"))
(widget-insert "\n")
(widget-create 'push-button
:notify (lambda (&rest ignore)
(setq number (1+ number))
(widget-value-set my-item number))
:help-echo "Púlsame para incrementar el número"
"Incrementar")
En la documentación no encontrarás referencia alguna al uso del widget como un espacio de solo lectura o zona en el cual podamos renderizar strings. Sin embargo, nosotros lo usaremos con tal fin ya que no existe otro widget que nos permita hacerlo.
radio-button-choice
(radio button)
Los radio buttons son aquellos botones que se agrupan y solo se puede seleccionar uno de ellos. En Emacs, utilizamos el widget radio-button-choice
para crear el grupo. Cada botón se crea con el widget item
.
(widget-insert "¿Qué quieres beber?:\n\n")
(widget-create 'radio-button-choice
:value "Café"
:notify (lambda (widget &rest ignore)
(message "Has seleccionado %s" (widget-value widget)))
'(item "Café")
'(item "Té")
'(item "Agua"))
En el caso que no queramos que ningún botón esté seleccionado por defecto, podemos omitir el atributo :value
.
checkbox
Los checkbox son similares a los radio buttons, pero en este caso se pueden seleccionar varios a la vez. Para ello, usamos el widget checkbox
.
(widget-insert "\nAficiones favoritas:\n\n")
(widget-create 'checkbox
:help-echo "Marcar si te gusta leer"
:notify (lambda (&rest ignore) (message "Has seleccionado Leer")))
(widget-insert " Leer\n")
(widget-create 'checkbox
:help-echo "Marcar si te gusta ver películas"
:notify (lambda (&rest ignore) (message "Has seleccionado Ver series")))
(widget-insert " Ver series\n")
(widget-create 'checkbox
:help-echo "Marcar si te gusta jugar a videojuegos"
:notify (lambda (&rest ignore) (message "Has seleccionado Jugar a videojuegos")))
(widget-insert " Jugar a videojuegos\n")
No podemos utilizar el atributo :format
para dar una etiqueta (label) a los checkbox. Al hacerlo deja de funcionar el widget. Posiblemente se deba a limitación técnica. Por lo tanto, debemos crear el texto nosotros mismos con widget-insert
.
En el caso que queramos que alguno de los checkbox esté seleccionado por defecto, debemos incluir t
como último argumento de checkbox
.
(widget-create 'checkbox
:help-echo "Marcar si te gusta leer"
:notify (lambda (&rest ignore) (message "Has seleccionado Leer"))
t)
toggle
(switch)
Es similar a un checkbox
en funcionalidad, pero visualmente es un switch de 2 posiciones: on
o off
. Es decir, un botón que puede estar en el estado activado o desactivado.
(widget-insert "¿Aceptas las condiciones? ")
(widget-create 'toggle
:help-echo "¿Aceptas las condiciones?"
:on "👍"
:on-glyph '
:off "👎"
:off-glyph '
:value t
:notify (lambda (widget &rest ignore)
(message "Has seleccionado %s"
(if (widget-value widget)
"aceptar"
"rechazar"))))
Obligatoriamente debes definir:
:on
: Texto que se muestra cuando el toggle está activado.:off
: Texto que se muestra cuando el toggle está desactivado.:value
: Valor inicial del toggle.t
para activado ynil
para desactivado.:notify
: Función que se ejecuta cuando se cambia el estado del toggle.
Opcionalmente puedes definir:
:on-glyph
: Icono glyph, si están activados, que se muestra cuando el toggle está activado.:off-glyph
: Icono glyph, si están activados, que se muestra cuando el toggle está desactivado.:help-echo
: Texto que se muestra cuando se pasa el ratón por encima.
editable-list
(lista editable)
Las listas editables es un widget de lo más peculiar. Permite crear una lista de elementos que se pueden editar. Es decir, podemos añadir, eliminar y modificar elementos de la lista. Similar a un TODO.
(widget-create 'editable-list
:entry-format "%i %d %v"
:notify (lambda (widget &rest ignore) (message "%s" (widget-value widget)))
:value '("elisp" "emacs")
'(editable-field :value ""))
Si queremos incluir argumentos en los botones, como por ejemplo un texto de ayuda, debemos utilizar los atributos :insert-button-args
, :delete-button-args
y :append-button-args
.
(widget-create 'editable-list
:entry-format "%i %d %v"
:insert-button-args '(:help-echo "Inserta un elemento nuevo" :tag "Insertar")
:delete-button-args '(:help-echo "Borra el elemento" :tag "Borrar")
:append-button-args '(:help-echo "Inserta un elemento al final" :tag "Insertar nueva línea")
:value '("elisp" "emacs")
'(editable-field :value ""))
:insert-button-args
: Argumentos que se pasan al botón de insertar.:delete-button-args
: Argumentos que se pasan al botón de borrar.:append-button-args
: Argumentos que se pasan al botón de insertar que se encuentra al final de la lista.
No podrás utilizar :notify
para obtener los cambios de la lista. En su lugar, debes utilizar :notify-insert
y :notify-delete
.
Existen otros atributos que podemos utilizar como :buttons
que representa los widgets de los botones para insertar y borrar. Si buscas personalizarlos, puedes sobreescribirlos.
Como ejemplo práctico al widget, puede ver en el siguiente ejemplo he creado un formulario para crear hashtags.
(widget-insert "\nIncluye las etiquetas que quieras crear: \n\n")
(setq widget-preview (widget-create 'item :value ""))
(widget-insert "\n")
(widget-create 'editable-list
:entry-format "%i %d %v"
:notify (lambda (widget &rest ignore)
(widget-value-set widget-preview
;; Convierte la lista a string, añadiendo un espacio de separación. Similar a join en otros lenguajes
(mapconcat 'identity
;; Concadena a cada elemento un "#" al inicio.
(mapcar (lambda (item) (concat "#" item))
;; Ignora los campos vacios
(seq-filter (lambda (item) (and (stringp item) (not (string= item ""))))
(widget-value widget))) " ")))
:value '()
'(editable-field :value ""))
color
Es un widget que no esta documentado, pero si esta presente en el código fuente del paquete. Nos permite seleccionar un color de una paleta de colores.
(widget-create 'color
:value "#ff0000"
:tag "Color"
:format "%{%t%}: %v (%{Previa%})\n"
:notify (lambda (widget &rest ignore)
(message "Has seleccionado %s" (widget-value widget))))
El atributo :format
es más complejo que el resto de widgets. Nos permite definir el texto del tag (%t
), el valor (%v
) y el texto de la previsualización (%{Previa%}
).
Si deseas renombrar el botón de selección, puedes sobreescribir la función widget-color-value-create
.
(defun widget-color-value-create (widget)
(widget-field-value-create widget)
(widget-insert " ")
(widget-create-child-and-convert
widget 'push-button
:tag " Selecciona " :action 'widget-color--choose-action)
(widget-insert " "))
group
No es un widget visual como todos los anteriores, su labor es funcional. Nos brinda la capacidad de agrupar widgets para organizar los comportamientos. Puedes pensar en él como una carpeta.
(setq form-contact (widget-create 'group :tag "form-contact"))
(setq input-email (widget-create
'editable-field
:size 20
:format "Email: %v"
:parent form-contact)) ; Nueva
(setq input-password (widget-create
'editable-field
:size 20
:format "Contraseña: %v"
:secret ?*
:parent form-contact)) ; Nueva
No te puedo dar más información sobre este widget, ya que no he encontrado documentación sobre él.
Archivos
Si leemos el código fuente del paquete widget
(emacs/lisp/wid-edit.el
), podemos encontrar otros selectores que no están documentados. Entre ellos, para seleccionar archivos, imágenes y directorios.
No los he incluido en el curso porque no he conseguido que funcionen. Si por tu lado consigues hacerlos trabajar, no dudes en compartirlo conmigo.
Actividad 1
Vamos a construir un formulario que nos ayude a calcular contidades con y sin impuestos.
El formulario debe tener los siguientes campos:
- Campo de texto para introducir la cantidad
- Desplegable
- Botón para calcular
item
para mostrar el resultado
El desplegable, o menu-choice
, contendrá las siguientes opciones:
- Sin impuestos
- Con impuestos
Cuando se pulse el botón de calcular, se obtendrá el valor del campo de texto y se incrementará en un 21% si se ha seleccionado la opción "Con impuestos". En caso contrario, "Sin impuestos", se restará un 21%. El resultado de la operación se mostrará en el item
.
Actividad 2
Crea un formulario con la siguiente estructura:
- ¿Ocultar tareas completadas?
toggle
item
con el número de tareas completadas
Cuando se pulse en el toggle
, se mostrará el número de tareas completadas en el item
. La información se obtendrá del siguiente endpoint: https://dummyjson.com/todos
Actividad 3
Utiliza una lista editable para sumar números. Todos los campos de la lista deben ser numéricos. Después de la lista, se debe mostrar el resultado, puedes apoyarte de un item
para ello.
Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 4.0 Internacional.
¿Me invitas a un café? ☕
Puedes hacerlo usando el terminal.
ssh customer@andros.dev -p 5555
Comentarios
Nuevo comentario
Nueva replica {{ formatEllipsisAuthor(replyComment.author) }}
Escribe el primer comentario
{{ comments.length }} comentarios