lid's stuff

Slimv: REPL Common Lisp pour ViM

Étant un Vimmer, s'il y a bien quelque chose que j'enviais à Emacs, c'était bien Slime (Superior Lisp Interaction Mode for Emacs).

Après quelques tâtonnements, j'ai enfin réussi:

  • à faire tourner correctement slimv, l'implémentation de Slime pour ViM. Hint: la version sur github n'est pas à jour, il faut utiliser mercurial pour cloner le repo sur bitbucket
  • à lancer StumpWM directement via sbcl, et à le faire lancer sur commande le serveur swank sur lequel slimv se connectera pour vous permettre d'obtenir une jolie REPL (Read-Eval-Print-Loop) depuis ViM vous permettant d'interagir avec StumpWM, et surtout de pouvoir modifier son code à la volée et de le faire réévaluer par la REPL sans avoir à recompiler le code source de stumpWM. Et ça… c'est juste énorme!

Étapes préliminaires et prérequis

  • Une distribution Linux installée
  • Une implémentation Common Lisp installée (par exemple, sbcl ou clisp)
  • git et mercurial
  • Quicklisp installé et configuré (j'y reviens)

Installation de sbcl

Pour cet article je prendrais Steel Bank Common Lisp aka SBCL comme exemple.
Votre distribution doit normalement fournir un paquet SBCL dans ses dépôts, donc normalement rien de bien difficile.
Pour ceux qui aiment le travail mâché:

Archlinux:

$ sudo pacman -S sbcl

Debian et consorts:

$ sudo apt-get install sbcl
ou alternativement, vu qu'on est en 2015:
$ sudo apt install sbcl

etc, etc en fonction de votre gestionnaire de paquets

On va déjà vérifier que sbcl fonctionne:

$ sbcl
This is SBCL 1.2.16, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (quit)

Tapez (quit) puis Return pour quitter la REPL SBCL.

Installation de quicklisp et de StumpWM via QuickLisp

Téléchargez le fichier quicklisp.lisp disons dans ~/Downloads par exemple.

Lancez ensuite la commande:

$ sbcl --load ~/Downloads/quicklisp.lisp

Pour installer Quicklisp (normalement dans le répertoire ~/quicklisp)

SBCL va ouvrir sa REPL, à l'invite de commande, tapez:

(quicklisp-quickstart:install)
(ql:add-to-init-file)

Qui va installer quicklisp et le lancer à chaque démarrage de SBCL (regardez votre fichier ~/.sbclrc ;))

Ensuite, nous voulons installer StumpWM via QuickLisp (et non pas via github, compilation, etc ainsi que je vous en parlais dans un article précédent):

(ql:quickload "stumpwm")

Qui devrait normalement installer tout le nécessaire pour StumpWM, c'est à dire StumpWM lui même ainsi que CLX (bindings XLib pour Common Lisp) et CL-PPCRE (regexes Perl pour Common Lisp). Si ce n'est pas le cas:

(ql:quickload "clx")
(ql:quickload "cl-ppcre")

On veut aussi pouvoir utiliser swank pour que ViM puisse se connecter ensuite à la REPL de StumpWM:

(ql:quickload "swank")

Normalement, de ce côté-ci, on est bons!

Installation de Slimv pour ViM

Tout d'abord, je vous recommande d'utiliser un gestionnaire de plugins pour ViM tels Pathogen, vundle, et caetera, celui de votre choix, qui nous faciliterons le travail et éviterons de transformer nos répertoires .vim/plugins & cie en bordel ingérable©

