XMonad: el window manager que no sabias que necesitabas (y las 300 extensiones que no sabias que existian)
Que es XMonad
XMonad es un window manager de tiling para X11 escrito en Haskell. Eso significa que en vez de ventanas flotantes que arrastras con el raton (como Windows o macOS), las ventanas se organizan automaticamente en mosaico ocupando toda la pantalla. Sin gaps inutiles, sin ventanas tapandose, sin perder el tiempo moviendo cosas.
Pero XMonad no es como i3 o Sway. XMonad es tu config ES el
window manager. No hay archivos de configuracion: tu xmonad.hs es un programa Haskell que se compila.
Si compila, funciona. Si no compila, te dice exactamente que linea esta
mal. Cero misterio.
Y luego esta xmonad-contrib. 300+ extensiones. Todas incluidas. Sin
instalar nada extra. Solo import y a
funcionar.
Lo que usamos (nuestro xmonad.hs)
Nuestro config tiene 448 lineas y usa 30 modulos. Aqui va lo que tenemos y por que:
7 layouts
Los layouts definen como se organizan las ventanas. Cambias entre
ellos con Mod+Space.
| Layout | Que hace | Cuando usarlo |
|---|---|---|
| ThreeColMid | 3 columnas, master en el centro | Ultrawide (5120x1440). El master ocupa 2/3, perfecto para codigo |
| ResizableTall | 2 columnas, master a la izquierda | El clasico. Codigo a la izquierda, terminal a la derecha |
| MultiCol | Columnas dinamicas | Muchas ventanas, cada una su columna |
| Column | Una sola columna vertical | Para leer documentacion o logs |
| Grid | Cuadricula automatica | Monitoreo: 4-6 terminales iguales |
| Tall | Tiling clasico de XMonad | Cuando quieres simplicidad total |
| Mirror Tall | Tall rotado 90 grados | Apilado horizontal, util en pantallas verticales |
| Full | Pantalla completa sin bordes | Toggle con Mod+f. Para concentrarse en una ventana |
Todos tienen spacingWithEdge 5 (gap de
5px) y smartBorders (sin bordes cuando
solo hay 1 ventana). avoidStruts respeta
el espacio de xmobar.
5 prompts nativos (recien estrenados)
Hemos reemplazado dmenu por XMonad.Prompt. Mismo keybinding (M-p), mejor en todo:
| Keybinding | Prompt | Que hace |
|---|---|---|
M-p |
Shell | Lanza programas del PATH. Fuzzy matching: escribe "fire" y encuentra "firefox" |
M-g |
Window Go | Busca ventanas abiertas por titulo. Te lleva al workspace donde esta |
M-b |
Window Bring | Como Go pero trae la ventana a TU workspace |
M-/ |
Man | Man pages con autocompletion. Escribe "nix" y ves todas las paginas |
M-S-p |
SSH | Lee ~/.ssh/config. Fuzzy match: "vesp" encuentra "vespino-tunnel" |
Todos comparten un tema One Dark con fuzzy matching tipo fzf, historial persistente de 256 entradas sin duplicados, y autocompletion al escribir (sin pulsar Tab).
myXPConfig :: XPConfig
myXPConfig = def
{ font = "xft:Hurmit Nerd Font:size=9:antialias=true"
, bgColor = "#282c34"
, fgColor = "#abb2bf"
, bgHLight = "#61afef"
, fgHLight = "#282c34"
, searchPredicate = fuzzyMatch
, sorter = fuzzySort
, showCompletionOnTab = False
, alwaysHighlight = True
}5 scratchpads
Ventanas flotantes que aparecen y desaparecen con un keybinding. Como los drawers de macOS pero configurables:
| Keybinding | Scratchpad | Tamano | Notas |
|---|---|---|---|
M-a |
Terminal (Alacritty) | 80% pantalla | Para comandos rapidos sin dejar tu layout |
M-e |
Emacs (Doom) | 70% pantalla | Notas, org-mode, edicion rapida |
M-j |
JetBrains Toolbox | 80% pantalla | Lanzar IDEs |
M-v |
Toggle sticky window | - | Ventana visible en TODOS los workspaces |
M-s |
GridSelect | visual | Selector visual de ventanas con cuadricula |
IndependentScreens
Cada pantalla tiene sus propios workspaces 1-9. En aurin con el ultrawide es un monitor, pero cuando conectas un segundo: Mod+3 en monitor A va al workspace 3 del monitor A, Mod+3 en monitor B va al workspace 3 del monitor B. No se pisan.
Lo demas
- EWMH: compatibilidad con paneles, systray, fullscreen de apps
- DynamicLog: envia info a xmobar (workspace actual, titulo de ventana, layout)
- CopyWindow: ventanas sticky (
M-v) que aparecen en todos los workspaces - Keybindings estilo Emacs:
M-p,M-S-q, etc. via EZConfig - Teclas multimedia: volumen, brillo, backlight teclado
- ToggleLayouts:
M-fpara fullscreen instantaneo sin cambiar de layout
El catalogo: 300+ modulos de xmonad-contrib
Aqui viene lo gordo. Todo esto esta instalado y listo para usar con
un import. Dividido por categorias con lo
mas interesante de cada una.
Actions (67 modulos)
Acciones que puedes asignar a keybindings.
Las imprescindibles
| Modulo | Que hace | Usamos? |
|---|---|---|
Actions.CopyWindow |
Copiar ventana a todos los workspaces (sticky) | SI |
Actions.GridSelect |
Selector visual de ventanas en cuadricula | SI |
Actions.WithAll |
Aplicar accion a todas las ventanas (sinkAll, etc.) | SI |
Actions.SpawnOn |
Lanzar app en un workspace especifico | NO |
Actions.Promote |
Swap ventana actual con master | NO |
Actions.CycleWS |
Navegar workspaces con atajos | NO (tenemos custom) |
Las que molan mucho
| Modulo | Que hace |
|---|---|
Actions.TreeSelect |
Menu en arbol para workspaces. Como un file manager pero para tus escritorios. Puedes anidar categorias: "Trabajo > Vocento > Bitbucket" |
Actions.DynamicProjects |
Workspaces con nombre y startup hook. "M-p proyecto" abre workspace "Cohete" que lanza terminal + emacs + firefox automaticamente |
Actions.EasyMotion |
Numera las ventanas visibles y saltas a una tecleando su numero. Como vim-easymotion pero para ventanas |
Actions.Search |
Busca en Google/DuckDuckGo/Hoogle/Wikipedia desde un prompt. M-/ "que es monada haskell" abre el navegador |
Actions.Submap |
Keybindings multi-nivel tipo Emacs. M-x abre un submap, luego "w s" hace algo. Prefijos infinitos |
Actions.TopicSpace |
Workspaces tematicos: cada uno tiene un directorio de trabajo y app por defecto. "Codigo" abre terminal en ~/src, "Mail" abre thunderbird |
Actions.MouseGestures |
Gestos de raton: boton derecho + arrastrar izquierda = workspace anterior |
Actions.WindowMenu |
Menu contextual para ventanas: cerrar, flotar, mover a workspace, minimizar |
Actions.Navigation2D |
Navegar ventanas con flechas en 2D (arriba/abajo/izquierda/derecha) de forma intuitiva |
Actions.Minimize |
Minimizar ventanas a la bandeja (como Windows). Con maximize para restaurar |
Actions.GroupNavigation |
Alt-Tab por historial real (no circular). Va a la ventana que usaste hace 2 ventanas |
Actions.Warp |
Mueve el cursor al centro de la ventana enfocada automaticamente |
Actions.SwapWorkspaces |
Intercambiar el contenido de dos workspaces enteros |
Actions.DynamicWorkspaces |
Crear y destruir workspaces al vuelo. No estas limitado a 1-9 |
Actions.Profiles |
Perfiles de configuracion: "trabajo" vs "gaming" vs "multimedia" con distintos layouts y keybindings |
Layouts (90+ modulos)
Formas de organizar ventanas. Cada layout es una idea distinta.
Los que usamos
ThreeColumns, ResizableTall, MultiColumns, Column, Grid, Spacing, NoBorders, ToggleLayouts, IndependentScreens.
Los que nos faltan
| Layout | Que hace | Para que |
|---|---|---|
Layout.BinarySpacePartition |
BSP como i3/bspwm. Cada split divide el espacio en 2 | Para los que vienen de i3 |
Layout.Tabbed |
Pestanas como navegador. Multiples ventanas con tabs arriba | Cuando tienes 10 terminales y no quieres 10 tiles |
Layout.Magnifier |
La ventana enfocada se agranda, las demas se encogen | Para pair programming o demos |
Layout.Combo |
Combinar layouts: mitad izquierda Tall, mitad derecha Tabbed | Lo mejor de dos mundos |
Layout.Accordion |
Ventanas apiladas como acordeon. La enfocada se expande | Pantallas verticales o side panels |
Layout.Spiral |
Espiral de Fibonacci. Cada ventana nueva mas pequena y rotando | Bonito. Poco practico. Ideal para screenshots |
Layout.Roledex |
Ventanas en abanico con offset. Como un Rolodex | Visualmente impresionante |
Layout.Circle |
Ventanas en circulo, enfocada grande en el centro | Pantallas muy grandes |
Layout.Dwindle |
Como Spiral pero alternando horizontal/vertical | Mas practico que Spiral |
Layout.Dishes |
Master arriba, resto en filas horizontales | Dashboards con panel principal |
Layout.TwoPane |
Solo dos ventanas visibles. Navegar cambia cual se muestra | Minimalista extremo |
Layout.OneBig |
Una ventana grande, el resto en miniatura | Video + chat |
Layout.SubLayouts |
Layouts DENTRO de otros. Tabs dentro de Tall | Composicion (esto es Haskell, baby) |
Layout.PerWorkspace |
Layout diferente por workspace | Automatizar por contexto |
Layout.PerScreen |
Layout diferente por pantalla. Ultrawide: ThreeCol. Laptop: Tall | Multi-monitor inteligente |
Layout.Hidden |
Ocultar ventanas sin cerrarlas | Minimizar sin systray |
Layout.Drawer |
Panel lateral desplegable | Sidebars |
Layout.Groups |
Agrupar ventanas en tabs, moverse entre grupos | SubLayouts pero mas potente |
Layout.Maximize |
Maximizar una ventana temporalmente | M-f manteniendo layout debajo |
Layout.MouseResizableTile |
Redimensionar ventanas con raton | Para los que echan de menos el raton |
Prompts (18 modulos)
El sistema de prompts que acabamos de estrenar. Lo que nos falta:
| Prompt | Que hace |
|---|---|
Prompt.Shell |
Lanzar programas (como dmenu). YA ACTIVO |
Prompt.Window |
Ir a / traer ventana. YA ACTIVO |
Prompt.Man |
Man pages. YA ACTIVO |
Prompt.Ssh |
SSH a hosts. YA ACTIVO |
Prompt.FuzzyMatch |
Fuzzy matching. YA ACTIVO |
Prompt.RunOrRaise |
Lanzar O ir a app si ya esta abierta. Lo mejor de Shell + Window Go |
Prompt.XMonad |
Ejecutar acciones internas por nombre. Tipo M-x de Emacs |
Prompt.Workspace |
Ir a workspace por nombre, crear nuevos |
Prompt.Layout |
Cambiar layout escribiendo nombre en vez de ciclar |
Prompt.Pass |
Buscar passwords en pass (password-store) |
Prompt.Unicode |
Buscar caracteres unicode por nombre e insertarlos |
Prompt.OrgMode |
Capturar notas en formato org-mode desde el prompt |
Prompt.AppendFile |
Escribir linea y anadirla a un archivo. Inbox rapido |
Prompt.ConfirmPrompt |
Confirmar acciones peligrosas (logout, reboot) |
Prompt.DirExec |
Ejecutar scripts de un directorio |
Hooks (35 modulos)
Funciones que se ejecutan cuando pasan cosas.
| Hook | Que hace | Usamos? |
|---|---|---|
Hooks.ManageDocks |
Respetar espacio de barras | SI |
Hooks.EwmhDesktops |
Compatibilidad EWMH | SI |
Hooks.DynamicLog |
Info para xmobar | SI |
Hooks.WindowSwallowing |
Terminal traga apps que lanza. vim reemplaza terminal, al cerrar vuelve | NO (quiero) |
Hooks.FadeInactive |
Ventanas inactivas semi-transparentes | NO |
Hooks.InsertPosition |
Controlar donde aparecen ventanas nuevas | NO |
Hooks.UrgencyHook |
Flash visual cuando ventana pide atencion | NO |
Hooks.RefocusLast |
Al cerrar ventana, volver a la anterior | NO |
Hooks.ShowWName |
Nombre del workspace en grande al cambiar | NO |
Hooks.DynamicIcons |
Iconos dinamicos en xmobar segun apps abiertas | NO |
Hooks.ScreenCorners |
Hot corners como macOS | NO |
Hooks.Modal |
Modos tipo vi: normal, resize, move | NO (quiero) |
Util (50+ modulos)
| Util | Que hace | Usamos? |
|---|---|---|
Util.EZConfig |
Keybindings estilo "M-p" | SI |
Util.SpawnOnce |
Ejecutar solo una vez | SI |
Util.NamedScratchpad |
Ventanas flotantes toggle | SI |
Util.NamedActions |
Documentar keybindings automaticamente. M-? muestra atajos | NO (QUIERO) |
Util.Themes |
Pack de temas predefinidos | NO |
Util.Paste |
Pegar texto programaticamente | NO |
Util.ExclusiveScratchpads |
Solo un scratchpad visible a la vez | NO |
Util.Hacks |
Workarounds para bugs de apps Java, Chrome | NO |
Util.DynamicScratchpads |
Convertir cualquier ventana en scratchpad | NO |
Util.ClickableWorkspaces |
Click en workspaces de xmobar | NO |
Lo que queremos probar siguiente
Mi shortlist de lo que mas nos cambiaria la vida:
- RunOrRaise - Si la app ya esta abierta, te lleva. Si no, la lanza. Cero duplicados.
- WindowSwallowing - Terminal traga apps. vim reemplaza alacritty, al cerrar vuelve.
- Submap - Keybindings multi-nivel tipo Emacs.
- TreeSelect - Menu en arbol para workspaces.
- Actions.Search - Buscar en Google/Hoogle desde prompt.
- Hooks.Modal - Modos tipo vim: normal, resize, move.
- NamedActions - M-? muestra TODOS los keybindings.
- DynamicProjects - Workspaces con startup automatico.
Por que Haskell no da miedo
La gente ve Haskell y sale corriendo. Pero nuestro xmonad.hs de 448 lineas usa exactamente esto:
- Listas:
[1, 2, 3] - Strings:
"hola" - Records:
{ font = "...", bgColor = "#282c34" } - Funciones:
foo x = x + 1 - Pattern matching:
case x of Just y -> y; Nothing -> 0 - Pipe:
layout1 ||| layout2 ||| layout3 - Composicion:
hook1 <+> hook2 <+> hook3 - Import:
import XMonad.Prompt.Shell
No necesitas entender monadas, functors, typeclasses, ni nada de eso para tener un WM brutal.
Como anadir un modulo nuevo
Ejemplo: WindowSwallowing (terminal traga apps):
-- 1. Anadir import
import XMonad.Hooks.WindowSwallowing
-- 2. Anadir al handleEventHook
, handleEventHook = swallowEventHook (className =? "Alacritty") (return True)Recompilar:
xmonad --recompile && xmonad --restartDos lineas. Sin instalar nada. Hot reload.
El resultado
Lo que empezamos como "reemplazar dmenu" se ha convertido en
descubrir que XMonad tiene un catalogo de 300+ extensiones que cubren
cualquier cosa que puedas querer de un window manager. Y todas son un
import de distancia.
La pregunta no es "que le falta a XMonad". Es "cuanto de lo que tiene estamos usando". La respuesta: alrededor del 10%.
Nos queda un 90% por explorar.
Comentarios (0)
Sin comentarios todavia. Se el primero!
Deja un comentario