TERMINAL Ultra Rápida y OLVIDATE de los alias

Vistas: 1
0:00 / 0:00
TERMINAL Ultra Rápida y OLVIDATE de los alias

Llevo semanas, meses diría yo, metido de lleno en un par de aplicaciones que tienen su parte de backend y su parte de frontend. El backend está escrito en Rust con Axum y el frontend en TypeScript con React, y ese detalle, que parece anecdótico, es justo el que quiero que te quedes: tener un pie a cada lado de la pila significa que la terminal se convierte en mi sitio de trabajo principal. Y no solo se trata de programar, ni mucho menos. En un día normal muevo ficheros de un sitio a otro, los renombro en lote, construyo imágenes de Docker, extraigo el audio de un vídeo con yt-dlp o convierto un montón de cosas que ni te imaginas. Al final, la terminal es donde caen todas esas tareas.

El problema es que de todos esos comandos que ejecuto hay dos clases. Una, los que tengo tan interiorizados que los tecleo sin pensar, como respirar. Y dos, esos otros que se me atragantan, que son un pelín más largos, un pelín más complicados, y que acordarse de ellos se vuelve casi una tarea titánica. Y lo curioso es que muchas veces el problema no es no acordarse del comando, sino que el comando es largo y podrías ejecutarlo de una forma mucho más productiva. Piensa en el clásico docker compose up -d --force-recreate. Lo escribes una vez y ya te entra sudor frío al pensar en repetirlo.

Todo esto se puede resolver en cualquier shell que uses. Lo puedes hacer en bash, lo puedes hacer en zsh o lo puedes hacer en fish. En mi caso concreto uso Fish como shell por defecto desde hace un par de años, después de una migración paulatina: entré por bash con Oh My Zsh, pasé luego a zsh también con Oh My Zsh, y terminé aterrizando en Fish, donde ya no uso ningún tipo de framework. Está ahí, directo, a pelo. Lo que sí he ido haciendo es crearme mis pequeñas abreviaturas y mis pequeñas funciones para facilitarme la vida.

Así que de eso va el episodio, de cómo agilizar y acelerar tu terminal —por ejemplo Kitty, que para mí es la terminal más rápida a este lado de Linux— usando precisamente esa clase de abreviaturas y funciones que te voy a contar a partir de ahora. Vamos directos al turrón.

Mucho tiempo en la terminal, y no todo es programar

Conviene que entiendas primero por qué paso tanto tiempo delante del prompt, porque no es capricho. Cuando tienes un backend en Rust y un frontend en React en el mismo proyecto, el ciclo de trabajo es constante: compilas, arrancas servicios, miras logs, vuelves a compilar, levantas los contenedores otra vez. Si a eso le sumas que también genero contenido, grabo, edito y preparo material, entonces me encuentro extrayendo audio, procesando vídeo y moviendo ficheros de un directorio a otro todo el rato.

Y ahí está la clave: aunque no lo creas, muchísimas de las operaciones que hago las hago directamente en la terminal porque me resulta más cómodo que coger el ratón y buscar en un menú. No es nostalgia ni postureo de viejo Unix. Es que para ciertas tareas encadenadas, la línea de comandos es simplemente más rápida, y encima es repetible. Escribes una vez, ejecutas muchas.

El problema aparece cuando esos comandos se alargan. Un docker compose up -d --force-recreate tiene veinte caracteres de más y ninguna gana de memorizarlo. Un yt-dlp con tres o cuatro banderas para quedarte solo con el audio y que ignore los errores es directamente un trabalenguas. Y un flujo de Git que combine un add, un commit con mensaje generado por un modelo de lenguaje y un merge sin fast-forward es un poema que nadie debería tener que recitar cada mañana.

La buena noticia es que Fish trae dos mecanismos estupendos para domar todo esto: las abreviaturas y las funciones. Y no son lo mismo, ni mucho menos. Entender la diferencia es la mitad del episodio.

De bash a zsh y de ahí a Fish, sin framework

Te hago un poco de historia personal porque creo que ayuda a entender por qué me quedo con Fish. Empecé, como casi todo el mundo, en bash. Ahí tenía mis tradicionales alias definidos en el .bashrc y vivía razonablemente feliz. En algún momento me pasé a zsh apoyándome en Oh My Zsh, ese framework que trae tema, plugins y mil comodidades de serie. Ahí volví a definir alias, esta vez en el .zshrc, y también estaba cómodo.

