Cartero va tomando forma

Resumen del stream del viernes para quien se lo perdiese. En el stream del viernes se continuó con el desarrollo del clon de Postman que he empezado a escribir en Rust. Estos son en resumen los cambios:

  • El programa ya tiene nombre. En el chat el otro día se propusieron varias palabras, y he de decir que me gustó bastante «Cartero», por lo que va a adoptar este nombre.
  • El programa ya tiene repositorio online. Debido a la naturaleza de este proyecto y visto que la gente quería contribuir a él, lo he publicado en GitHub.com. En los últimos días ya he visto varios forks y sorprendentemente hay gente tirando código.
  • El prototipo de la interfaz de usuario ya está casi completo con las cosas que querría proponer para la primera iteración. En el stream del viernes casi todo el tiempo se fue en preparar lo que podría ser un widget para poner las cabeceras HTTP.

El repositorio de Cartero

Para este proyecto acepté guardar el código en un repositorio que sí permita contribuciones externas. Hoy en día todo mi código lo auto-alojo en git.danirod.es, y tiene la consecuencia de que sólo yo puedo subir código. No hay pull requests, no hay issue tracker, no hay forma de que alguien se dé de alta.

Sin embargo, decidí cargarlo en GitHub.com precisamente para poder aceptar contribuciones externas. La gente estos días mostraba mucho interés en poder contribuir al código, y por otra parte me parece una decisión correcta si el programa va a ser software libre de verdad.

Pensé subirlo a gitlab.gnome.org, que es la instancia de GitLab oficial de GNOME, pero por otra parte hay varias cosas que me echaron atrás en este momento.

  • Una es que se me hace raro aprovecharme de su servidor para alojar mi proyecto, incluso en el grupo World e incluso siendo un proyecto que es software libre y que tiene que ver con GTK+.
  • Otra es que los propios requisitos para guardar código en gitlab.gnome.org requieren que haya al menos una versión publicada. Dado que el proyecto acaba de nacer, todavía no tiene releases.
  • Me preocupa que a parte de mi comunidad y mi canal de streamings se le pueda ir la cabeza a la hora de contribuir o crear cuentas en su servidor de GitLab.

En estos días, he visto ya varios forks, commits y pull requests, y me parece muy interesante para poder aportar distintos enfoques. Supongo que como maintainer, mi rol también es asegurarme de que los pull requests que se aceptan no se escapan del ámbito y de los objetivos del proyecto y coordinar el trabajo entrante, pero me parece muy interesante lo que puede permitir esto, sobre todo por parte de gente que sepa más Rust que yo.

El código de Cartero

Siguiendo lo que dije en el manifesto, Cartero es una aplicación publicada bajo los términos de la licencia GPL 3.0 or later, lo que la convierte en software libre bajo la licencia más pura de las que ofrece la Free Software Foundation. Esto es algo que tiene sentido después de todo.

Cartero no tiene asignación de copyright, ni transferencia del copyright. Commit externo que entre en el repositorio, commit que le pertenece a la persona que lo escribió, siempre que la contribución sea legítima. En teoría existen documentos como el DCO para que la persona que envía un pull request declare que la contribución es suya o que tiene permiso para compartirla (que no ha copiado y pegado código de una base privativa, por ejemplo). Sin embargo, por el momento no le veo necesidad.

Esta falta de transferencia de copyright sumado a la licencia que se está utilizando, confirma que resulta imposible tomar la base de código una vez esté desarrollada, y privatizarla. No puedo tomar el código del producto, hacer una empresa, ponerle funciones cloud al producto y alterar el código para hacer difícil que se use sin pagarme una suscripción mensual, por ejemplo. Cosa que por otra parte tiene sentido.

El estado de la interfaz de usuario

Para la primera iteración de Cartero, el objetivo es simplemente que se pueda hacer una petición HTTP. Todavía no existe el concepto de «colecciones» ni peticiones guardadas, porque la intención es tener algo útil antes de ponerle más características.

Las cosas que tiene que permitir hacer Cartero 0.1 son:

  • Introducir la URL de la petición (https://api.example.com/v1/users).
  • Introducir el verbo de la petición (GET, HEAD, PUT…).
  • Introducir cabeceras HTTP para la petición.
  • Introducir un cuerpo que adjuntar a la petición.
  • Al pulsar el botón Enviar, hacer la petición HTTP de forma efectiva.
  • Reportar el código HTTP de la respuesta a la petición.
  • Reportar las cabeceras que envió el servidor.
  • Reportar en formato raw los bytes que mandó el servidor.

La lógica de negocio correrá presumiblemente a cargo de reqwest. En otras palabras, cuando se pulse el botón Enviar, el estado de la interfaz de usuario se convertirá a una petición de reqwest para hacerse, y lo que devuelva la petición de reqwest será lo que se muestre en la parte derecha de la página.

Por el momento, en el stream del viernes se terminó de agregar una primera versión del selector de cabeceras HTTP. Este componente va a dar bastante pelea, así que me dejo mis opiniones al respecto para el futuro. En cuanto al resto de componentes, poder sacar la cadena de caracteres marcada del DropDown de verbo HTTP también fue un poco laborioso pero se hizo. Ahora mismo, pulsar el botón «Enviar» (que no «Send») imprime por la terminal los valores que se han puesto en los componentes, lo que implica que posibilidad de extraer las cadenas de caracteres hay.

Por primera vez he hecho QA en GNOME para ver qué tal se ve fuera de mi cálido i3, sobre todo por la integración con otras aplicaciones del ecosistema. El resultado no tiene mala forma.

Otras cosas a nivel código que hay que hacer

Más pronto que tarde, habrá que meter Meson. Meson es un sistema de compilación parecido a CMake, que permite hacer más cosas antes y durante la compilación de un código fuente. Por ejemplo, compilar las traducciones de una aplicación, transformar archivos .ui… Es la herramienta recomendada en el mundo de GNOME para hacer aplicaciones.

Meson tiene soporte para Rust. Incluso aunque todo lo que haga sea llamar a cargo run, cargo build y cargo test, en el fondo vale la pena precisamente por todo lo que hay en el proyecto que no es Rust. En particular:

  • La posibilidad de generar los archivos de interfaz de usuario automáticamente cada vez que se compile la aplicación, que ahora mismo hay que hacerlo a mano llamando a blueprint-compile. (Erick ha propuesto un script, que por lo menos mejora las cosas.)
  • La posibilidad de tener traducciones en un archivo, para no hacer Spanglish ni tener las cadenas de caracteres grabadas a fuego en el código fuente de la aplicación. Esto por ahora es más prioritario porque tiene que ver con la interfaz de usuario.
  • Eventualmente, habrá que compilar GSchemas, archivos .desktop y esas cosas, y también es algo que se puede hacer con Meson en vez de invocar comandos a mano.

Así que es bastante probable que Meson entre muy pronto simplemente porque funciona y porque es un patrón aceptado en otras aplicaciones de GNOME.

Por otro lado, gtk-rs tiene un capítulo en su libro dedicado a hablar del subclassing y de cómo hacerlo. gtk-rs es una biblioteca para Rust, y Rust no es un lenguaje de programación donde el sistema de clases tradicional encaje bien. Sin embargo, la orientación a objetos en GTK+ es un tema esencial y al final Rust tiene que tener una forma de simular herencia de clases e implementaciones.

En GTK+, lo normal cuando se hacen interfaces de usuario para programas de verdad es fabricar una subclase del componente GTK+. Por ejemplo, en una aplicación de chat, cada una de las líneas con un mensaje enviado podría ser una GtkBox que muestre en horizontal el nombre de usuario del autor, el mensaje y la hora. Y podríamos hacerlo tal cual mediante un factory method que instancie objetos de tipo GtkLabel, GtkBox, GtkButton, les ponga sus atributos y los devuelva.

Pero lo normal será que el componente «mensaje enviado» sea una clase propia que extienda de GtkBox, y que la lista de mensajes no sea una lista de Gtk sino de nuestra clase propia. Incluso mediante composite templates, esa clase tendría su propia plantilla, y con funciones que permita interactuar con propiedades de alguno de los hijos.

En gtk-rs hay un sistema de macros que es un poco complicado de entender al principio, pero estoy convencido de que haciendo una clase, ya saldrán el resto solas.