joe di castrohttp://joedicastro.com2012-07-09T22:42:00+02:00Productividad & Linux: tmux2012-07-09T22:42:00+02:00joe di castrohttp://joedicastro.com/productividad-linux-tmux.html<p><a href="http://tmux.sourceforge.net/">Tmux</a> es un <strong>multiplexor</strong> de terminales. Es una herramienta básica,
casi diría imprescindible, para los que trabajamos habitualmente con la consola
de Linux. El termino multiplexor es empleado en electrónica para designar un
dispositivo que combina múltiples entradas en una única salida. Esto es lo que
hace tmux, combinar varios terminales en una sola ventana, de forma que podamos
organizarlos de la forma más eficiente posible. Si lo primero que te viene a la
cabeza son terminales con múltiples pestañas o paneles como <a href="https://launchpad.net/terminator/">Terminator</a>,
olvídalo, tmux es un concepto diferente y más potente.</p>
<p>La gran diferencia es que tmux está basado en un modelo cliente-servidor. El
servidor puede albergar múltiples sesiones y cada instancia (ventana de
terminal) puede estar asociado con una o más sesiones. Se pueden abrir, cerrar
sesiones, moverse entre ellas, renombrarlas. Una sesión puede ser compartida por
varios clientes, lo que es empleado por ejemplo para sesiones de <a href="https://es.wikipedia.org/wiki/Programaci%C3%B3n_en_pareja">pair
programming</a>. Si se cierra un cliente, la sesión sigue corriendo en segundo
plano, pudiéndose volver a ella cuando se desee. A su vez cada sesión puede
albergar varias ventanas (el equivalente a las pestañas en otros terminales) y
cada ventana puede subdividirse en varios paneles.</p>
<p>Es una aplicación muy flexible y con muchas posibilidades, no voy a entrar en
detalle en todas ellas porque me extendería demasiado. Es totalmente controlable
desde el teclado, lo que lo hace muy ágil en su manejo. Yo lo uso a diario y es
muy raro que trabaje en un terminal sin hacerlo dentro de una sesión de tmux.
Tmux te permite tener perfectamente organizadas todas esas ventanas de terminal
que los SysAdmins manejamos y que de otra manera se convierten en un caos. Antes
de emplear tmux empleaba screen y terminator dependiendo de la tarea y el equipo
a emplear, pero tmux me da lo mejor de ambas aplicaciones y aún más. Y si además
los combinamos con un terminal ligero, superrápido y con soporte para UTF-8 y
256 colores como <code>rxvt-unicode</code> tenemos un entorno ideal para cualquier tarea
que desarrollemos en la consola.</p>
<h2 id="caracter+sticas">Características</h2>
<p>Este es un resumen de las características de tmux:</p>
<ul>
<li>Modelo cliente/servidor</li>
<li>Linea de comandos potente, consistente y fácilmente programable</li>
<li>Totalmente controlable desde el teclado, aunque tiene un soporte básico de
ratón</li>
<li>División de las ventanas en múltiples paneles horizontales y/o verticales</li>
<li>Los paneles pueden ser movidos, redimensionados y pueden reorganizarse en
esquemas predefinidos</li>
<li>Sincronizar paneles. Introducir el mismo texto en varios paneles a la vez</li>
<li>Soporte para UTF-8 y 256 colores</li>
<li>Copiar y pegar con múltiples bufferes</li>
<li>Menús interactivos para seleccionar ventanas, sesiones o clientes</li>
<li>Bloqueo de terminal manualmente o por cuenta atrás</li>
<li>Moverse a una ventana mediante una búsqueda del texto existente dentro de ella</li>
<li>Barra de estado por defecto y muy personalizable</li>
<li>Fichero de configuración basado en texto plano</li>
<li>Soporte para combinaciones de teclas basadas en Vim o Emacs</li>
<li>Documentación bastante completa</li>
</ul>
<p>En esta imagen se puede ver la configuración por defecto de tmux, a primera
vista no se puede apreciar toda la potencia que se esconde detrás de esta
aplicación.</p>
<p style="text-align:center;"><img src="pictures/tmux.png" width="700"
height="481" alt="tmux" /></p>
<h2 id="alternativas">Alternativas</h2>
<p>La alternativa más directa es el veterano <a href="http://es.wikipedia.org/wiki/GNU_Screen">GNU Screen</a> en el que se
inspira tmux. Sigue siendo una aplicación muy utilizada, pero en mi opinión tmux
la ha superado hace tiempo. Otra alternativa es <a href="https://launchpad.net/byobu">Byobu</a> que no es más que
un frontend para tmux o screen que los hace más amigables para los usuarios
menos avanzados.</p>
<h2 id="scripts">Scripts</h2>
<p>Una de las posibilidades más potentes que nos permite tmux es la de la creación
de scripts para iniciar una o varias sesiones con configuraciones
predeterminadas. De esto modo se pueden crear sesiones predefinidas para
desarrollo, web, ssh, etc. Pero crear scripts en tmux es una tarea bastante
árida, por lo que se han desarrollado algunas utilidades de terceros para
realizar esto de forma más cómoda y agradable:</p>
<ul>
<li>
<p><a href="https://github.com/aziz/tmuxinator">Tmuxinator</a> es una utilidad escrita en <a href="http://www.ruby-lang.org/es/">Ruby</a> para crear y
modificar sesiones de Tmux, permitiendo crear sesiones complejas de una forma
muy sencilla ya que emplea ficheros de configuración en formato <a href="https://es.wikipedia.org/wiki/YAML">YAML</a>
para ello.</p>
</li>
<li>
<p><a href="https://github.com/remiprev/teamocil">teamocil</a> es una utilidad que nos permite crear esquemas de ventanas y
paneles predefinidos con facilidad empleando el formato YAML. También está
escrito en Ruby, en cuya comunidad de desarrolladores tmux está muy implantado.</p>
</li>
</ul>
<p>Aquí se puede ver una ventana de tmux con mi configuración en la que se muestra
la sesión <code>www</code> donde tengo agrupadas varias ventanas con aplicaciones
relacionadas con la web. Se puede ver como estoy en la ventana 2 de 4 y como he
personalizado la barra de estado:</p>
<p style="text-align:center;"><img src="pictures/tmux_www.png" width="700"
height="429" alt="tmux con una sesión para internet" /></p>
<h2 id="mi_configuraci+n">Mi configuración</h2>
<p>Mi configuración de tmux puede encontrarse en mi repositorio <em>dotfiles</em> en
<a href="http://github.com/joedicastro/dotfiles">GitHub</a>. Mi configuración se apoya en la muchos otros usuarios que me han
aportado ideas y en buena parte gracias a la lectura del libro <a href="http://pragprog.com/book/bhtmux/tmux">tmux: Productive
Mouse-Free Development</a> de Brian P. Hogan.</p>
<p>En esta otra imagen se puede ver una sesión de desarrollo con tmux, donde tengo
abiertos tres paneles con tres aplicaciones (de izquierda a derecha y de arriba
a abajo): vim, <a href="http://ipython.org/">ipython </a> y <a href="http://jonas.nitro.dk/tig/">tig</a>. Así mismo hay una ventana adicional
donde tengo un shell bash. Pulsar sobre ella para ver a tamaño completo.</p>
<p style="text-align:center;"><a href="pictures/tmux_develop_full.png" alt="tmux
como entorno de desarrollo" title="tmux como entorno de desarrollo"><img
src="pictures/tmux_develop.png" width="700" height="430" alt="tmux como entorno
de desarrollo" /></a></p>
<p>Voy a destacar algunos puntos reseñables de mi configuración. Lo primero que
configuro es la combinación de teclas conocida como <code>Prefix</code> que es la
combinación que precede a los atajos de teclado de tmux. Esto se hace de este
modo para no interferir con los atajos de teclado de las aplicaciones que
ejecutemos dentro de tmux. El prefijo por defecto de tmux es <strong><code>Ctrl + b</code></strong>,
pero para los que estábamos acostumbrados a <strong>screen</strong> la combinación <strong><code>Ctrl +
a</code></strong> es más idónea. Y también porque es más cómodo de teclear, sobre todo si
como en mi caso, tienes mapeada una tecla de <strong><code>Ctrl</code></strong> adicional en lugar de
<strong><code>Bloq Mays</code></strong>. Bueno, en realidad uso la tecla <strong><code>Bloq Mays</code></strong> también como
tecla <strong><code>Esc</code></strong> cuando no es pulsada en combinación con otras, gracias a la
maravillosa pequeña utilidad <a href="https://github.com/alols/xcape">xcape</a>, muy útil para los usuarios de Vim.</p>
<div class="codehilite"><pre><span class="gp">#</span> Use C-a instead of C-b as the prefix
<span class="go">set -g prefix C-a</span>
<span class="go">unbind-key C-b</span>
<span class="go">bind-key C-a send-prefix</span>
</pre></div>
<p>Para emplear 256 colores y indicarle que interprete de shell emplear, se lo
indico mediante las siguientes lineas</p>
<div class="codehilite"><pre><span class="gp">#</span> <span class="nb">set </span>256 colors
<span class="go">set -g default-terminal "screen-256color"</span>
<span class="gp">#</span> <span class="nb">set </span>default shell
<span class="go">set -g default-command "exec /bin/bash"</span>
</pre></div>
<p>También cambio el retraso inicial después de pulsado el prefijo, para que no de
problemas con otras aplicaciones como vim y para mejorar su respuesta.</p>
<div class="codehilite"><pre><span class="gp">#</span> be more responsive, changing the default delay
<span class="go">set -sg escape-time 1</span>
</pre></div>
<p>Para hacer más fácil el cambio entre ventanas y paneles a través de los números
de los mismos, lo que hago es que empiecen a contar desde 1 y no desde 0</p>
<div class="codehilite"><pre><span class="gp">#</span> Start numbering at 1
<span class="go">set -g base-index 1</span>
<span class="go">setw -g pane-base-index 1</span>
</pre></div>
<p>Esto es muy útil para comprobar cambios en la configuración sobre la marcha sin
necesidad de cerrar las sesiones. Este comando me permite recargar la
configuración en vivo con la combinación <strong><code>prefix r</code></strong></p>
<div class="codehilite"><pre><span class="gp">#</span> force a reload of the config file
<span class="go">unbind r</span>
<span class="go">bind r source-file ~/.tmux.conf \; display "Reloaded!"</span>
</pre></div>
<p>Para moverme entre los paneles y cambiar su tamaño empleo las teclas típicas de
movimiento de vim para no tener que abandonar los dedos de la fila principal del
teclado.</p>
<div class="codehilite"><pre><span class="gp">#</span> moving between panes
<span class="go">bind h select-pane -L</span>
<span class="go">bind j select-pane -D</span>
<span class="go">bind k select-pane -U</span>
<span class="go">bind l select-pane -R</span>
<span class="gp">#</span> Quick pane selection
<span class="go">bind -r C-h select-window -t :-</span>
<span class="go">bind -r C-l select-window -t :+</span>
<span class="gp">#</span> Pane resizing
<span class="go">bind -r H resize-pane -L 5</span>
<span class="go">bind -r J resize-pane -D 5</span>
<span class="go">bind -r K resize-pane -U 5</span>
<span class="go">bind -r L resize-pane -R 5</span>
</pre></div>
<p>La barra de estado que empleo está inspirada en el plugin de Vim,
<a href="https://github.com/Lokaltog/vim-powerline/">vim-powerline</a>, que le otorga una estética más lograda que la original. Es
necesario emplear para ello una fuente monoespaciada parcheada especialmente,
con los símbolos que emplea vim-powerline. Se pueden encontrar varias en su
<a href="https://github.com/Lokaltog/vim-powerline/wiki/Patched-fonts">wiki</a>. Yo empleo mi fuente preferida que es Dejavu Sans Mono.</p>
<div class="codehilite"><pre><span class="gp">#</span> Custom status bar
<span class="gp">#</span> Powerline symbols: ⮂ ⮃ ⮀ ⮁ ⭤
<span class="go">set -g status-utf8 on</span>
<span class="go">set -g status-left-length 32</span>
<span class="go">set -g status-right-length 150</span>
<span class="go">set -g status-interval 2</span>
<span class="go">set -g status-left '#[fg=colour15,bg=colour238,bold] #S #[fg=colour238,bg=colour234,nobold]⮀'</span>
<span class="go">set -g status-right '#[fg=colour245]⮃ %R ⮃ %d %b #[fg=colour254,bg=colour234,nobold]⮂#[fg=colour16,bg=colour254,bold] #h '</span>
<span class="go">set -g window-status-format "#[fg=white,bg=colour234] #I #W "</span>
<span class="go">set -g window-status-current-format "#[fg=colour234,bg=colour39]⮀#[fg=colour16,bg=colour39,noreverse,bold] #I ⮁ #W #F #[fg=colour39,bg=colour234,nobold]⮀"</span>
</pre></div>
<p>Por último unos atajos de teclado muy útiles que me permiten hacer un zoom
temporal de un panel a ventana completa y luego regresar a la distribución
original de paneles.</p>
<div class="codehilite"><pre><span class="gp">#</span> Maximize and restore a pane
<span class="go">unbind Up</span>
<span class="go">bind Up new-window -d -n tmp \; swap-pane -s tmp.1 \; select-window -t tmp</span>
<span class="go">unbind Down</span>
<span class="go">bind Down last-window \; swap-pane -s tmp.1 \; kill-window -t tmp</span>
</pre></div>