Pero el salto definitivo fue a Fish. Y lo hice, además, dejando atrás los frameworks. Mi configuración actual no depende de ninguna capa por encima; es Fish pelado y yo añadiéndole lo que necesito. Eso sí, he ido construyendo a mano mi propio arsenal: abreviaturas para lo corto y funciones para lo que tiene miga. Esa combinación es la que hace que la terminal vuele.

Un detalle de transparencia, porque me gusta decir las cosas como son: no soy ningún gurú que se haya leído el manual de pe a pa. Muchas de estas cosas las he ido descubriendo a base de usarlas, de probar, de equivocarme y de rehacer. Y algunas las sigo ajustando sobre la marcha, como te contaré a lo largo del episodio. Así que si algo te chirría, perfecto, es señal de que estás pensando conmigo.

Alias y abreviaturas no son lo mismo

Aquí llega el meollo del asunto, y quiero pararme porque es donde la mayoría de la gente mete la pata. Venimos de bash y de zsh, donde estamos acostumbrados al alias. Y un alias, al final, es simplemente un nombre que le ponemos a un comando con todas sus opciones. Por ejemplo, tú tienes el comando docker compose up -d --force-recreate y le pones el alias dcu. Escribes dcu y el shell sustituye, punto. Nada más.

En Fish, en cambio, no hablamos exactamente de alias. Hablamos de abreviaturas, y funcionan de otra manera. Una abreviatura no sustituye el texto silenciosamente cuando pulsas Enter, sino que expande el comando en el mismo momento en que tú pulsas la barra espaciadora después de escribir el detonante. Y esa diferencia, que parece un matiz de nada, lo cambia todo.

Fíjate en el ejemplo. Si yo definí la abreviatura dcu para docker compose up -d --force-recreate, cuando escribo dcu y pulso espacio, lo que aparece escrito en mi línea de comandos es el comando completo, ya desarrollado. No se ejecuta solo, se escribe. Y a partir de ahí yo puedo seguir trabajando sobre ese comando, editarlo, quitarle una bandera, cambiarle el servicio, lo que me dé la gana.

Un alias es una caja cerrada: escribes la etiqueta y te traga el comando con todo lo que lleva dentro. Una abreviatura es una puerta abierta: te despliega el texto y te deja seguir escribiendo. Esa diferencia es la razón por la que ya casi no uso alias.

¿Y por qué es tan importante poder seguir editando? Pues imagina el caso concreto. Tal vez no quieres hacer un force-recreate de todos los contenedores que forman tu docker-compose, sino solo de uno. Con un alias tendrías que hacer otro alias distinto, o renunciar. Con una abreviatura te basta con expandir dcu y, acto seguido, escribir al final el nombre del servicio que te interesa. El comando ya está ahí, tú solo lo retocas. Ahí está la ventaja, y es considerable.

Cómo se crea una abreviatura con abbr

Crear una abreviatura en Fish es tan sencillo que casi da risa. El comando se llama abbr y su sintaxis básica es la que ves aquí: le dices el detonante y el comando al que debe expandir.

abbr --add gst 'git status'

Con esa línea ya tengo mi abreviatura. A partir de este momento, cuando escribo gst y le doy al espacio, Fish me lo completa con git status. Como detrás de git status no va nada más, tampoco hace falta, pero el mecanismo es exactamente el mismo que con el ejemplo de Docker. Es una manera comodísima de reemplazar los alias clásicos de bash y de zsh por algo que, para mí, es bastante más práctico.

Fíjate en el --add y no te pierdas, porque abbr tiene varios subcomandos y merece la pena conocerlos. Con --show puedes listar todas las abreviaturas que tienes configuradas, que en mi caso ya son unas cuantas.

abbr --show

Y si en algún momento quieres deshacerte de una, no la borras a mano del fichero, la eliminas con --erase.

abbr --erase dcu

También existe --rename para cambiarle el nombre a una abreviatura sin tener que volver a escribir el comando entero. Y hay una opción que a mí me parece especialmente útil, que es --position. Por defecto, Fish expande la abreviatura solo cuando está al principio del comando, que es lo lógico para un detonante tipo gst. Pero con --position anywhere le dices que expanda esa abreviatura aparezca donde aparezca, incluso a mitad de una tubería.

