Manuel Kaufmann (Humitos): Emacs fácil

Lo primero que hay que preguntarse es, ¿se puede?

Sí, hay una forma de configurar emacs y que sea sencillo. ¿Cómo? Usando el trabajo que los otros han estado haciendo :) . El mismísimo mundo se basa en eso, entonces, ¿porqué no hacerlo nosotros también?

Una de mis preocupaciones con Emacs era encontrar una forma fácil de compartir mi configuración para que otro la pruebe sin que re rompa la cabeza. En principio creé un repo git para eso, pero no fue suficiente. Es cierto que yo demoré bastante hasta entender cómo funcionan estas cosas.

Luego pensé en hacer un paquete con mi config, pero al final de cuenta también ya necesitás un nivel de conocimiento de emacs.

Después escribí un script tryit.sh basándome en la idea de los que escribieron helm (un plugin de emacs). Básicamente, bajás el repo mio de git, ejecutás tryit.sh y ya haría todo lo necesario para que funcione. Sin embargo, mantenerlo y hacer que funcione en diferentes versiones de Linux fue complicado. Abandoné rápido por no tener una forma fácil de probarlo.

Hoy está de moda Docker, así, ¿porqué no dockerizarlo?

Hice una primera prueba con Ubuntu y la imagen terminó pesando 1.2 GB, lo cuál no tiene sentido para mí. Así que busqué otras alternativas y llegué a Alpine Linux (3.8 MB).

Luego de probar algunas cositas, llegué a la primera configuración e imagen lista para ser corrida (~350 MB). Entonces, si tenés docker instalado en tu máquina hacé:

docker run --rm -it -e DISPLAY -v $(pwd):/src -v /tmp/.X11-unix:/tmp/.X11-unix:ro -v $XAUTHORITY:/root/.Xauthority --net=host humitos/emacs-x11-alpine

Esperá unos 5 minutos que baje la imagen y probalo!

Referencia: https://github.com/humitos/emacs-configuration

Juanjo Conti: Goodreads review: Días de combate (Hector Belascoarán Shayne, #1) (Paco Ignacio Taibo II)

Me gustó. Sobre todo los primeros 4/5, hasta después del diario del estrangulador. Luego todo se precipitó (ej: de la nada resultó que la chica de la cola de caballo era corredora de autos).

Como estoy estudiando el objeto novela desde el punto de vista de un constructor, anoto un par de cosas que me hicieron ruido:

Aparecieron algunos personajes que nada tuvieron que ver con la trama.
Está contado en tercera persona pero en varias ocasiones aparecía una segunda no muy justificada.

Rating: 4/5

Original: https://www.goodreads.com/review/show/1790805054

Marcos Dione: implementing-selenium-with-python-and-qt

I'm writing a python module that allows me to 'drive' a site using Qt. This means that I can navigate the site, fill forms, submit them and read the resulting pages and scrape them, Selenium style. The reasons I'm using Qt are that it has enough support for the site I'm driving (it's the web frontend of the SIP telephony solution we're using, which has an incomplete API and I have to automatize several aspects not covered by it); there are python bindings; and because I can do it headless: instead of using browser instances, I simply instanciate one QWebPage[1] per thread and that's it.

The first thing I learned today is that JS objects representing the DOM elements have two sets of value holders: attributes and properties. The properties is what in Python we call attributes: the object's elements which are accesible with the '.' operator and hold instance values. The attributes are in fact the HTML element's attributes that gave the properties' initial values. That is, given the following HTML element:

<input type="text" name="foo° id="bar" value="quux">

the initial JS object's attributes and properties will have those values. If you change the value with your browser, the value property of that element will be changed, but not the attribute. When you submit the form, the value properties of all the form elements are used, so if you "only' change the value attribute, that won't be used. So forget attributes. Also, the DOM is the representation of the actual state of the page, but this state is never reflected in the HTML source that you can ask your browser to show, but you see those changes reflected in the browser's debugger. It's like they really wanted[3] to keep initial values apart from current state[2].

On the Qt side, QWebElement is only the DOM element representation, not the JS object[4], so you can't access the properties via its API, but by executing JS[5]:

e = DOMRoot.findFisrt('[name="foo"]')
e.evaluateJavaScript("this.value = 'abracadabra'")

Tonight I finished fixing the most annoying bug I had with this site. To add a user I have to fill a form that is split in 7 'tabs' (which means 7 <div>s with fields where only one is shown at a time). One of the fields on the second tab has a complex JS interaction and I was cracking my skull trying to make it work. Because the JS is reacting to key presses, setting the value property was not triggering it. Next I tried firing a KeyboardEvent in JS, but I didn't succeed. Maybe it was me, maybe the fact that the engine behind QWebPage is the original Webkit and for some reason its JS support is lacking there, who knows.

But the good guys from #qtwebkit gave me a third option: just send plain QKeyEvents to the input element. Luckily we can do that, the web engine is completely built in Qt and supports its event system and more. I only had to give focus to the widget.

Again, I tried with JS and failed[7], so I went back cheating with Qt behind curtains. QWebElemnt.geometry() returns the QRect of the QWidget that implements the input element; I just took the .center() of it, and generated a pair of mouse button press/release events in that point. One further detail is that the .geometry() won't be right unless I force the second tab to be shown, forcing the field to be drawn. Still, for some reason getting a reference to the input field on page load (when I'm trying to figure out which fields are available, which in the long run does not make sense, as fields could easily be created or destroyed on demand with JS) does not return an object that will be updated after the widget is repositioned, so asking its geometry returns ((0, -1), (-1, 0)), which amounts to an invalid geometry. The solution is to just get the reference to the input field after forcing the div/tab to be shown.

