Skip navigation

Bon, ça faisait bien un peu plus d’un an que je n’avais rien posté – les impératifs de la vie réelle ayant un peu pris le dessus – mais vu que je suis désormais en « vacances prolongées », je devrais avoir un peu plus de temps pour venir vous gonfler avec les gestionnaires de fenêtres en mode pavant, les applications en mode texte et autres joyeusetés de geek assumé 🙂
Allez, on embraye, on perd pas de temps, aujourd’hui je vais vous parler de XMonad, le gestionnaire de fenêtres écrit, configuré et bidouillé en… Haskell. Tiens, j’entends quelques cris d’orfraie: « Au secours le haskell c’est une horreur c’est imbuvable on va tous mourir! ».

Meuh non. C’est pas plus dur que du lua, surtout pour ce qu’on veut faire: configurer xmonad.

I- Installation de xmonad.
Normalement, il ne devrait pas y avoir de problème, il doit être dans vos dépôts.

Sous ArchLinux:

yaourt -S xmonad xmonad-contrib xmobar

Le paquet xmonad se passe de commentaires, xmonad-contrib contient de nombreux addons (dont nous aurons besoin notamment pour rajouter de nouveaux layouts 🙂 ) et xmobar nous permettra d’afficher une petite barre à la dzen – on peut aussi utiliser dzen2, mais xmobar a quelques avantages dans le cas de l’utilisation avec xmonad – c’est pas pour rien qu’il commence par « xmo », hein!
Une fois installé, vous pourrez le lancer soit via votre .xinitrc, votre .xsession ou votre login manager – je ne vais pas détailler tout le bousin, ce serait un peu long, alors autant vous passer un lien vers la doc d’xmonad (en angliche):

http://xmonad.org/documentation.html

Au premier lancement, vous devriez arriver à un splendide écran noir du plus bel effet, tellement d’ailleurs qu’une des premières entrées de la FAQ d’xmonad concerne justement ce « mais y’a rien à l’écran boudiou! ».

Normal, on a rien configuré. Faites donc un petit shift-alt-return pour lancer un xterm (beurk, on va remplacer ça par urxvt – c’est même une des premières choses que l’on va faire).

La configuration par défaut, très basique, propose les mêmes raccourcis clavier qu’un awesome/dwm – là aussi, on peut remplacer Alt par Mod4, etc, on va y venir – cependant, étant l’heureux possesseur d’un clavier IBM Model M (de 1991), je me sers de la bonne vieille touche Alt pour mes raccourcis (pensez-y quand je vous montrerai, par exemple, comment rajouter de nouveaux raccourcis clavier).

Un petit récapitulatif vite fait:

S-Alt-Return : xterm

Alt-j/k : passer d’un client à l’autre, avec shift on intervertit les clients, classique

Alt-h/l : diminue/augmente la taille du master

Alt-Return: passe le client sélectionné en master

Alt-Space: changement de layout (pour le moment, 3 layouts, on va en rajouter tout à l’heure 🙂 )

Ce n’est pas une liste exhaustive, et si vous utilisez un clavier français, pour le moment, vous ne pouvez pas changer de workspace – on va y venir dans la configuration.

 

II- Le gros morceau: la configuration d’Xmonad.
Bon, pour le moment, Xmonad saybingentil© mais c’est un peu chiant. On va égayer tout ça!

Tout d’abord, le fichier de conf’ se trouve dans ~/.xmonad/ et s’appelle xmonad.hs.

S’il n’existe pas, créez le avec votre éditeur de texte favori! Plutôt que de vous faire un copié collé du mien, je vais vous le détailler en plusieurs parties. Je vous conseille de copier le fichier /usr/share/xmonad-0.9.2/man/xmonad.hs dans ~/.xmonad/ afin de bien voir ce que je modifie.

Tout d’abord: importation des libs XMonad:

import XMonad
import Data.Monoid
import System.Exit
import XMonad.Hooks.DynamicLog
import qualified XMonad.StackSet as W
import qualified Data.Map                 as M
import XMonad.Hooks.ManageDocks
import XMonad.Util.Run(spawnPipe)
import XMonad.Util.EZConfig(additionalKeys)
import XMonad.Actions.CycleWS
import XMonad.Layout.Circle
import XMonad.Layout.ResizableTile
import XMonad.Layout.Tabbed
import XMonad.Layout.Spiral
import XMonad.Layout.Magnifier
import System.IO

Les six premiers « import » (comme en lua, en python, équivalent aux include en C), sont les imports « de base » d’XMonad.