De même, vérifiez que ViM a bien été compilé avec le support de python (c'est normalement le cas si vous avez par exemple installé gvim ou vim-full)

Dans mon cas, j'utilise le bon vieux pathogen:

$ cd ~/.vim/bundle
$ hg clone https://bitbucket.org/kovisoft/slimv slimv

Comme on veut aussi pouvoir s'en servir sans forcément se connecter à la REPL de stumpwm, on ajoute cette ligne (à modifier suivant que vous utilisiez tmux, screen ou rien du tout, cf la documentation de slimv) à notre ~/.vimrc:

let g:slimv_swank_cmd = '! tmux new-window -d -n REPL-SBCL "sbcl --load ~/.vim/bundle/slimv/slime/start-swank.lisp"'

Qui nous permettra de nous connecter à une REPL Common Lisp depuis ViM. Pour cela, lançons ViM sur n'importe quel fichier Lisp, puis tapons ,c, on devrait obtenir quelque chose du style:

REPL_Basic

Si c'est le cas, tout marche! Essayez de taper 2/3 commandes dans la REPL, par exemple:

(format t "Hello World!")
(+ 2 (* 3 5))

etc…

Maintenant, tapez, dans votre fichier lisp, quelque chose comme:

(defun my_hello_world ()
  (format t "Hello World!!"))

positionnez vous sur defun, tapez ,s, vous aurez la doc pour la fonction defun

Tapez ,d, la fonction sera envoyée et évaluée dans la REPL - génial, non? Il y a bien sûr beaucoup d'autres commandes, que je vous invite à découvrir avec l'excellent tutorial de slimv sur http://kovisoft.bitbucket.org/tutorial.html qui vous permettra de découvrir toutes les fonctionnalités nécessaires, notamment l'inspecteur, les différentes options pour évaluer et compiler du code à la volée, etc… vous allez voir, c'est génial :)

Bon, et Stump?

On y arrive!

Tout d'abord, nous allons maintenant lancer StumpWM via SBCL directement, et non plus l'exécutable compilé. Pour cela, nous allons créer un fichier startstump.lisp (par exemple) que nous allons appeler dans notre fichier .xinitrc ou .xsession suivant votre distribution et votre choix d'environnement graphique:

Le fichier startstump.lisp:

(require:stumpwm)
(stumpwm:stumpwm)

Dans le .xinitrc:

exec sbcl --load /path/to/startstump.lisp

Dans votre fichier ~/.stumpwmrc ajoutez les lignes suivantes:

(require :swank)
(defun load-stump-swank ()
  (swank-loader:init)
  (swank:create-server :port 4005
                       :style swank:*communication-style*
                       :dont-close t))

(defcommand lss () ()
  "loading the swank REPL for stumpwm"
  (load-stump-swank))

La première ligne charge la dépendance swank, la fonction load-stump-swank initialise le serveur swank qui nous permettra d'accéder à la REPL via ViM, fonction qui sera lancée par la commande lss, qui ne prend aucun paramètres, via la commande Stump:

C-t :lss

En effet, on ne veut pas lancer swank automatiquement au lancement de stumpWM, car sinon, sur un C-t :restart-hard par exemple, Stump ne pourra pas relancer swank, le port 4005 étant déjà utilisé, et donc ne chargera pas votre configuration (oops!).

On quitte X, brutalement, de préférence, et on relance stumpWM avec notre joli script tout neuf. On tape ensuite C-t :lss pour lancer le serveur swank, et on lance enfin notre pote vim, par exemple:

vim ~/.stumpwmrc

On tape à nouveau ,c pour se connecter à la REPL, on devrait arriver à quelque chose comme ça:

stumpreplstart

Maintenant, affichons par exemple la version de StumpWM depuis la REPL:

(stumpwm:version)

Qui devrait nous donner ça:

replinaction

On voit bien que depuis la REPL, nous avons pu lancer une commande (version) StumpWM.

Bon, taper stumpwm: à chaque fois est un peu embêtant, plaçons nous donc dans le package stumpwm en tapant dans la REPL:

(in-package :stumpwm)

On remarque que l'invite de la REPL devient: STUMPWM>

À partir de là, toutes nos commandes seront par défaut préfixées de stumpwm: - on peut donc, dans la REPL, taper directement (version) pour obtenir la version de StumpWM (ou (windowlist) pour avoir la liste des fenêtres du groupe courant, etc).

Alors vous allez me dire, ok, c'est bien joli, mais je vais pas taper mes commandes stumpwm à la main dans une REPL, c'est une régression mon bon ami… En fait, c'est pas le but.

Redéfinir le code de StumpWM en live

Et c'est là que ça devient intéressant! Par exemple, clonons le code source de Stump depuis github et ouvrons, au hasard, le fichier source group.lisp et modifions la fonction add-group à la ligne 301 (le code d'erreur: un nom de groupe ne peut pas être vide). Pour le moment il contient cette ligne:

(error "Groups must have a name.")

Modifions le de la sorte:

(error "Groups must have a FUCKING name!")

et réévaluons la fonction avec la commande vim ,d, notre REPL va nous envoyer un petit WARNING pour nous dire que nous venons de réévaluer une fonction de STUMPWM:

stumpouinouin

Maintenant, essayons de créer un groupe sans nom via la commande C-t :gnew, nous devrions bien nous faire insulter:

stumpinsult

Et c'est bien le cas!!
Nous venons donc de modifier, en live le code source de StumpWM, dont cette fonction précise (addgroup) qui a été réévaluée à la volée, sans que nous ayons à recompiler ou relancer StumpWM!!! Alors certe, c'est un exemple trivial, mais je vous laisse imaginer la puissance de cette combo (vim/slimv ou emacs/slime et stumpwm) par exemple pour programmer en live de nouvelles extensions pour StumpWM!

Amusez-vous bien!


Tagged under: linux, window managers, stumpwm, common lisp, vim