Finally, I create a pair of key press/release events for each character of the string I wanted as value, and seasoned everything with a lot of QMainLoop.processEvents(). Another advantage of using the Qt stuff is that while I was testing I could plug a QWebView, sprinkle some time.sleep() of various lengths, and see how it behaved. Now I can simply remove that to be back to headlessness.

I'm not sure I'll publish the code; as you can see, it's quite hacky and it will require a lot of cleanup to be able to publish it without a brown paper bag in my head.


[1] Yes, I'm using qt5.5 because that's what I will have available in the production server.

[2] Although as I said, you can change the attributes and so you lose the original values.

[3] I guess the answer is in in the spec.

[4] I think i got it: QWebElement is the C++ class that is used in WebKit to represent the HTML tree, the real DOM, while somewhere deeper in there are the classes representing the JS objects which you just can't reach[6].

[5] This clearly shows that there is a connection between the DOM object and the JS one, you just can't access it via the API.

[6] This is the original footnote: Or something like that. Look, I'm an engineer and I usually want to know how things work, but since my first exposure to HTML, CSS and JS, back in the time when support was flaky and fragmented on purpose, I always wanted to stay as far away from them as possible. Things got much better, but as you can see the details are still somewhat obscure. I guess, I hope the answer is in the spec.

[7] With this I mean that I executed something and it didn't trigger the events it should, and there's no practical way to figure out why.


python pyqt

Marcos Dione: activate-external-screen-with-external-keyboard-in-Dell-Inspiron-1420

This is the second time I spent hours looking for this, so this time I'm writing it down.

My 10 year old Dell Inspiron 1420N, which is now my home server where I keep several useful online tools, has two problems: The keyboard and the LCD do not work. Well, the LCD works erratically, most of the times a couple of seconds after boot. The first problem can be fixed by attaching a USB keyboard, and the second by attaching an external screen.

Except that the machine does not enable the VGA output by default; but no problem, you just press Fn+F8 and voilà, external screen works. Except that external keyboards do not have the Fn key; but no problem, you can emulate it with Scroll Lock by just telling the BIOS to do so.