Viennent ensuite:

  • ManageDocks: ça va nous permettre de gérer xmobar ou dzen2, en lui réservant un espace sur l’écran, qui ne sera pas recouvert par les autres clients – tout comme le padding de ratpoison, par exemple.
  • Run(spawnPipe): nous permettra d’envoyer des informations d’XMonad au stdin de xmobar (workspace, layout, titre du client)
  • EZConfig(additionalKeys): pour rajouter facilement des raccourcis clavier à la fin du fichier de conf’ d’xmonad
  • Actions.CycleWS: va nous permettre de binder quelques touches pour cycler entre les workspaces
  • Layout.*: différents layouts que nous allons utiliser – il y en a un gros paquet, et de plus il existe aussi un mode Combo, sur lequel je reviendrai lorsque je l’aurai testé (donc pas aujourd’hui ^^)

myTerminal = « urxvt »

myFocusFollowsMouse :: Bool

myFocusFollowsMouse = False (ou True, dépend de vos goûts en la matière)

myBorderWidth = 1 (taille de la bordure autour du client sélectionné)

myModMask = mod1Mask (mod4Mask pour la touche zindoze)

myWorkspaces = [« 1 », « 2 »,…blabla, »9″] (on peut aussi mettre des noms, [« main », »blabla », »trucmuche »,…etc] )

myNormalBorderColor = « #3f3f3f » (la couleur pour le bord d’une fenêtre sans focus)

myFocusedBorderColor = « #6f6f6f » (je vous laisse deviner…)

 

Ensuite, nous allons définir la liste de nos layouts:

myOwnLayout = tiled ||| Mirror tiled ||| magnifier (Circle) ||| ResizableTall 1 (3/100) (1/2) [] ||| spiral (6/7) ||| simpleTabbed ||| Full

where

tiled = Tall nmaster delta ratio

nmaster = 1

ratio = 1/2

delta = 3/100

Notez que j’aurai pu faire de même pour ResizableTall, en l’appellant resizetall, puis en le définissant dans le where: resizetall = ResizableTall nmaster delta ratio []

nmaster: le nombre de fenêtres dans le master, delta: le pourcentage de l’écran modifié à chaque redimensionnement via Alt-h/l, ratio: partage de l’écran par défaut (une moitié pour le master, l’autre moitié pour le reste)

Vous remarquerez que je n’ai pas touché aux raccourcis claviers par rapport à la config par défaut, et de même, je ne modifie pas myManageHook.

Idem pour les autres Hooks (myLogHook, myStartupHook, etc)

Ensuite, on charge notre conf’ par défaut dans la variable defaults:

defaults = defaultConfig {
— simple stuff
terminal           = myTerminal,
focusFollowsMouse  = myFocusFollowsMouse,
borderWidth        = myBorderWidth,
modMask            = myModMask,
numlockMask        = myNumlockMask,
workspaces         = myWorkspaces,
normalBorderColor  = myNormalBorderColor,
focusedBorderColor = myFocusedBorderColor,

— key bindings
keys               = myKeys,
mouseBindings      = myMouseBindings,

— hooks, layouts

manageHook         = myManageHook,
handleEventHook    = myEventHook,
logHook            = myLogHook,
startupHook        = myStartupHook
}

Là, comme vous le voyez, j’ai viré le layout = myLayout, par rapport à la conf par défaut, vous allez voir un peu plus bas pourquoi, puisque nous arrivons au bout du fichier de conf’:

main = do
xmproc <- spawnPipe « /usr/bin/xmobar »
xmonad $ defaultConfig
{ manageHook = manageDocks <+> manageHook defaultConfig
, layoutHook = avoidStruts $ myOwnLayout
, logHook = dynamicLogWithPP xmobarPP
{ ppOutput = hPutStrLn xmproc
, ppTitle = xmobarColor « lightblue » «  » . shorten 50
}
, modMask = mod1Mask
, terminal = myTerminal
, focusFollowsMouse = myFocusFollowsMouse
, workspaces = myWorkspaces
, normalBorderColor  = myNormalBorderColor
, focusedBorderColor = myFocusedBorderColor

} `additionalKeys`
[ ((0, xK_Pause), spawn « mpc –no-status toggle »)
, ((0, xK_Print), spawn « mpc –no-status prev »)
, ((0, xK_Scroll_Lock), spawn « mpc –no-status next »)
, ((mod1Mask, xK_u ), sendMessage (IncMasterN 1))
, ((mod1Mask, xK_i ), sendMessage (IncMasterN (-1)))
, ((mod1Mask, xK_Right), nextWS)
, ((mod1Mask, xK_Left), prevWS)
, ((mod1Mask .|. shiftMask, xK_Right), shiftToNext >> nextWS)
, ((mod1Mask .|. shiftMask, xK_Left), shiftToPrev >> prevWS)
, ((mod1Mask,               xK_p     ), spawn « dmenu_run -i -nb ‘#3F3F3F’ -nf ‘#DCDCCC’ -sb ‘#1E2320’ -sf ‘#F0DFAF' »)
, ((mod1Mask,             xK_a), sendMessage MirrorShrink)
, ((mod1Mask,              xK_z), sendMessage MirrorExpand)
]

 

Oui, ça fait un peu peur! Bon, ligne par ligne:

main = do     No Comment!!! 🙂

xmproc <- spawnPipe « /usr/bin/xmobar »  On envoie les données de Xmonad au stdin de xmobar – regardez au début du fichier, nous avons importé cette fonction 🙂 et c’est pas pour rien!

xmonad $ defaultConfig  on charge la config par défaut d’xmonad puis:

{ manageHook = manageDocks <+> manageHook defaultConfig
, layoutHook = avoidStruts $ myOwnLayout

Là, avoidStruts nous permet de réserver une petite place pour notre pote xmobar (dont on va parler dans pas longtemps 😉 ), et on charge NOS layouts et pas ceux par défaut 🙂

, logHook = dynamicLogWithPP xmobarPP
{ ppOutput = hPutStrLn xmproc
, ppTitle = xmobarColor « lightblue » «  » . shorten 50
}

Là, on définit ce qu’XMonad va envoyer à notre pote xmobar.

Le reste coule de source, jusqu’au:

`additionalKeys`

[

vos raccourcis clavier

]

comme vous le voyez, j’utilise les vieilles touches Print, Scroll Lock, et pause pour contrôler mpd via mpc, alt-u/i me permet d’ajouter/enlever un client du master, Alt-gauche/droite me permet (enfin! je vous avais bien dit qu’on allait y arriver) de passer d’un workspace à l’autre (là aussi, regardez bien ce qu’on a importé en début de fichier 😉 ) shift-alt-gauche/droite me permet d’envoyer une appli d’un workspace à l’autre. Vous noterez aussi le Alt-p, qui me lance dmenu avec des couleurs « zenburn » au lieu du dmenu de base dans la conf’ par défaut. Alt-a/z me permet de redimensionner un client verticalement en mode ResizableTall – un peu comme wmii.

Bien évidemment vous pouvez toujours remplacer mod1Mask par mod4Mask, etc…

Notez aussi la commande spawn « blabla », qui permet d’exécuter un programme dans le $PATH en l’associant à une touche du clavier/combo de touches.

Dernier petit détail, pour que xmonad prenne en compte vos changements, Alt-q permet de le recompiler et – si tout s’est bien déroulé – de le relancer. En cas d’erreur, vous verrez un xmessage apparaître avec l’erreur en question, la(les) ligne(s) concernée(s) et une solution possible.

Bon, votre xmonad devrait déjà avoir un peu plus de gueule! Il reste juste à remplir un peu notre pote xmobar d’infos intéressantes :] Et ça, ça se bidouille dans le fichier ~/.xmobarrc

 

III- Exemple de .xmobarrc.

Bon, tout d’abord je vous conseille fortement de lire le man d’xmobar, il y a pas mal d’options et ce serait un peu long de toutes les détailler. En attendant, voici le mien:

Config { font = « -*-terminus-*-*-*-*-12-*-*-*-*-*-*-u »
, bgColor = « #3F3F3F »
, fgColor = « #dcdccc »
, position = Top
, lowerOnStart = True
, commands = [ Run Network « eth0 » [« -L », « 8 », « -H », « 32 », « -l », « #C9A34E », « -n », « #429942″ , »-h », « #A36666 », « -t », « dl: <rx> Kio/s – ul: <tx> Kio/s »] 10
, Run Memory [« -t », »Mem: <usedratio>% »] 10
, Run Com « mpc » [« | head -n1 »] «  » 50
, Run MultiCpu [« -t <total0>% <total1>% »] 50
, Run Weather « LFRS » [« -t », » <tempC>°C », »-L », »10″, »-H », »22″, »–normal », »lightgreen », »–high », »#C33B3B », »–low », »lightblue »] 18000
, Run Date « %a %b %_d %Y %H:%M:%S » « date » 10
, Run StdinReader
]
, sepChar = « % »
, alignSep = « }{ »
, template =  » %StdinReader% }{ <fc=#dfaf8f>[</fc> ♫: %mpc% <fc=#dfaf8f>|</fc> #:%multicpu% <fc=#dfaf8f>|</fc> %memory% <fc=#dfaf8f>|</fc> %eth0% <fc=#dfaf8f>|</fc> ☼:%LFRS% %date% <fc=#dfaf8f>]</fc> »
}

Important: le Run StdinReader! C’est ce qui nous permet de lire ce qu’XMonad va envoyer au stdin d’xmobar 🙂

De même, si vous voulez lancer une commande externe à xmobar, Run Com « nomdelacommande » [« paramètres / pipe »] «  » intervalle en dixième de secondes.

Comme vous voyez, xmobar est assez complet et nous permet d’afficher pas mal de choses. Petite note au niveau de Weather (météo): habitant à Nantes, ma station est LFRS, vous pourrez trouver une liste complète ici:

http://weather.noaa.gov

Et la doc d’xmobar:

http://projects.haskell.org/xmobar/

Et pour finir, un petit screenshot de chez moi:

 


 

4 Comments

  1. Un articles sympathique. Moi qui suis en pleine recherche d’un bon tiling WM je suis comblé par tout ça.
    Je rajoute juste une petite précision très facilement trouvable dans la doc :
    « When running with multiple monitors (Xinerama, TwinView, xrandr), each screen has exactly 1 workspace visible. Pressing mod-{w,e,r} switches the focus between screens, while pressing shift-mod-{w,e,r} moves the current window to that screen. When xmonad starts, workspace 1 is on screen 1, workspace 2 is on screen 2, etc. When switching workspaces to one that is already visible, the current and visible workspaces are swapped. »
    Ca permettra de tester vite fait le truc en lisant ton article sans avoir à passer par la doc.

    • lidstah
    • Posted 11 juillet 2011 at 11 h 13 min
    • Permalink

    Salut Pheimors!
    En effet, j’avais « zappé » les raccourcis clavier et le fonctionnement d’XMonad en multi-écrans lorsque j’ai écrit cet article, car j’ai chopé mon deuxième écran la semaine suivante :]
    Merci de ta précision à ce sujet 😉 – je mettrai d’ailleurs à jour l’article dans le courant de la journée normalement.
    En espérant que cet article te soit utile dans ta découverte d’XMonad, qui offre vraiment beaucoup de possibilités de personnalisation, même si (et ce fût mon cas pendant un bon bout de temps) la conf’ en haskell peut rebuter de prime abord :p

    • saroumane
    • Posted 9 janvier 2012 at 17 h 57 min
    • Permalink

    Salut « voisin ».
    — Un Brestois émigré sous les tropiques.
    — commentaire en mode Haskell !!!

    Je suis obligé de te laisser un petit mot tellement ton article m’a été d’une grande aide.
    J’en ai googlé des « configuer xmonad ** * * *  » et dans toutes les pages vues, c’est ton article qui m’a permis d’avoir un système fonctionnel.
    Bon, le copier/coller et le Haskell ne font pas bon ménage…mais j’ai fini par réussir.
    Seul truc qui cloche –> myNumlockMask ‘est défini nul part.
    Dommage que tu n’aies pas évoqué le multi-écran.. En tout cas Xmonad et le WM que je cherchais, quant au Haskell, je pensais à un truc pour barbu mais finalement…

    Merci en tout cas pour le temps que tu m’as fait gagné.
    Sarou

    • lidstah
    • Posted 11 janvier 2012 at 1 h 55 min
    • Permalink

    Salut Saroumane!

    Tout d’abord, merci beaucoup pour ton commentaire, ça fait vraiment plaisir d’avoir du retour positif, et encore plus de savoir que ça t’auras (et à d’autres, je l’espère), été utile 🙂

    Alors pour le myNumLockMask, il me semble (si tu utilises la version 0.10 d’XMonad) que ça a dégagé (j’utilisais la 0.9.2 lors de la rédaction de cet article, faut que je le mette à jour (l’article, pas xmonad, lui, c’est fait 😉 ).

    Pour le multi-écran, faut que, là encore, je mette à jour l’article (normalement mod+z,e,r permettent de switcher d’un écran à un autre, chacun affichant un workspace donné, une des qualités d’xmonad) – mais je suis un peu overbooké en ce moment, entre le boulot, le parti pirate des pays de la loire, et la zique 😀

    Quant à Haskell… aaah, c’est un langage très intéressant, fonctionnel (comme Lisp par exemple), avec un riche choix de bibliothèques de fonctions… Miam :]

    En tout cas, merci de ton commentaire, ça fait toujours plaisir!


Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

What is 12 + 12 ?
Please leave these two fields as-is: