joe di castrohttp://joedicastro.comThu, 07 Jun 2012 00:00:00 +0200Productividad en el escritorio Linux: Awesomehttp://joedicastro.com/productividad-en-el-escritorio-linux-awesome.html<p>Como había comentando en el anterior articulo sobre <a href="http://joedicastro.com/productividad-en-el-escritorio-linux-xmonad.html">Xmonad</a>, tenía la intención de probar un <a href="http://joedicastro.com/productividad-en-el-escritorio-linux-tiling.html">Gestor de ventanas de mosaico</a> más, antes de tomar la decisión final de cual emplear a diario. Y si, <em>y solo si</em>, resultaba ser una mejor alternativa, abandonaría <strong>Xmonad</strong>. Este <strong>tiling window manager</strong> era <a href="http://awesome.naquadah.org/">Awesome</a> y ha conseguido con creces que abandone a Xmonad.</p> <p><strong>Awesome</strong> carece de algunas funcionalidades que me ofrecía Xmonad, pero después de trabajar con él durante seis meses y conseguir tener una configuración a mi medida, solamente hecho en falta una característica que comentare después. Además Awesome me ofrece algunas características que no me ofrecía Xmonad y que valoro lo suficiente como para realizar el cambio sin mirar atrás.</p> <h2 id="awesome_vs_xmonad">Awesome vs Xmonad</h2> <p>En esta tabla podemos ver una comparativa rápida de algunas de las características de ambos gestores de ventanas.</p> <table> <thead> <tr> <th>Característica</th> <th>Awesome</th> <th>Xmonad</th> </tr> </thead> <tbody> <tr> <td><strong>Lenguaje</strong></td> <td>C</td> <td>Haskell</td> </tr> <tr> <td><strong>Extensible</strong></td> <td>Lua</td> <td>Haskell</td> </tr> <tr> <td><strong>Gestión ventanas</strong></td> <td>Automático</td> <td>Automático</td> </tr> <tr> <td><strong>Soporte ratón</strong></td> <td>Muy bueno</td> <td>Básico</td> </tr> <tr> <td><strong>Bandeja sistema (systray)</strong></td> <td>Integrada</td> <td>No</td> </tr> <tr> <td><strong>Paneles</strong></td> <td>Integrado</td> <td>No</td> </tr> <tr> <td><strong>Reinicio en caliente</strong></td> <td>Si</td> <td>Si</td> </tr> <tr> <td><strong>Librería</strong></td> <td>XCB</td> <td>Xlib</td> </tr> <tr> <td><strong>Soporte varios monitores</strong></td> <td>Muy bueno</td> <td>Bueno</td> </tr> <tr> <td><strong>Transparencias</strong></td> <td>Gestor externo</td> <td>Gestor externo</td> </tr> <tr> <td><strong>Integración escritorios</strong></td> <td>Buena</td> <td>Muy buena (Gnome, KDE)</td> </tr> <tr> <td><strong>Desarrollo</strong></td> <td>Muy activo</td> <td>Muy activo</td> </tr> <tr> <td><strong>Estabilidad</strong></td> <td>Estable</td> <td>Estable</td> </tr> <tr> <td><strong>Documentación</strong></td> <td>Buena</td> <td>Buena</td> </tr> </tbody> </table> <h3 id="ventajas">Ventajas</h3> <p>Una de las principales ventajas de Awesome sobre Xmonad es la velocidad de respuesta que ofrece el entorno, que en Awesome es bastante superior a la de Xmonad. Alguna que otra vez, al intentar realizar muchas operaciones consecutivas entre ventanas y escritorios en Xmonad, se me ha quedado colgado y he tenido que reiniciarlo (que se hace en caliente y en segundos, pero no deja de ser algo molesto). En este sentido Awesome solo se me ha colgado un par de veces.</p> <p>Otra de las grandes ventajas es que al configurarse en <a href="https://es.wikipedia.org/wiki/Lua">Lua</a> es bastante más sencillo hacerse con él, ya que es un lenguaje relativamente asequible y carece de la complejidad inicial de <a href="https://es.wikipedia.org/wiki/Haskell">Haskell</a> para aquellos que no conocen la programación funcional. Esto aumenta las posibilidades de personalizarlo para un usuario con conocimientos muy básicos de programación.</p> <p>La configuración por defecto de Awesome también es más completa y amigable que la de Xmonad, partiendo de un esquema tradicional de ventanas flotantes y con menús que nos permiten dar los primeros pasos y poder abandonar la sesión sin llegar a conocer las combinaciones de teclado por defecto. Algo que agradecerán aquellos que se hayan tenido que enfrentar a una configuración por defecto de Xmonad por primera vez. Esto invita a conocer el sistema y no abandonarlo "asustado" por su complejidad. En la imagen se puede ver el aspecto que presenta una sesión de Awesome con la configuración por defecto.</p> <p style="text-align:center;"><img src="pictures/awesome_default.png" width="700" height="525" alt="configuración por defecto de Awesome" /></p> <blockquote> <p>Para acceder al menú podemos bien hacer click sobre el icono de Awesome en la parte superior izquierda o bien con el botón derecho en cualquier parte de la pantalla. También se puede acceder a él con la combinación de teclas <strong><code>Win</code></strong> + <strong><code>w</code></strong></p> </blockquote> <p>Finalmente, el que Awesome tenga integrados aspectos como los paneles, una bandeja del sistema (systray), lanzador de aplicaciones y un soporte muy bueno del ratón facilita el poder emplearlo en solitario, sin un sistema de escritorio tradicional detrás. Y a través de librerías es fácil implementar un sistema de notificaciones, un localizador de ventanas, temas, menús emergentes, ...</p> <h3 id="desventajas">Desventajas</h3> <p>Quizás para mí la mayor desventaja frente a Xmonad y lo único que hecho realmente en falta, es la imposibilidad, a diferencia de Xmonad, de poder regular el tamaño vertical de las ventanas. Es particularmente útil en algunas situaciones y en Xmonad está integrado de manera natural. Pero después de varios meses he aprendido a vivir sin ello.</p> <p>La otra gran desventaja es que el desarrollo aún no ha alcanzado el estadio de madurez de Xmonad, esta sujeto a demasiados cambios y no cuidan demasiado la retrocompatibilidad. Las nuevas versiones frecuentemente obligan a realizar cambios en la configuración para que todo vuelva a funcionar con normalidad.</p> <p>Por otro lado, la instalación en algunas distribuciones puede no ser tan sencilla como la de Xmonad por la falta de soporte a la librería XCB o por necesitar versiones especificas de cairo.</p> <h3 id="diferentes_filosof+as">Diferentes filosofías</h3> <p>Siendo como son ambos, gestores de ventanas de mosaico, difieren particularmente en la manera de entender principalmente dos conceptos:</p> <h4 id="__m+ltiples_escritorios__"><strong>Múltiples escritorios</strong></h4> <p>Aquí Xmonad sigue el concepto tradicional de múltiples escritorios en Linux, soportando por defecto 9 por monitor y asignándoles un número del 1 al 0. Luego una aplicación puede estar, por ejemplo, en el escritorio 4 del monitor 2 y podemos movernos entre escritorios y monitores y mover a su vez las aplicaciones entre ellos.</p> <p>En cambio, Awesome, aunque aparentemente sigue el mismo sistema, y para cualquiera que no quiera profundizar en ello no habrá diferencia alguna, se basa en un concepto diferente. En Awesome cada escritorio es en realidad una <strong>etiqueta</strong> y puede ser tanto un número como un texto. En principio también son 9 por monitor, aunque esto puede ampliarse o reducirse en la configuración. La diferencia principal es que una aplicación puede ser asignada a varias etiquetas simultáneamente y puede por lo tanto ser mostrada en varios <em>escritorios</em> a la vez. Esto permite asignar de forma muy sencilla etiquetas destinadas a una tarea y predefinir ciertas aplicaciones para que sean mostradas en una o más etiquetas. Por ejemplo podemos tener una etiqueta para <code>redes sociales</code> y mostrar allí un navegador, pero al mismo tiempo podemos tener una etiqueta <code>desarrollo</code> en la que también queremos que se muestre el navegador. Por otro lado, también es posible mostrar varias etiquetas al mismo tiempo, lo que nos permite trabajar en dos tareas distintas y bien definidas, cada una en su etiqueta, y en un momento dado, visualizarlas juntas sin perder la asignación de etiquetas original. En este sentido Awesome es mucho más flexible y potente que Xmonad.</p> <h4 id="__m+ltiples_monitores__"><strong>Múltiples monitores</strong></h4> <p>En este caso Xmonad comparte el mismo escritorio en distintos monitores. Por lo tanto si estamos en el escritorio 1 en el monitor 1 y nos movemos al escritorio 2, lo hará en todos los monitores a la vez, lo que también es el comportamiento clásico. Con lo que podemos decir que aunque tenemos 9 escritorios por monitor, se comporta como si tuviéramos 9 para todos los monitores.</p> <p>Awesome, al contrario, emplea 9 etiquetas por monitor independientes entre si. Lo que significa que en este casi si tenemos 9 <em>escritorios</em> reales por cada monitor. Si nos encontramos en el monitor 1 y la etiqueta 1, al cambiar a la etiqueta 2, el resto de monitores permanecerán inalterados en la etiqueta en la que estuvieran previamente. En este sentido Awesome también sigue siendo bastante más flexible y potente que Xmonad. Este comportamiento puede ser alterado mediante la configuración. Hay quienes prefieren un método de trabajo y quienes prefieren el otro, yo soy de los que prefieren el comportamiento de Awesome.</p> <h2 id="awesome_con_gnome">Awesome con Gnome</h2> <p>Actualmente estoy empleando Awesome en solitario, si un escritorio detrás, lo que me obliga a configurar por mi cuenta todos los servicios que estos proporcionan, pero me compensa con la ligereza que me reporta el no emplear un pesado escritorio por debajo. Sin embargo, los primeros meses lo empleé conjuntamente con Gnome en Ubuntu, utilizando solo los componentes básicos del mismo. La forma de configurar una sesión de Awesome con Gnome en Ubuntu (11.10 y 12.04) y en <a href="http://www.archlinux.org">Arch Linux</a>, la distribución que estoy empleando ahora, es a través de los siguientes ficheros:</p> <p><code>/usr/share/applications/awesome.desktop</code></p> <div class="codehilite"><pre><span class="k">[Desktop Entry]</span> <span class="na">Version</span><span class="o">=</span><span class="s">1.0</span> <span class="na">Type</span><span class="o">=</span><span class="s">Application</span> <span class="na">Name</span><span class="o">=</span><span class="s">Awesome</span> <span class="na">Comment</span><span class="o">=</span><span class="s">The awesome launcher!</span> <span class="na">TryExec</span><span class="o">=</span><span class="s">awesome</span> <span class="na">Exec</span><span class="o">=</span><span class="s">awesome</span> </pre></div> <p><code>/usr/share/gnome-session/sessions/awesome.session</code></p> <div class="codehilite"><pre><span class="k">[GNOME Session]</span> <span class="na">Name</span><span class="o">=</span><span class="s">Awesome session</span> <span class="na">RequiredComponents</span><span class="o">=</span><span class="s">gnome-settings-daemon;</span> <span class="na">RequiredProviders</span><span class="o">=</span><span class="s">windowmanager;</span> <span class="na">DefaultProvider-windowmanager</span><span class="o">=</span><span class="s">awesome</span> <span class="na">DesktopName</span><span class="o">=</span><span class="s">GNOME</span> </pre></div> <p><code>/usr/share/xsessions/awesome-gnome-session.desktop</code></p> <div class="codehilite"><pre><span class="k">[Desktop Entry]</span> <span class="na">Name</span><span class="o">=</span><span class="s">Awesome GNOME</span> <span class="na">Comment</span><span class="o">=</span><span class="s">Dynamic window manager</span> <span class="na">TryExec</span><span class="o">=</span><span class="s">/usr/bin/gnome-session</span> <span class="na">Exec</span><span class="o">=</span><span class="s">gnome-session --session=awesome</span> <span class="na">Type</span><span class="o">=</span><span class="s">XSession</span> </pre></div> <p>Evidentemente para esto es necesario instalar los paquetes necesarios para ejecutar Awesome que en el caso de Ubuntu son <code>awesome</code> y <code>awesome-extra</code>:</p> <div class="codehilite"><pre><span class="gp">$</span> sudo apt-get install awesome awesome-extra </pre></div> <p>En Arch, bastaría con instalar el paquete <code>awesome</code>:</p> <div class="codehilite"><pre><span class="gp">$</span> sudo pacman -S awesome </pre></div> <h2 id="mi_configuraci+n">Mi configuración</h2> <p>A diferencia de Xmonad, mi configuración de Awesome no está contenida en un solo fichero, ya que el tema y los diversos plugins están alojados dentro de sus propios directorios. Además el fichero de configuración <code>rc.lua</code> es demasiado extenso (cerca de 1200 lineas) para volcarlo aquí. Así que me limitare a mencionar los aspectos más destacados, la configuración completa queda disponible a través de mi repositorio en <a href="http://github.com/joedicastro/dotfiles">GitHub</a>.</p> <p>Destacar que al principio del fichero incluyo una <em>Cheat Sheet</em> ("chuleta") con todas las combinaciones de teclado y ratón que tengo habilitadas en mi configuración.</p> <h2 id="panel_y_widgets">Panel y Widgets</h2> <p>Awesome permite la creación de varios paneles, generalmente se suelen crear en la parte superior y/o inferior de la pantalla. A mi me gusta disponer del máximo espacio posible para las aplicaciones, así que solo he creado uno superior que además puedo ocultar a conveniencia. De hecho, para determinadas tareas, lo mantengo oculto la mayor parte del tiempo y solo lo muestro cuando me interesa consultar la información que allí se muestra.</p> <p>Aquí se puede ver la apariencia del panel superior y una ampliación del mismo:</p> <p style="text-align:center;"><img src="pictures/wibox_full.png" width="700" height="8" alt="wibox" /></p> <p style="text-align:center;"><img src="pictures/wibox.png" width="600" height="63" alt="Zoom sobre la barra de estado" /></p> <p>En el que se pueden apreciar (de izquierda a derecha y de arriba a abajo) los siguientes widgets:</p> <ul> <li>Icono de Awesome. Proporciona acceso al menú de Awesome</li> <li>Etiquetas. Aquí se puede ver que hay dos activas y que nos encontramos en la segunda, <code>β</code></li> <li>Icono de esquema. Vemos que está seleccionado el esquema <code>tile</code></li> <li>Icono y titulo de la ventana activa. En este caso tenemos una ventana de <em>Gvim</em> y además el icono del final nos indica que es una ventana flotante</li> <li>Pomodoro. Es un widget que me permite seguir el método <a href="http://www.pomodorotechnique.com/">Pomodoro</a> y que indica que quedan 4 minutos y 14 segundos para tomarme un pequeño descanso.</li> <li>MPD. Indica el estado del servidor de música <em>mpd</em>, y en este caso nos indica el autor y el titulo de la canción que se está reproduciendo</li> <li>Velocidad de los ventiladores del sistema</li> <li>Temperaturas de CPU y GPU</li> <li>Uso de las CPUs del microprocesador</li> <li>Porcentaje y cantidad de memoria RAM en uso</li> <li>Velocidad (en Kbs) de bajada y subida de la red.</li> <li>Porcentaje de ocupación en disco de <code>/</code> y <code>/home</code></li> <li>Estado de la batería y tiempo estimado de carga/descarga</li> <li>Uptime. Indica el tiempo que lleva el equipo encendido desde el último reinicio</li> <li>Versión del Kernel Linux en ejecución</li> <li>Volumen del sonido del sistema</li> <li>Fecha y hora</li> </ul> <p>Muchos prefieren añadir iconos o encabezados a todos los widgets para facilitar su identificación, pero yo ya conozco para que es cada uno y prefiero un entorno minimalista que me distraiga lo menos posible. Muchos de estos widgets ejecutan una acción al ser pulsados con un botón del ratón o al pasar por encima de ellos. Por ejemplo al pasar el ratón por encima de la fecha y hora se muestra un calendario y al pulsar con el botón izquierdo sobre el uso de las CPUs, se lanza una ventana con el programa <code>htop</code></p> <h2 id="localizar_aplicaciones">Localizar aplicaciones</h2> <p>Una de las funcionalidades geniales que tenía implementada en Xmonad me permitía conocer todas las ventanas que estaban abiertas y elegir la deseada con una rápida combinación de teclas. Awesome no tiene esto implementado, pero gracias a una librería externa, <strong><a href="https://github.com/bioe007/awesome-revelation">Revelation</a></strong>, podemos emplear un método similar al famoso Exposé del Mac OS y también presente en Compiz. Lo que hace es mostrarnos en la etiqueta que estemos actualmente todas las ventanas abiertas en forma de mosaico y podemos elegir una de ellas para saltar automáticamente a ella (y la etiqueta en la que se encuentre). Aquí podemos ver un screencast de su funcionamiento:</p> <p style="text-align:center;"><img src="pictures/revelation.gif" width="640" height="400" alt="Revelation en funcionamiento" /></p> <p>Es también un método muy rápido y muy visual, al final he acabado prefiriendo este método al que empleaba en Xmonad, ya que en este último, el titulo de las ventanas podía ser muy ambiguo y no ser fácil dar con la ventana adecuada.</p> <h2 id="gesti+n_din+mica_de_etiquetas">Gestión dinámica de etiquetas</h2> <p>Aunque por defecto Awesome define 10 etiquetas por monitor, podemos definir a nuestro antojo el número de ellas que queramos en el fichero de configuración. Podemos optar por un número clásico en los escritorios Linux, cuatro, o podemos crear una para cada tarea concreta más una libre. Por defecto tengo definidas diez, empleando para identificarlas los números en griego:</p> <div class="codehilite"><pre><span class="c1">-- definición de las etiquetas en el fichero de configuración rc.lua</span> <span class="n">tags</span><span class="p">[</span><span class="n">s</span><span class="p">]</span> <span class="o">=</span> <span class="n">awful</span><span class="p">.</span><span class="n">tag</span><span class="p">({</span> <span class="s2">&quot;</span><span class="s">α&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="s">β&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="s">γ&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="s">δ&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="s">ε&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="s">ς&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="s">ζ&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="s">η&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="s">θ&quot;</span><span class="p">},</span> <span class="n">s</span><span class="p">,</span> <span class="n">layouts</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> </pre></div> <p>Sin embargo, en mi configuración empleo una librería externa, <a href="http://git.glacicle.org/eminent">Eminent</a>, que gestiona estas etiquetas de forma dinámica, creándolas y destruyéndolas según sea necesario. Así de entrada solo tenemos una etiqueta, <code>α</code> y solo se creara una segunda etiqueta, <code>β</code> si nos desplazamos a ella. Del mismo modo, cuando eliminamos la última ventana de una etiqueta y la abandonamos, se destruye. La ventaja de esto es que por un lado nos facilita localizar donde estamos más fácilmente y por otro, que en caso de ser necesario, si necesitamos más etiquetas (de las creadas por defecto), las creara de forma automática. De este modo cuando llegamos a la etiqueta <code>θ</code>, si necesitamos otra, creara la <code>10</code> y así en lo sucesivo.</p> <h2 id="lanzar_aplicaciones">Lanzar aplicaciones</h2> <p>Existen dos métodos para realizar esta tarea:</p> <ul> <li>Empleando un prompt que emerge en el panel superior y nos permite escribir el comando que queremos ejecutar y que posee autocompletado. La combinación de teclas por defecto que activa esto es <strong><code>Win</code></strong> + <strong><code>r</code></strong></li> </ul> <p style="text-align:center;"><img src="pictures/awesome_prompt.png" width="585" height="30" alt="prompt en Awesome" /></p> <ul> <li>Empleando <a href="http://awesome.naquadah.org/wiki/Menubar">menubar</a>. Menubar es una librería externa, que será incluida en la próxima versión de Awesome por defecto, que al igual que muchos otros lanzadores de aplicaciones (<em>Gnome Do</em>, <em>Kupfer</em>, <em>Synapse</em>, etc) nos va mostrando las aplicaciones disponibles en función de lo que vayamos tecleando. Se lanza con la combinación de teclas <strong><code>Win</code></strong> + <strong><code>p</code></strong> y en mi caso, esta aparece inmediatamente debajo del panel superior. Aquí se puede ver la menubar en funcionamiento (la tecla <strong><code>Win</code></strong> también es llamada <strong><code>Super</code></strong> ):</li> </ul> <p style="text-align:center;"><img src="pictures/menubar.gif" width="640" height="400" alt="Lanzar aplicaciones con menubar en Awesome wm" /></p> <p>Yo además empleo un tercer método que heredo de Xmonad, y es emplear <a href="http://tools.suckless.org/dmenu/">dmenu</a> para lanzar aplicaciones. <code>dmenu</code> es muy parecido al prompt de Awesome, pero busca para el autocompletado en todo el nombre del comando y no solo al principio. Además muestra todas las coincidencias disponibles y que se pueden seleccionar con las teclas de dirección.</p> <p style="text-align:center;"><img src="pictures/dmenu.gif" width="640" height="400" alt="dmenu en acción" /></p> <h3 id="grabar_v+deos_y_screencasts_del_escritorio">Grabar vídeos y screencasts del escritorio</h3> <p>Adicionalmente, tengo definidas ciertas combinaciones de teclas para lanzar determinadas aplicaciones o procesos con las teclas de función. Dentro de estos atajos de teclado cabe destacar cinco que en lugar lanzar una aplicación, comienzan o terminan un determinado proceso. Estas combinaciones, que van de <strong><code>F8</code></strong> a <strong><code>F12</code></strong>, las utilizo para grabar vídeos y screencasts con gifs animados y son las que he empleado para ilustrar este articulo.</p> <div class="codehilite"><pre><span class="c1">-- Win + F8 Start gif screencast recording LowRes</span> <span class="c1">-- Win + F9 Start gif screencast recording HighRes</span> <span class="c1">-- Win + F10 Stop gif screencast recording</span> <span class="c1">-- Win + F11 Start mkv screencast recording</span> <span class="c1">-- Win + F12 Stop mkv screencast recording</span> <span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">&quot;</span><span class="s">F8&quot;</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn_with_shell</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">rm &quot;</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">/screencast.gif&quot;</span><span class="p">)</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">ffmpeg -f x11grab -s &quot;</span> <span class="o">..</span> <span class="n">scr_res</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s"> -r 2 -i :0.0 -b:v 500k -pix_fmt rgb24 -y&quot;</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s"> -loop 0 -s 640x400 &quot;</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">/animated.gif&quot;</span><span class="p">)</span> <span class="k">end</span><span class="p">),</span> <span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">&quot;</span><span class="s">F9&quot;</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn_with_shell</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">rm &quot;</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">/screencast.gif&quot;</span><span class="p">)</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">ffmpeg -f x11grab -s &quot;</span> <span class="o">..</span> <span class="n">scr_res</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s"> -r 2 -i :0.0 -b:v 500k -pix_fmt rgb24 -y&quot;</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s"> -loop 0 -s 1440x900 &quot;</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">/animated.gif&quot;</span><span class="p">)</span> <span class="k">end</span><span class="p">),</span> <span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">&quot;</span><span class="s">F10&quot;</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">killall ffmpeg&quot;</span><span class="p">)</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">convert ephemeral:&quot;</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">/animated.gif -fuzz 7% -layers Optimize &quot;</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">/screencast.gif&quot;</span><span class="p">)</span> <span class="k">end</span><span class="p">),</span> <span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">&quot;</span><span class="s">F11&quot;</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn_with_shell</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">rm &quot;</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">/screencast.mkv&quot;</span><span class="p">)</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">ffmpeg -f x11grab -s &quot;</span> <span class="o">..</span> <span class="n">scr_res</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s"> -r 25 -i :0.0 -sameq &quot;</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">/screencast.mkv&quot;</span><span class="p">)</span> <span class="k">end</span><span class="p">),</span> <span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">&quot;</span><span class="s">F12&quot;</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">killall ffmpeg&quot;</span><span class="p">)</span> <span class="k">end</span><span class="p">)</span> </pre></div> <h2 id="gesti+n_tiempo_con_pomodoro">Gestión tiempo con pomodoro</h2> <p>La <a href="https://es.wikipedia.org/wiki/T%C3%A9cnica_Pomodoro">técnica Pomodoro</a> puede ser muy provechosa en ciertas tareas si se emplea con sentido común y se sigue más o menos a rajatabla. Yo la empleo muy a menudo cuando tengo una tarea concreta en la que quiero centrarme sin distracciones para sacarla adelante y no caer en el error de procrastinar demasiado. Es una combinación ideal entre concentración puntual y alternar distracciones, que impiden a uno "quemarse" por no saber echar el freno a tiempo. Es una técnica muy útil a la hora de programar o de crear un articulo como este, pero que es difícilmente aplicable en tareas que requieren cierta multitarea como son las de administración de sistemas.</p> <p>Existen múltiples aplicaciones, applets, indicadores, etc para aplicar esta técnica, que se basaba originalmente en un simple reloj de cocina. Pero alguien, en su momento pensó, que no era mala idea crear un widget para Awesome que nos permitiera medir los tiempos para aplicarla y creo una librería externa para ello. Yo empleo esta <a href="https://github.com/nikolavp/awesome-pomodoro">librería</a> ligeramente modificada para controlar el tiempo transcurrido.</p> <p>El funcionamiento es muy básico, pulsamos sobre el icono y se activa la cuenta atrás de 25 minutos. Al acabar, una alarma sonora y una notificación emergente, nos avisan de que se ha terminado el tiempo de trabajo y nos merecemos un descanso. Volvemos a pulsar sobre el widget y comienza la cuenta atrás de cinco minutos y se repite el proceso. Si pulsamos con el botón derecho se reinicia el widget.</p> <p style="text-align:center;"><img src="pictures/pomodoro.png" width="613" height="105" alt="notificaciones de pomodoro" /></p> <h2 id="debug_con_xephyr">Debug con Xephyr</h2> <p>Esta es una de las posibilidades que nos permite Awesome, que más nos ayudará a la hora de "trastear" con él, sin temor a "romper" nada. Podemos depurar los errores y realizar pruebas con Awesome con una configuración distinta a la nuestra y en una sesión X distinta a la actual. Esto lo conseguimos ejecutando Awesome dentro de un servidor X, <a href="http://www.freedesktop.org/wiki/Software/Xephyr">Xephyr</a>, que aparecerá dentro de nuestra sesión como una ventana más.</p> <p>Yo he integrado esta posibilidad dentro del menú de Awesome para que sea mucho más sencillo e inmediato el poder probar cambios en un entorno de pruebas.</p> <p style="text-align:center;"><img src="pictures/awesome_menu.png" width="603" height="275" alt="Mi menu de Awesome" /></p> <p>En este vídeo se puede ver el funcionamiento básico de este sistema. Normalmente inicio el entorno de pruebas a pantalla completa, pero que se pueda apreciar mejor la diferencia, he grabado la mayoría del vídeo con una sesión de Xephyr a menor resolución. Lo que se puede ver es como primero inicio una sesión de Awesome dentro de Xephyr con la configuración por defecto. Después la cierro y compruebo la sintaxis Lua de la configuración de test. La notificación me alerta de que el fichero no existe, luego procedo a crearlo (es una copia de la configuración real actual) y vuelvo a comprobar la sintaxis. Una vez que veo que esta es correcta, lanzo Awesome con la configuración de test. Cierro la sesión y procedo a realizar cambios en la configuración de pruebas. Ahora lanzo de nuevo Awesome con esta configuración y compruebo que efectivamente se han realizado los cambios. Dentro de esta sesión vuelvo a editar la configuración de test para deshacer los cambios y después reinicio este Awesome de pruebas. Se puede ver como efectivamente todo vuelve a el estado anterior. Cierro la sesión y compruebo el log de la sesión para ver los mensajes de error. Finalmente abro varias sesiones de Awesome a la vez y una a pantalla completa.</p> <div style="text-align:center"> <iframe src="http://player.vimeo.com/video/43562306" width="700" height="438"> </iframe> <p>Muestra de las posibilidades que ofrecen Xephyr y el script <strong>awdt.py</strong> para poder depurar la configuración de Awesome. Recomiendo ver en alta resolución y a pantalla completa.</p> </div> <p>Para realizar estas acciones programé un script en Python, <code>awdt.py</code>, que incluyo al final del articulo.</p> <p>Una de las ventajas de Awesome con respecto a Xmonad, es que no necesitamos recompilar cada vez que realizamos un cambio en la configuración, basta con editar el fichero, salvar y reiniciarlo. Reiniciar Awesome es algo que lleva menos de un segundo.</p> <h2 id="reinicio_apagado_y_suspensi+n">Reinicio, apagado y suspensión</h2> <p>Dado que no empleo ningún escritorio, arrancando directamente la sesión en Awesome, debo gestionar directamente cierto tipo de situaciones que vienen resueltas de manera predefinida en estos. Uno de estos casos es la gestión de energía del equipo, esto es: apagarlo, reiniciarlo, suspenderlo e hibernarlo. Dado que nunca lo hiberno, he implementado únicamente las tres primeras acciones. Lo que hago es emplear directamente los comandos de consola, que ejecuto a través de un dialogo gráfico que me pide la contraseña para <code>sudo</code> con <code>gksudo</code> (podría haber empleado <em>Zenity</em>, <em>Xdialog</em> o cualquier otro similar) que es activado a través de una combinación de teclas. Por ejemplo, para suspender el equipo lo activo a través de la combinación <strong><code>Win</code></strong> + <strong><code>s</code></strong> :</p> <div class="codehilite"><pre><span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">&quot;</span><span class="s">s&quot;</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">&quot;</span><span class="s">gksudo pm-suspend -m &quot;</span> <span class="o">..</span> <span class="s2">&quot;</span><span class="s">&#39;Se va a suspender el equipo, ¿estás seguro?&#39;&quot;</span><span class="p">)</span> <span class="k">end</span><span class="p">),</span> </pre></div> <p>con el siguiente resultado:</p> <p style="text-align:center;"><img src="pictures/suspend.png" width="381" height="191" alt="Dialogo para suspensión" /></p> <p>Sé que la mayoría no está acostumbrado a tener que introducir la contraseña para realizar cualquiera de estas acciones y posiblemente detestarían hacerlo, pero yo lo prefiero así.</p> <h2 id="bloqueo_de_la_pantalla">Bloqueo de la pantalla</h2> <p>Empleo un método similar para bloquear la pantalla, ya que no empleo un salvapantallas (simplemente apago la pantalla pasado un cierto tiempo) empleo el programa <a href="http://joelburget.com/slimlock/"><code>slimlock</code></a> para realizar esta tarea y lo activo de forma manual con otra combinación de teclas. El resultado es una pantalla como esta:</p> <p style="text-align:center;"><img src="pictures/slimlock.png" width="642" height="401" alt="slimlock" /></p> <h2 id="documentaci+n_y_enlaces_de_inter+s">Documentación y enlaces de interés.</h2> <p>La documentación del código fuente y de la API de Awesome son bastante buenas, con lo que si tienes los conocimientos suficientes no te será muy dificil hacerte con él. Si necesitas algo más general, tanto el propio Wiki de Awesome como los recursos disponibles gracias a su comunidad (lista de correo e IRC) son bastante útiles para ayudarte a conseguir la configuración que más se ajuste a tus necesidades. Es una comunidad muy dinámica y bastante colaboradora. También en el Wiki de Arch Linux hay información interesante sobre Awesome.</p> <ul> <li><a href="http://awesome.naquadah.org/">Pagina principal</a></li> <li><a href="http://awesome.naquadah.org/wiki/Main_Page">Wiki</a></li> <li><a href="http://awesome.naquadah.org/wiki/Screenshots">Pantallazos</a></li> <li><a href="http://awesome.naquadah.org/wiki/User_Configuration_Files">Ficheros de configuración</a></li> <li><a href="http://awesome.naquadah.org/doc/api/">API Docs</a></li> <li><a href="https://wiki.archlinux.org/index.php/Awesome">Arch Linux Wiki</a></li> <li><a href="http://www.lua.org/pil/">Programming in Lua</a></li> </ul> <h2 id="awdtpy">awdt.py</h2> <p>Este es el contenido del script <code>awdt.py</code> que empleo para depurar la configuración de Awesome en un entorno de pruebas. Se encuentra dentro del mismo repositorio que el resto de la configuración.</p> <div class="codehilite"><pre><span class="c">#!/usr/bin/env python</span> <span class="c"># encoding: utf-8</span> <span class="sd">&quot;&quot;&quot;</span> <span class="sd"> awdt.py: a script to debug awesome wm configs in nested Xephyr sessions</span> <span class="sd"> This script is a tool intended to help to debug Awesome wm configurations</span> <span class="sd"> in a safe manner. To this purpose uses the Xephyr X server to nest a X</span> <span class="sd"> session inside the current Awesome X session.</span> <span class="sd"> The original idea come from the mikar&#39;s bash awmtt script (Thanks mikar):</span> <span class="sd"> https://github.com/mikar/awmtt</span> <span class="sd"> Needs logger.py and check_execs.py from my Python Recipes repository at</span> <span class="sd"> https://github.com/joedicastro/python-recipes</span> <span class="sd">&quot;&quot;&quot;</span> <span class="c">#==============================================================================</span> <span class="c"># Copyright 2012 joe di castro &lt;joe@joedicastro.com&gt;</span> <span class="c">#</span> <span class="c"># This program is free software: you can redistribute it and/or modify</span> <span class="c"># it under the terms of the GNU General Public License as published by</span> <span class="c"># the Free Software Foundation, either version 3 of the License, or</span> <span class="c"># (at your option) any later version.</span> <span class="c">#</span> <span class="c"># This program is distributed in the hope that it will be useful,</span> <span class="c"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span> <span class="c"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span> <span class="c"># GNU General Public License for more details.</span> <span class="c">#</span> <span class="c"># You should have received a copy of the GNU General Public License</span> <span class="c"># along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.</span> <span class="c">#==============================================================================</span> <span class="n">__author__</span> <span class="o">=</span> <span class="s">&quot;joe di castro &lt;joe@joedicastro.com&gt;&quot;</span> <span class="n">__license__</span> <span class="o">=</span> <span class="s">&quot;GNU General Public License version 3&quot;</span> <span class="n">__date__</span> <span class="o">=</span> <span class="s">&quot;05/06/2012&quot;</span> <span class="n">__version__</span> <span class="o">=</span> <span class="s">&quot;0.5&quot;</span> <span class="k">try</span><span class="p">:</span> <span class="kn">import</span> <span class="nn">os</span> <span class="kn">import</span> <span class="nn">sys</span> <span class="kn">from</span> <span class="nn">argparse</span> <span class="kn">import</span> <span class="n">ArgumentParser</span><span class="p">,</span> <span class="n">RawDescriptionHelpFormatter</span> <span class="kn">from</span> <span class="nn">re</span> <span class="kn">import</span> <span class="n">findall</span> <span class="kn">from</span> <span class="nn">shutil</span> <span class="kn">import</span> <span class="n">copy</span> <span class="kn">from</span> <span class="nn">subprocess</span> <span class="kn">import</span> <span class="n">Popen</span><span class="p">,</span> <span class="n">PIPE</span><span class="p">,</span> <span class="n">STDOUT</span> <span class="kn">from</span> <span class="nn">tempfile</span> <span class="kn">import</span> <span class="n">gettempdir</span> <span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span> <span class="kn">from</span> <span class="nn">logger</span> <span class="kn">import</span> <span class="n">Logger</span> <span class="kn">from</span> <span class="nn">check_execs</span> <span class="kn">import</span> <span class="n">check_execs</span> <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> <span class="c"># Checks the installation of the necessary python modules</span> <span class="k">print</span><span class="p">((</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s">&quot;An error found importing one module:&quot;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]),</span> <span class="s">&quot;You need to install it&quot;</span><span class="p">,</span> <span class="s">&quot;Stopping...&quot;</span><span class="p">]))</span> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="k">def</span> <span class="nf">arguments</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Defines the command line arguments for the script.&quot;&quot;&quot;</span> <span class="n">main_desc</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;Debug awesome wm configurations in Xephyr sessions.</span> <span class="s"> Use `new` to create a new test config file cloned from your rc.lua</span> <span class="s"> Use `check` to test the Lua syntax on this file</span> <span class="s"> Use `start` to start a new awesome debug session</span> <span class="s"> Use `restart` to restart all awesome debug sessions</span> <span class="s"> Use `stop` to stop all awesome debug sessions</span> <span class="s"> &quot;&quot;&quot;</span> <span class="n">parser</span> <span class="o">=</span> <span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="n">main_desc</span><span class="p">,</span> <span class="n">formatter_class</span><span class="o">=</span><span class="n">RawDescriptionHelpFormatter</span><span class="p">)</span> <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">&quot;action&quot;</span><span class="p">,</span> <span class="n">choices</span><span class="o">=</span><span class="p">[</span><span class="s">&quot;new&quot;</span><span class="p">,</span> <span class="s">&quot;check&quot;</span><span class="p">,</span> <span class="s">&quot;start&quot;</span><span class="p">,</span> <span class="s">&quot;restart&quot;</span><span class="p">,</span> <span class="s">&quot;stop&quot;</span><span class="p">],</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;the action to perform&quot;</span><span class="p">)</span> <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">&quot;-t&quot;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">&quot;test&quot;</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">&quot;store_true&quot;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;use created test configuration file&quot;</span><span class="p">)</span> <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">&quot;-s&quot;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">&quot;screen&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;the screen resolution&quot;</span><span class="p">)</span> <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">&quot;-d&quot;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">&quot;display&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;the DISPLAY to use&quot;</span><span class="p">)</span> <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">&quot;-v&quot;</span><span class="p">,</span> <span class="s">&quot;--version&quot;</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">&quot;version&quot;</span><span class="p">,</span> <span class="n">version</span><span class="o">=</span><span class="s">&quot;</span><span class="si">%(prog)s</span><span class="s"> {0}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">__version__</span><span class="p">),</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;show program&#39;s version number and exit&quot;</span><span class="p">)</span> <span class="k">return</span> <span class="n">parser</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;The script core.&quot;&quot;&quot;</span> <span class="c"># the files needed</span> <span class="n">cfg_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s">&quot;~/.config/awesome&quot;</span><span class="p">)</span> <span class="n">rc_real</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cfg_dir</span><span class="p">,</span> <span class="s">&quot;rc.lua&quot;</span><span class="p">)</span> <span class="n">rc_test</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cfg_dir</span><span class="p">,</span> <span class="s">&quot;rc_test.lua&quot;</span><span class="p">)</span> <span class="n">rc_original</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cfg_dir</span><span class="p">,</span> <span class="s">&quot;rc_original.lua&quot;</span><span class="p">)</span> <span class="n">xpids_tmp</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">gettempdir</span><span class="p">(),</span> <span class="s">&quot;xpids&quot;</span><span class="p">)</span> <span class="n">apids_tmp</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">gettempdir</span><span class="p">(),</span> <span class="s">&quot;apids&quot;</span><span class="p">)</span> <span class="n">log_file</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cfg_dir</span><span class="p">,</span> <span class="s">&quot;awdt.log&quot;</span><span class="p">)</span> <span class="n">args</span> <span class="o">=</span> <span class="n">arguments</span><span class="p">()</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> <span class="c"># get the current screen resolution</span> <span class="n">xdpyinfo</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="s">&quot;xdpyinfo&quot;</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">)</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="n">currres</span> <span class="o">=</span> <span class="n">findall</span><span class="p">(</span><span class="s">&quot;dimensions:\s*(\d+x\d+)\spixels&quot;</span><span class="p">,</span> <span class="n">xdpyinfo</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="c"># set defaults</span> <span class="n">args</span><span class="o">.</span><span class="n">screen</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">screen</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">screen</span> <span class="k">else</span> <span class="n">currres</span> <span class="n">args</span><span class="o">.</span><span class="n">test</span> <span class="o">=</span> <span class="n">rc_test</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">test</span> <span class="k">else</span> <span class="n">rc_original</span> <span class="n">args</span><span class="o">.</span><span class="n">display</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">display</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">display</span> <span class="k">else</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">&quot;new&quot;</span><span class="p">:</span> <span class="n">copy</span><span class="p">(</span><span class="n">rc_real</span><span class="p">,</span> <span class="n">rc_test</span><span class="p">)</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">&quot;check&quot;</span><span class="p">:</span> <span class="n">check</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="s">&quot;awesome -c {0} -k&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rc_test</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">STDOUT</span><span class="p">)</span> <span class="n">check_out</span> <span class="o">=</span> <span class="n">check</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span> <span class="n">Popen</span><span class="p">([</span><span class="s">&quot;notify-send&quot;</span><span class="p">,</span> <span class="s">&quot;Lua sintax chek:&quot;</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">check_out</span><span class="p">)])</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">&quot;start&quot;</span><span class="p">:</span> <span class="c"># clean log in each debug session</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">apids_tmp</span><span class="p">):</span> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">log_file</span><span class="p">):</span> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">log_file</span><span class="p">)</span> <span class="n">log</span> <span class="o">=</span> <span class="n">Logger</span><span class="p">()</span> <span class="n">log</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">log_file</span> <span class="n">log</span><span class="o">.</span><span class="n">header</span><span class="p">(</span><span class="s">&quot;https://github.com/joedicastro/dotfiles&quot;</span><span class="p">,</span> <span class="s">&quot;This is a log from an Awesome wm&#39;s debug session&quot;</span><span class="p">)</span> <span class="n">log</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="s">&quot;Start time&quot;</span><span class="p">)</span> <span class="n">x_cmd</span> <span class="o">=</span> <span class="s">&quot;Xephyr -ac -br -noreset -screen {0} :{1}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">screen</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">display</span><span class="p">)</span> <span class="n">aw_cmd</span> <span class="o">=</span> <span class="s">&quot;awesome -c {0}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">test</span><span class="p">)</span> <span class="n">xserver</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="n">x_cmd</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">STDOUT</span><span class="p">)</span> <span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="n">os</span><span class="o">.</span><span class="n">putenv</span><span class="p">(</span><span class="s">&quot;DISPLAY&quot;</span><span class="p">,</span> <span class="s">&quot;:{0}.0&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">display</span><span class="p">))</span> <span class="n">awesome</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="n">aw_cmd</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">STDOUT</span><span class="p">)</span> <span class="c"># save the process PIDs for kill them properly later. This way, no</span> <span class="c"># matter how many awesome sessions do you start, all of them will be</span> <span class="c"># reported to the log file. Also, awesome PIDs are used to restart each</span> <span class="c"># one when is required</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">xpids_tmp</span><span class="p">,</span> <span class="s">&#39;a+&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">xpids</span><span class="p">:</span> <span class="n">xpids</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">xserver</span><span class="o">.</span><span class="n">pid</span><span class="p">)</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="p">)</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">apids_tmp</span><span class="p">,</span> <span class="s">&#39;a+&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">apids</span><span class="p">:</span> <span class="n">apids</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">awesome</span><span class="o">.</span><span class="n">pid</span><span class="p">)</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="p">)</span> <span class="n">log</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">&quot;Parameters&quot;</span><span class="p">,</span> <span class="p">[</span><span class="s">&quot;Screen resolution: {0}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">screen</span><span class="p">),</span> <span class="s">&quot;Display: {0}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">display</span><span class="p">),</span> <span class="s">&quot;Configuration file: {0}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">test</span><span class="p">)])</span> <span class="n">log</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">&quot;Xephyr output&quot;</span><span class="p">,</span> <span class="n">xserver</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">readlines</span><span class="p">())</span> <span class="n">log</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">&quot;Awesome output&quot;</span><span class="p">,</span> <span class="n">awesome</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">readlines</span><span class="p">())</span> <span class="n">log</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="s">&quot;End time&quot;</span><span class="p">)</span> <span class="n">log</span><span class="o">.</span><span class="n">free</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)</span> <span class="n">log</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">&quot;restart&quot;</span><span class="p">:</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">apids_tmp</span><span class="p">,</span> <span class="s">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">apids</span><span class="p">:</span> <span class="k">for</span> <span class="n">pid</span> <span class="ow">in</span> <span class="n">apids</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span> <span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">pid</span><span class="p">),</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">&quot;stop&quot;</span><span class="p">:</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">xpids_tmp</span><span class="p">,</span> <span class="s">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">xpids</span><span class="p">:</span> <span class="k">for</span> <span class="n">pid</span> <span class="ow">in</span> <span class="n">xpids</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span> <span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">pid</span><span class="p">),</span> <span class="mi">9</span><span class="p">)</span> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">xpids_tmp</span><span class="p">)</span> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">apids_tmp</span><span class="p">)</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span> <span class="n">check_execs</span><span class="p">(</span><span class="s">&quot;Xephyr&quot;</span><span class="p">,</span> <span class="s">&quot;awesome&quot;</span><span class="p">)</span> <span class="n">main</span><span class="p">()</span> <span class="c">#==============================================================================</span> <span class="c"># Changelog:</span> <span class="c">#==============================================================================</span> <span class="c">#</span> <span class="c"># 0.5:</span> <span class="c">#</span> <span class="c"># * New log file per debug session</span> <span class="c"># * Improve argparse help</span> <span class="c"># * Better comments</span> <span class="c">#</span> <span class="c"># 0.4:</span> <span class="c">#</span> <span class="c"># * remove debug prints</span> <span class="c"># * clean code</span> <span class="c">#</span> <span class="c"># 0.3:</span> <span class="c">#</span> <span class="c"># * implement logging functions</span> <span class="c"># * check for executables</span> <span class="c">#</span> <span class="c"># 0.2:</span> <span class="c">#</span> <span class="c"># * argparse instead of sys.argv</span> <span class="c"># * create a new rc_test.lua file from original</span> <span class="c"># * restart the awesome session</span> <span class="c">#</span> <span class="c"># 0.1:</span> <span class="c">#</span> <span class="c"># * First attempt</span> <span class="c">#</span> <span class="c">#==============================================================================</span> </pre></div>joe di castroThu, 07 Jun 2012 00:00:00 +0200http://joedicastro.com/productividad-en-el-escritorio-linux-awesome.htmllinuxarchtilingtwmproductividadawesomegnomeluapython