abbr --add --position anywhere dl 'yt-dlp --ignore-errors'

Eso te abre la puerta a encadenar comandos con abreviaturas dentro de una pipeline, que ya es nivel avanzado. Para el día a día, con las de posición normal vas sobrado.

Abreviaturas para Docker, Kitty, Podman y ese churro de yt-dlp

Y ahora te enseño el tipo de abreviaturas que tengo yo montadas, para que veas el abanico. No son solo para Git. Tengo abreviaturas para Kitty, mi terminal, para Docker, para Podman, para skim, ese buscador difuso que me encanta, y para un largo etcétera. Lo bonito es que cada una encapsula un comando largo que, de otro modo, tendría que recordar palabra por palabra.

El ejemplo que más me gusta contar, porque ilustra de golpe el problema y la solución, es el de la descarga de audio con yt-dlp. Fíjate en el churro que hay que escribir a mano si quieres descargar solo el audio de un vídeo y que además ignore los errores para no morir en el primer fallo:

yt-dlp --ignore-errors --format bestaudio --extract-audio URL

Pues eso mismo lo tengo reducido a tres letras, dlm, con una abreviatura como esta:

abbr --add dlm 'yt-dlp --ignore-errors --format bestaudio --extract-audio'

Y aquí está la gracia que contaba antes: no es que dlm ejecute el churro sin que yo lo vea. Es que cuando pulso espacio, el churro entero aparece escrito en mi línea de comandos. Así que, si un vídeo concreto necesita otra bandera, o quiero cambiar el formato de salida, o quiero apuntar a otro sitio, sigo escribiendo sobre el comando completo. No he perdido nada por el camino, solo he ganado tiempo.

Y ya que estamos con la lista, te dejo por aquí abajo un puñado de las abreviaturas típicas que puede tener cualquiera, para que te hagas una idea y copies las que te sirvan:

  • gst para git status
  • gco para git checkout
  • dcu para docker compose up -d --force-recreate
  • dcd para docker compose down
  • dcl para docker compose logs -f
  • dlm para yt-dlp --ignore-errors --format bestaudio --extract-audio
  • sk para lanzar skim y buscar ficheros a toda velocidad

Ese es el patrón. Comandos largos, feos y propensos al error, reducidos a dos o tres letras que el cerebro reconoce en automático pero que se pueden seguir editando después de expandirlos.

Cuando la abreviatura se queda corta: las funciones

Las abreviaturas están muy bien, pero solo sirven para sustituir un texto fijo por otro. ¿Qué pasa cuando lo que quieres es una lógica? ¿Cuando necesitas algo que haga varias cosas seguidas, o que decida en función de una condición? Ahí las abreviaturas se quedan cortas y entran las funciones, que son la otra pata de Fish.

En mi configuración tengo una serie de cosas que yo llamo alias por costumbre, pero que en realidad son funciones. No son tan simples como un alias; llevan detrás un poquito más de trabajo. Un ejemplo tonto pero muy real: tengo una función que primero se va a mi directorio de notas y luego me abre la nota maestra que tengo ahí. Que, dando un detalle de transparencia, mientras te estoy hablando me acabo de dar cuenta de que el nombre del fichero de la nota maestra no es el que yo creía; es index.md. Tonterías de la vida, pero ahí lo dejo.

Luego las hay cada vez más complejas, funciones que ejecutan operaciones distintas según las condiciones que les hayas puesto, o funciones que encadenan varios pasos. Y aquí es donde Fish brilla de verdad, porque te permite montar flujos completos sin salir del shell.

Una de las operaciones que hago más a menudo es crear los commits de Git. Y aquí he ido un paso más allá. En lugar de tirar del típico git commit -am en el que piensas tú el mensaje, lo que hago es una función que coge el git diff, se lo pasa a un modelo de lenguaje, y le pide que analice los cambios y genere el mensaje de commit a partir de ese contenido, empezando por un gitmoji como manda la convención. Es decir: yo no escribo el mensaje, lo redacta el modelo, y mi función se encarga de todo el encadenado.

Otras funciones que tengo por ahí hacen cosas como un git merge en condiciones, con las banderas que a mí me gustan para no editar el mensaje y forzar un merge sin fast-forward:

git merge --no-edit --no-ff development

Y alguna otra que lanza el CLI de Gemini en modo interactivo. Como ves, cuando la tarea tiene pasos, condiciones o llamadas externas, la abreviatura ya no basta y una función es la respuesta. Y todas estas funciones, evidentemente, las tengo publicadas. Al final del episodio te dejo un enlace a mis dotfiles para que te las puedas llevar enteras y aprovecharlas.

Crear y guardar una función paso a paso

Vamos a lo práctico, porque crear una función en Fish es casi de juguete. Imagínate que quieres una función que simplemente diga hola. Abres la línea de comandos y escribes esto, todo de una vez:

function hola
    echo hola
end

Fíjate en la estructura: la palabra function, el nombre hola, el cuerpo con el echo hola, y un end para cerrar. Con eso ya tienes la función definida en la sesión actual. Si ahora ejecutas hola, te responde con su saludo. Listo.

hola

Pero claro, esa función vive solo en la memoria de esta sesión. Si cierras la ventana, se va. Para que no se pierda, tienes que guardarla, y para eso existe un comando con un nombre precioso: funcsave. Se llama así, con el nombre de la función, y ya está.

funcsave hola

Lo que hace funcsave es escribir la función en un fichero dentro del directorio functions de tu configuración de Fish. Así que ahí aparece una nueva función llamada hola.fish. Si te vas a ese directorio y la miras con un cat, verás el contenido tal cual lo habías definido.

cat ~/.config/fish/functions/hola.fish

Y ojo, porque ese detalle del directorio functions es importante: Fish carga automáticamente todas las funciones que encuentra en él al arrancar, así que cualquier función guardada con funcsave está disponible en todas tus sesiones sin que tengas que hacer nada más. Ese es el mecanismo, y es de una sencillez que asusta. En mi caso, cuando estaba probando esto, la borré después para no dejar basura en la configuración, pero tú ya ves lo fácil que es tener una función nueva funcionando y persistida.

Y si en algún momento quieres editar una función existente sin salir del shell, hay un atajo cómodo: funced hola te abre la función en tu editor para que la retoques. Al guardar, vuelves a estar listo. Para funciones gordas, siempre puedes abrir el fichero del directorio functions con tu editor favorito de la casa, y ya está.

Completados, variables y el resto de la configuración

Más allá de las abreviaturas y las funciones, en mi configuración de Fish tengo otra capa que también me facilita mucho la vida: los autocompletados. Fish los genera y los carga, y para ciertas herramientas ese autocompletado es oro puro. En mi caso tengo completados configurados para varias utilidades que uso a diario:

  • Starship, el prompt que me muestra el estado de Git y demás información útil
  • Atuin, que sincroniza y hace buscable todo mi historial de comandos
  • Zoxide, el sustituto inteligente de cd que aprende por dónde ando
  • direnv, que me carga variables de entorno según el directorio en el que esté
  • uv, ese gestor de paquetes de Python que se ha convertido en imprescindible

Todo eso vive en mi config.fish, junto con variables propias que siempre es cómodo tener a mano, como las que apuntan a directorios de trabajo o a cachés de herramientas. También tengo ahí algún ajuste directo relacionado con el directorio de pnpm, de esas personalizaciones que haces una vez y agradeces cada día. No son el corazón del episodio, pero forman parte de ese mismo objetivo: que la terminal trabaje para ti y no al revés.

Y como te decía en la introducción, la gran ventaja de todo este montaje está en las abreviaturas. El concepto de alias y el de funciones ya existe en bash y en zsh, así que no es una novedad radical. Lo que sí es una novedad, y por eso me quedo con Fish, es esa posibilidad de expandir un dcu y quedarme con el comando completo delante para retocarlo según mi criterio y mis necesidades del momento. Esa plasticidad no la tienes en los otros shells.

Por qué la expansión gana a la sustitución

Quiero detenerme un momento en la filosofía, porque creo que es lo que hace que este truco merezca la pena. Cuando usas alias, tu cabeza tiene que recordar dos catálogos: el de los comandos reales y el de los alias que has inventado. Y si un alias no te sirve exactamente para lo que necesitas en ese instante, estás perdido, porque no puedes editar dentro de él. O haces un alias nuevo, o escribes el comando largo otra vez.

Con las abreviaturas de Fish, en cambio, el catálogo mental es uno solo: recuerdas el detonante, lo expandes, y a partir de ahí vuelves a estar en terreno de comandos reales. Es como tener a mano una plantilla que se materializa en el prompt y que puedes modificar letra a letra. La potencia no está en escribir menos, está en no quedarte nunca encerrado en una abreviatura que no encaja.

Una herramienta buena no es la que te escribe el comando por ti, sino la que te lo pone delante a medio escribir para que tú termines de decidir. Eso es exactamente lo que hacen las abreviaturas de Fish.

Y si a eso le sumas las funciones, que te dejan empaquetar lógica de varios pasos, tienes un sistema en el que lo simple es simple y lo complejo sigue siendo posible. No hay que elegir entre rapidez y control: con Fish tienes las dos, siempre que sepas cuándo usar una abreviatura y cuándo una función.

Kitty, o por qué la terminal más rápida merece un shell a su altura

Permíteme una pequeña digresión, porque he mencionado Kitty un par de veces y no quiero dejarlo pasar. Para mí es la terminal más rápida a este lado de Linux, y eso, cuando pasas ocho horas al día dentro de ella, se nota más de lo que parece. Kitty está acelerada por GPU, así que el renderizado de texto y el desplazamiento son increíblemente fluidos. Tener una terminal así y luego perder el tiempo escribiendo comandos larguísimos a mano es un desperdicio.

La gracia es que la velocidad de una terminal no depende solo de lo rápido que pinte las letras, sino de lo rápido que tú consigues llegar al comando. Y ahí las abreviaturas y las funciones marcan la diferencia. De nada sirve un motor potentísimo si tardas quince segundos en teclear el comando de levantar los contenedores. Es la combinación de las dos cosas, la terminal rápida y el shell bien afinado, lo que de verdad te hace volar.

Conclusiones

Hagamos balance del episodio, que para eso estamos. Hemos visto que Fish ofrece dos mecanismos complementarios: las abreviaturas, que expanden texto fijo y te dejan seguir editando, y las funciones, que te permiten empaquetar lógica de varios pasos, condiciones y llamadas a herramientas externas. Con las abreviaturas cubres los comandos largos de Docker, de Git, de yt-dlp o de lo que se te ocurra. Con las funciones conviertes en un solo nombre tareas que antes eran tres o cuatro comandos encadenados.

Me llevo tres conclusiones de todo esto, y me las apunto para no olvidarlas. La primera, que la diferencia entre alias y abreviatura no es un tecnicismo, es una ventaja práctica real: poder expandir un dcu y retocarlo vale más que cualquier atajo que se ejecute a ciegas. La segunda, que las funciones son el siguiente escalón y merecen la pena en cuanto la tarea deja de ser un simple comando, aunque solo sea para que un modelo de lenguaje te escriba el mensaje de commit con su gitmoji. Y la tercera, la que más me importa, que este arsenal se apoya en haber renunciado a los frameworks y haber construido la configuración a mano, pieza a pieza, entendiendo qué hace cada cosa.

Si algo de lo que te he contado te ha picado la curiosidad, no hace falta que rehagas tu vida de golpe. Empieza por lo tonto: define un par de abreviaturas con abbr --add para los comandos que más te fastidian, y comprueba lo que se siente al expandir y editar. Luego, cuando te quedes corto, pásate a las funciones y guarda la primera con funcsave. Y si quieres atajar de verdad, échale un ojo a mis dotfiles, que te dejo enlazados abajo, y roba lo que te sirva.

Y la semana que viene, si todo va según lo previsto, seguimos dándole vueltas a la terminal y a Fish, que todavía me quedan trucos en la recámara. Así que ya sabes: si puedes, déjame una valoración en Spotify o en YouTube, un me gusta o un comentario, que me vendría fantástico para dar a conocer este proyecto. Y recuerda que la vida son dos días y uno ya ha pasado, así que disfrútala como si no hubiera mañana, y si puede ser con Linux —y con Fish—, mejor que mejor. Nos escuchamos el próximo jueves. 🐧


Más información

Deja una respuesta