But you can't do it if you can't see anything on the screen. To do it blindly, you have to either know you BOIS by heart or find any reference online. I don't know that BIOS by heart, mainly because it's been a loooong while since I had to use it for anything, but also because I barely touch that machine anymore. And online references, well, there are none for models so old.

One of the possible solutions it occured to me that could help was to try to run a BIOS image, which you can still download from Dell's site (!), under qemu, but this tool cannot run arbitrary BIOSes. A pity, but understandable.

So without further ado, a schematic of the BIOS contents and how to fix this blindly:

- System
| System Info         <-- the cursor starts here
| Processor Info
| Memory Info
| Device Info
| Battery Info
| Battery Health
| Date/Time
| Boot Sequence
+ Onboard Devices
+ Video
+ Security
+ Performance
+ Power Management
+ Maintenance
- POST Behaviour      <-- 14 * <Down> + <Enter> and the following menu opens
| Adapter Warnings
| Fn Key Emulation    <-- 2 * <Down> + <Enter> and the setup screen opens
| Fast Boot
| Virtualization
| Keypad (embedded)
| Numlock LED
| USB Emulation
+ Wireless

The setup screen is quite simple, it has two options, Off and Scroll Lock, and you move with <Left> and <Right>. I'm not sure if it's needed, but pressing <Enter> to choose your option does not hurt. Then you press <Esc>, which gives you the Exit screen. This screen has three options: Remain in Setup (which is selected), Save/Exit and Discard/Exit. Guess which one you want :^) Just press <Right>, <Enter> and you're done! The machine reboots and now you can use <Scroll Lock>+<F8> in your external keyboard to activate the external screen.


misc

Juanjo Conti: Goodreads review: El Fantasma De Las Invasiones Inglesas: [Buenos Aires En 1806] (Claudia Piñeiro)

Lo leí de a poco, pero cuando llegué a los capítulos finales tuve que acelerar para saber qué pasaría.

La parte de la última batalla contra los ingleses me emocionó hasta las lágrimas.

El libro está pensando para ser leíd por alumnos de secundaria, en la materia de historia o lengua y da links para "seguir invistigando". Pero no me gustó mucho que las referencias a blogspot estén metidas en el texto.

Rating: 3/5

Original: https://www.goodreads.com/review/show/1861774371

Facundo Batista: Parque Acuático


Entre Navidad y Año Nuevo nos tomamos unos días de vacaciones con la familia.

Esta vez nos fuimos, por primera vez, a un Parque Acuático.

La verdad es que lo pasamos bárbaro. Yo le tenía un poco de aprensión por si Malena iba a disfrutarlo (Felipe, siendo más grande, seguro que sí). Ambos la pasaron genial, así como también Moni y yo.

Moni y Male disfrutando

El primer día llegamos a la tardecita y estaba nublado y fresco, así que en el parque acuático propiamente dicho no había nadie. Nosotros tampoco nos metimos, sino que fuimos directamente a las piletas con aguas termales, así estábamos calentitos :)

Piletas con aguas termales

Pero lo que más disfrutamos fué el parque acuático propiamente dicho, con todas sus variantes de juegos para tirarse al agua. Al principio Male se quedaba en los juegos para niños, pero luego del primer día también se tiró mucho de la rampa grande.

Juegos de los niños

Felu y Male en la rampa grande

Felu se tiró de casi todos lados (excepto el más salvaje, que era casi caída libre), incluso se tiró de los juegos grandes un montón de veces, en loop: se tiraba, subía, se tiraba, subía, se tiraba...

Felipe en el juego que te hace girar

También aprovechamos para pasear y conocer Concepción del Uruguay. Incluso una de las tardes vinieron familiares de Moni desde Concordia, y nos fuimos a las playas de Banco Pelay, donde nos metimos en el rio y jugamos con la arena hasta que se hizo de noche y nos fuimos al pueblo a comernos unas pizzas :)
http://www.turismoentrerios.com/cdeluruguay/pelay.htm

Moni con la prima Sandra y la tia Rosa

Almorzando con la familia

La escapada de pocos días al parque acuático mostró ser una copada forma de desconectar. Seguro repetiremos.

Juanjo Conti: Goodreads review: Tiempo muerto (Germán Bartizzaghi)

Me gustó este libro. El autor domina completamente el lenguaje y tiene muchas herramientas a su alcance (como por ejempo, un rico vocabulario, que le viene al pelo al narrador, un bibliotecario jubilado, y del que solo no voy a perdonar usar supermercado y almacen como sinónimos).

Sin embargo, el final (del capítulo de los moteles en adelante) se me hizo apresurado y me dejó con demasiadas preguntas.

Rating: 3/5

Original: https://www.goodreads.com/review/show/1883570308

Facundo Batista: Bronca con los dos dedos en V


Hoy volví en el auto, a casa. Escuchando mucha música. Pasó este tema, y me di cuenta que es lo que siento con respecto al 2016.

[Pinchen aquí]

Bronca cuando ríen satisfechos
al haber comprado sus derechos
Bronca cuando se hacen moralistas
y entran a correr a los artistas

Bronca cuando a plena luz del día
sacan a pasear su hipocresía
Bronca de la brava, de la mía
bronca que se puede recitar

Para los que toman lo que es nuestro
con el guante de disimular
Para el que maneja los piolines
de la marioneta universal

Para el que ha marcado las barajas
y recibe siempre la mejor
Con el as de espadas nos domina
y con el de bastos entra a dar y dar y...

¡Marcha! Un, dos...
No puedo ver tanta mentira organizada
Sin responder,
Con voz ronca mi bronca, mi bronca

Bronca porque matan con descaro
pero nunca nada queda claro
Bronca porque roba el asaltante
pero también roba el comerciante

Bronca porque está prohibido todo
hasta lo que haré de cualquier modo
Bronca porque no se paga fianza
si nos encarcelan la esperanza

Los que mandan tienen este mundo
repodrido y dividido en dos
Culpa de su afán de conquistarse
por la fuerza o por la explotación

Bronca pues entonces cuando quieren
que me corte el pelo sin razón,
Es mejor tener el pelo libre
que la libertad con fijador

¡Marcha!  No puedo ver
Tanto desastre organizado
sin responder con voz ronca
mi bronca mi bronca

Bronca sin fusiles y sin bombas
Bronca con los dos dedos en V
Bronca que también es esperanza
Marcha de la bronca y de la fe

Feliz 2017.

Facundo Batista: Regalo de fin de año: Recordium


En estas últimas semanas terminé de poner a punto un proyectito que había empezado durante el año. Aunque le faltan algunos detalles, ya es funcional y útil.

Se llama Recordium. Es una aplicación sencillita que ayuda al vos-fuera-de-tu-compu a recordarle cosas a tu futuro vos-en-la-compu.

Recordium

La idea es que ejecutás Recordium en tu computadora, y se pone ahí como un iconito pequeñito.

Después, en cualquier momento, estando en la calle, cortando el pasto, en la cola de la panadería, etc, cuando te acordás de algo que tenés que hacer, le mandás un texto o audio de Telegram a tu Bot de Recordium.

Cuando volvés a tu computadora (donde tomás las acciones correspondientes sobre eso que te habías acordado), el iconito de Recordium va a estar iluminado, te va a decir que tenés un mensaje nuevo (o más), y ahí podés leer/escuchar lo que te habías acordado en otro momento.

¿Se podría hacer algo similar utilizando herramientas más complejas? Sí. ¿O algún servicio de Google? También, pero no quiero meterle más yo a Google. Igual, lo más importante de Recordium es que me sirvió de proyecto juguete para (al mismo tiempo que lograba una funcionalidad que yo quería) tener algo hecho en Python 3 y PyQt 5.