22-Aller plus loin avec SLIME.
Je suppose que vous avez ouvert une session SLIME.
Sinon dans EMACS tapez M-x SLIME.
Rappelons que C représente la touche Ctrl, et M la touche Alt.
Vous venez de copier une fonction au REPL et elle vous semble mal indentée.
Vous pouvez procéder de deux façons:
1) Placez le curseur au début de chaque ligne et tapez la touche <TAB>.
2) Placez le curseur sur la parenthèse ouvrante et tapez: C-M-q.
Tapons ce qui suit:
C-c C-d C-h
Attention! Ne tapez pas C-c C-d h : ceci servirait à ouvrir l'hyperspec.
Une nouvelle fenêtre s'ouvre dans EMACS:
Début de la fenêtre.Je suppose que vous avez ouvert une session SLIME.
Sinon dans EMACS tapez M-x SLIME.
Rappelons que C représente la touche Ctrl.
Tapons ce qui suit:
C-c C-d C-h
Attention! Ne tapez pas C-c C-d h : ceci servirait à ouvrir l'hyperspec.
Une nouvelle fenêtre s'ouvre dans EMACS:
`slime-autodoc-mode' Minor Mode Bindings Starting With C-c C-d:
key binding
--- -------
C-c C-d C-a slime-autodoc-manually
C-c C-d A slime-autodoc-manually
`slime-editing-mode' Minor Mode Bindings Starting With C-c C-d:
key binding
--- -------
C-c C-d C-d slime-describe-symbol
C-c C-d C-f slime-describe-function
C-c C-d C-g common-lisp-hyperspec-glossary-term
C-c C-d C-p slime-apropos-package
C-c C-d C-z slime-apropos-all
C-c C-d # common-lisp-hyperspec-lookup-reader-macro
C-c C-d a slime-apropos
C-c C-d d slime-describe-symbol
C-c C-d f slime-describe-function
C-c C-d g common-lisp-hyperspec-glossary-term
C-c C-d h slime-documentation-lookup
C-c C-d p slime-apropos-package
C-c C-d z slime-apropos-all
C-c C-d ~ common-lisp-hyperspec-format
C-c C-d C-# common-lisp-hyperspec-lookup-reader-macro
C-c C-d C-~ common-lisp-hyperspec-format
Global Bindings Starting With C-c C-d:
key binding
--- -------
[back]
Fin de la fenêtre.
Nous sommes dans le 'slime-autodoc-mode' qui nous fournit toutes les liaisons commençant par:
C-c C-d.
Vous voulez une description de la fonction CAR, tapez:
C-c C-d C-f (ou bien C-c C-d f)
Puis <CAR> et <ENTREE> dans le mini-tampon.
Une nouvelle fenêtre s'ouvre contenant des indications sur la fonction, en particulier sa documentation (en anglais).
C-x o pour aller dans cette fenêtre.
q pour quitter la fenêtre.
Vous voulez en savoir plus sur un package: CL par exemple. Tapez:
C-c C-d C-p (ou bien C-c C-d p)
Puis <CL> et <ENTREE> dans le mini-tampon.
Vous obtenez, cette fois, tous les symboles externes du package Common Lisp: variables, fonctions, macros, type.
C-x o pour aller dans cette fenêtre.
q pour quitter la fenêtre.
Vous voulez connaître la fonction liée à un raccourci.
Il existe pour cela une fonction describe-key liée au raccourci C-h k. Tapez:
C-h k
Le mini-tampon vous annonce que vous venez d'appeler la fonction describe-key et attend le raccourci (clé) à décrire.
Justement, tapez: C-h k
La fenêtre suivante s'ouvre:
début
C-h k runs the command describe-key (found in global-map), which is an
interactive compiled Lisp function in ‘help.el’.
It is bound to C-h k, <f1> k, <help> k, <menu-bar> <help-menu>
<describe> <describe-key-1>.
(describe-key &optional KEY UNTRANSLATED UP-EVENT)
Display documentation of the function invoked by KEY.
KEY can be any kind of a key sequence; it can include keyboard events,
mouse events, and/or menu events. When calling from a program,
pass KEY as a string or a vector.
If non-nil, UNTRANSLATED is a vector of the corresponding untranslated events.
It can also be a number, in which case the untranslated events from
the last key sequence entered are used.
UP-EVENT is the up-event that was discarded by reading KEY, or nil.
If KEY is a menu item or a tool-bar button that is disabled, this command
temporarily enables it to allow getting help on disabled items and buttons.
[back]
fin
Cette fenêtre vous explique ce que fait la fonction describe-key liée au raccourci que vous avez tapé.
Prenons un autre exemple.
Il existe un raccourci: C-h b ...Désolé, je ne me souviens plus à quelle fonction il est lié.
Qu'importe! Je viens de voir comment faire. Je tape:
C-h k
Puis dans le mini-tampon:
C-h b
J'obtiens:
début
C-h b runs the command describe-bindings (found in global-map), which
is an interactive compiled Lisp function in ‘help.el’.
It is bound to C-h b, <f1> b, <help> b, <menu-bar> <help-menu>
<describe> <list-keybindings>.
(describe-bindings &optional PREFIX BUFFER)
Display a buffer showing a list of all defined keys, and their definitions.
The keys are displayed in order of precedence.
The optional argument PREFIX, if non-nil, should be a key sequence;
then we display only bindings that start with that prefix.
The optional argument BUFFER specifies which buffer’s bindings
to display (default, the current buffer). BUFFER can be a buffer
or a buffer name.
[back]
fin
On me rappelle, dans cette fenêtre, que C-h b est lié à la fonction describe-bindings qui affiche la liste de tous les raccourcis définis et leurs définitions.
...Ah, oui! Je me souviens maintenant.
Derechef, essayons cette fonction. Tapez:
C-h b
La fenêtre qui s'ouvre vous donne accès à tous les raccourcis. Génial!
Les clés (ou raccourcis) que nous venons d'utiliser sont propres à EMACS et s'adaptent au mode du tampon utilisé.
Ce qui veut dire que la réponse ne sera pas forcément la même pour tous les tampons.
Notez que les menus déroulants d'EMACS contiennent certaines clés et que ces menus varient d'un tampon à l'autre.
Il est temps de définir quelques clés d'EMACS. Reprenons celles déjà vues plus haut:
C-h k <key>
M-x describe-key
Décrit la fonction actuelle liée à <key> pour le tampon ayant le focus.
Vous avez deux méthodes d'accès à la fonction:
1°) C-h k (C est la touche <Ctrl>)
2°) M-x describe-key (M est la touche <Alt>)
La touche de tabulation peut être utile pour retrouver la fonction describe-key.
Les autres clés fonctionnent sur le même principe:
C-h b
M-x describe-bindings
Répertorie les raccourcis clavier actuels pour le tampon ayant le focus.
C-h m
M-x describe-mode
Affiche toutes les touches de mode majeur disponibles, puis les touches de mode mineur, pour les modes du tampon ayant le focus.
Essayez!
Placez le curseur dans un tampon REPL, puis C-h m. Voyez le résultat.
Placez le curseur dans un tampon Fundamental, puis C-h m. Constatez un résultat différent.
quelles suite de touches venez-vous de taper? Vous avez un doute. Faites ceci:
C-h l
M-x view-lossage
Vous montre la séquence littérale de touches que vous avez tapées.
Vous constaterez que l'historique (dans une nouvelle fenêtre) remonte assez loin.
La toute dernière séquence doit être:
C-h l [view-lossage]
La fonction liée apparaît entre crochet.
La désignation C-h est ce qu'on appelle une clé canonique. Elle signifie Ctrl-h ou <F1> actuellement.
Mais vous pouvez changer cette signification dans votre fichier .emacs qui initialise votre EMACS.
Si, par exemple, vous voulez dédier la touche <F1> à la fonction d'aide et C-h à la touche <Suppr> (ou Del), vous mettrez dans votre .emacs:
(global-set-key [f1] 'help-command)
(global-set-key "\C-h" 'delete-backward-char)
Mais attention! S i vous voulez faire appel, par exemple, à la fonction 'view-lossage', il ne faudra plus taper C-h l mais <F1> l.
C'est la fonction 'global-set-key' qui permet de lier une clé à une fonction. Sa syntaxe est:
(global-set-key KEY COMMAND)
Notez que, par défaut, la fonction 'global-set-key' n'est pas liée à une clé...
...Mais vous savez, maintenant, comment faire!
Sachez, aussi, qu'il peut y avoir un phénomène d'ombrage (shadowing) si la clé que vous voulez définir est déjà utilisée en liaison locale dans le tampon courant. Et...
... C'est tant mieux!
Les commandes d'évaluation:
C-x C-e
M-x slime-eval-last-expression
Évalue l'expression avant le curseur et affiche le résultat dans la zone mini-tampon.
exemple:
tapez dans le tampon slime-repl:
(car (nthcdr 3 '(a b c d e f)))
Votre curseur étant juste après la dernière parenthèse fermante.
Tapez C-x C-e
D s'affiche dans le mini-tampon.
Déplacez le curseur d'un cran vers la gauche.
Tapez C-x C-e
(D E F) s'affiche dans le mini-tampon.
Déplacez le curseur d'un cran vers la gauche.
Tapez C-x C-e
(A B C D E F) s'affiche dans le mini-tampon.
C'est toujours l'expression qui précède le curseur qui est évaluée.
Le curseur doit toujours être après une parenthèse fermante.
Ceci est utile pour évaluer une expression se trouvant à l'intérieur d'une autre.
C-M-x
M-x slime-eval-defun
Évalue la forme actuelle de niveau supérieur et affiche le résultat dans la zone mini-tampon.
Le raccourci C-M-x peut ne pas être défini dans votre implémentation (mais vous savez comment faire).
Sinon utilisez: M-x slime-eval-defun. Cette fonction traite spécialement les expressions 'defvar'.
Supposons que la variable définie par 'defvar' évolue pendant, disons, un calcul.
Si vous évaluez l'expression 'defvar' avec M-x slime-eval-defun, alors la variable sera réinitialisée à sa valeur initiale.
Vérifions cela sur un cas simple:
Je définis ma variable dans slime-repl:
(defvar *v* 1)
*V*
Je définis une fonction qui fait évoluer ma variable:
(defun new ()
(setq *v* (1+ *v*)))
NEW
Je vérifie la valeur de la variable:
*v*
1
Je fais appel à la fonction plusieurs fois:
(new)
2
(new)
3
(new)
4
Je veux redéfinir ma variable à la valeur initiale (1):
(defvar *v* 1)
*V*
Cela ne marche pas:
*v*
4
Je place le curseur sur defvar et j'active ma fonction d'évaluation:
M-x slime-eval-defun (ou M-x s-e-d en utilisant la touche de tabulation et en completant)
Il ne se passe rien et c'est normal.
Je vérifie la valeur de ma variable:
*v*
1
La variable a bien été réinitialisée. Ouf!
Imaginez une situation de déboggage. Cela peut être très utile de réinitialiser une variable!
Remarque: si C-x C-e reçoit un argument numérique, la valeur rendue par l'évaluation est affichée dans le tampon courant à la suite de l'expression (et non dans le mini tampon).
Pour le vérifier, mettez le curseur à la fin d'une expression.
Tapez:
C-u 2
puis:
C-x C-e
Et constatez.
C-c : ou bien: C-c C-e
M-x slime-évaluation-interactive
Évalue une expression lue dans le mini-tampon.
Exemple:
Tapez: C-c :
Puis une expression: (defvar *v* 1)
Le résultat s'affiche dans le mini-tampon: => *V*
C-c C-r
M-x slime-eval-region
Évalue la région.
Exemple:
Replacez le curseur sur la dernière expression: (defvar *v* 1) et sur le premier astérisque *.
Tapez: C-esp puis C-f C-f C-f (3 fois) pour avancer à la fin du deuxième astérisque.
Tapez: C-c C-r
Vous constatez que la variable *V* a été évaluée (dans le mini-tampon).
Pour désélectionner vous pouvez faire C-w C-y (C-w efface et C-y recopie)
Attention: si la sélection est une expression incomplète, une erreur est signalée.
Notez que ces commandes d'évaluation sont accessibles par le menu:
Quand vous êtes dans le tampon *slime-repl sbcl*, cliquez dans le menu sur SLIME, puis sur Evaluation.
Vous retrouvez les quatre fonctions précédentes.
Vous y trouvez aussi les fonctions 'Eval And Pretty-Print' et 'Eval Region And Pretty-Print' qui font la même chose que:
C-x C-e et C-c C-r respectivement, mais en ouvrant une nouvelle fenêtre pour l'affichage du résultat (au lieu du mini-tampon).
C-c C-p
M-x slime-pprint-eval-last-expression
Évalue l'expression avant le point et affiche le résultat dans un nouveau tampon.
Vous n'êtes pas dans REPL, mais dans un tampon contenant des expressions lisp (ou bien vous êtes en train de définir des fonctions).
Vous pouvez tester vos expressions à tout moment.
C-c E
M-x slime-edit-value
Modifie la valeur d'une forme setf-able dans un nouveau tampon *Edit <form>*. La valeur actuelle est inséré dans un tampon temporaire pour l'édition, vous pouvez alors la modifier, puis elle est défini dans Lisp lors de la validation avec C-c C-c.
Exemple: prenons la forme setf-able 'second'.
Je définis une liste pour ce qui suit:
(defparameter liste '(a b c d))
Je modifie le second élément de cette liste:
(setf (second liste) 5)
Je vérifie:
liste
(A 5 C D)
Je place le curseur à la fin de l'expression (second liste) dans (setf (second liste) 5)
et je demande l'évaluation avec:
C-c E
Je valide Ce qui s'affiche dans le mini_tampon.
Une fenêtre s'ouvre en affichant 5.
Je rectifie la valeur affichée: 5 --> 7
Et je valide avec C-c C-c.
Je vérifie:
liste
(A 7 C D)
Le deuxième élément a bien été modifié.
Quand le curseur se trouve dans une définition, vous pouvez faire appel à la fonction ainsi définie:
(vous êtes toujours dans le tampon *slime-repl sbcl*)
Ouvrez le menu SLIME-->Evaluation-->Call Defun
Entrez, éventuellement, les arguments et validez.
Ceci est pratique pour tester la fonction que vous voulez définir.
SAUVEGARDE D'UN TRAVAIL.
C-x C-f
Permet de créer un nouveau fichier.
Exemple:
Supposons que que nous soyons dans REPL.
Vous venez de programmer une nouvelle fonction. Disons:
(defun salutations ()
(format t "Bonjour tout le monde."))
Vous voulez enregistrer cette fonction dans un fichier nommé "salut.lisp".
Ceci est nécessaire si vous voulez réutiliser cette fonction dans une prochaine session SLIME.
Car en quittant SLIME toutes vos définitions s'effacent!
Donc, copiez (dans REPL) la dite fonction: sélectionnez le texte et M-w.
Alors tapez:
C-x C-f
Puis dans le mini-tampon:
salut.lisp
Un nouveau tampon nommé "salut.lisp" souvre dans le mode "Lisp adoc [COMMON-LISP-USER sbcl]".
C-y Pour coller la fonction.
Remarquez que l'indentation n'est pas forcément correcte.
Tapez <ENTREE>
Et la fonction est réindentée convenablement.
A ce stade, vous pouvez évaluer et compiler la définition:
C-c C-c
Pour revenir dans RPEL, tapez:
C-c C-z ou C-x b
Un message vous indique que la fonction a été compilée.
; compiling (DEFUN SALUTATIONS ...)
WARNING: redefining COMMON-LISP-USER::SALUTATIONS in DEFUN
De plus, le message indique que la fonction est redéfinie si on l'avait déjà définie dans REPL.
Maintenant, vous pouvez utiliser votre fonction compilée:
(salutations)
Bonjour tout le monde.
NIL
Si vous voulez modifier votre fonction, ou bien en définir une autre, tapez à nouveau:
C-x b
Le mini-tampon vous propose de basculer vers un autre buffer (tampon) et par défaut le tampon "salut.lisp".
Tapez <ENTREE> et vous êtes de nouveau dans le tampon "salut.lisp".
Ajoutons une documentation à notre fonction "salutations" et regardez ce qui se passe dans le mini-tampon:
Une indication montre comment doit être utilisée la fonction defun (de même avec la fonction format).
(defun salutations ()
"Affiche des salutations au monde qui nous entoure."
(format t "Bonjour tout le monde."))
Et définissons une deuxième salutation:
(defun salutations2 ()
"Salutations du soir aux spectateurs de la salle."
(format t "Bonsoir Mesdames et Messieurs."))
A ce niveau, vous recompilez avec:
C-c C-c
Le mini-tampon vous dit que la compilation est terminée, qu'il n'y a pas d'erreur, et donne le temps de la compilation.
Puis, pour retourner dans RPEL:
C-x b et <ENTREE>
Notez bien que:
-la fonction salutations a été évaluée.
-la fonction salutations2 a été compilée.
Essayons cette 2ème fonction:
(salutations2)
Bonsoir Mesdames et Messieurs.
NIL
Testons la documentation des deux fonctions:
(documentation 'salutations 'function)
NIL
(documentation 'salutations2 'function)
"Salutations du soir aux spectateurs de la salle."
La documentation de la 1ère fonction n'a pas été prise en compte (cette fonction était déjà compilée).
La documentation de la 2ème fonction est bien prise en compte.
Cela s'explique! Car le curseur dans le tampon salut.lisp se situait après la définition de la 2ème fonction. Donc, seule, la 2ème fonction est compilée.
Pour recompiler la 1ère fonction, mettez le curseur sur la 1ère définition ou à la fin de cette définition.
Puis:
C-c C-c et C-c C-z
Et tout devrait rentrer dans l'ordre. Essayez!
(documentation 'salutations 'function)
"Affiche des salutations au monde qui nous entoure."
Comme nous sommes très contents de ce travail, nous allons enregistrer le fichier salut.lisp pour pouvoir le réutiliser par la suite.
Revenez dans le tampon "salut.lisp" et tapez:
C-x C-s
Si vous quittez SLIME, pour retrouver vos fonctions il faudra ouvrir une nouvelle session SLIME et charger le fichier salut.lisp.
__________
Remarques: le chargement se fait, normalement avec (load "...").
Mais il se peut que cela ne marche pas. Une des raisons est qu'il n'est pas enregistré dans le répertoire courant.
Après une recherche, Je l'ai trouvé dans le répertoire racine ~. Mais le nom du fichier était #salut.lisp#.
J'ai pu le recharger en faisant:
(load "~/#salut.lisp#")
Les deux fonctions étaient bien fonctionnelles.
En voulant fermer le tampon salut.lisp, j'ai perdu toute trace du fichier (donc définitivement).
On peut en déduire que #salut.lisp# est un nom temporaire qui tombe dans le garbage collector à la fermeture.
Ce Ramasse-miettes peut-il intervenir sur le disque dur? Probablement pas.
Donc si vous voulez sauvegarder correctement votre fichier, précisez le répertoire, donc le chemin complet (ce répertoire peut-être proposé dans le mini-tampon).
__________
Ouvrez le tampon salut.lisp:
File-->OpenFile
Et dans le mini-tampon:
~/votre/chemin/salut.lisp
Vous pouvez ajouter d'autres fonctions dans votre tampon actuel.
Pour compiler et charger les fonctions dans REPL, tapez:
C-c C-k
Basculez dans le tampon REPL et constatez:
; compiling file "/home/trochet/LISP/Clisp/salut.lisp" (written 11 OCT 2020 02:59:33 PM):
; /home/trochet/LISP/Clisp/salut.fasl written
; compilation finished in 0:00:00.007
Le fichier a été entièrement compilé (on vous indique la date et l'heure).
Un fichier salut.fasl a été créé (vous devez le retrouver a côté du fichier salut.lisp.
Ce fichier pourra être chargé dans REPL de la façon suivante:
(load "/home/trochet/LISP/Clisp/salut.fasl")
La compilation a été effectuée en 7/1000 de seconde.
...Et vos fonctions sont utilisables dans REPL.
Remarque: vous avez utilisé C-c C-k dans le tampon salut.lisp, et pourtant si vous demandez:
C-c C-d C-d, puis C-c C-k, le mini-tampon vous répond que ce raccourci n'est pas défini!
Ceci n'est peut-être pas vrai dans toutes les implémentations.
COMPILATIONS PARTICULIÈRES des précédents raccourcis.
C-u C-c C-c
Compile une forme avec un maximum de débogage.
M-- C-c C-c
Compile une forme pour gagner en vitesse.
C-u C-c C-k
Compile un fichier avec un débogage maximal.
M-- C-c C-k
Compile un fichier pour accentuer la vitesse.
C-c M-k
Compile le fichier source du tampon actuel, mais ne le charge pas.
C-c C-l
M-x slime-load-file
Charge un fichier Lisp ou fasl. Cette commande utilise la fonction Common Lisp LOAD.
On utilise, de cette façon, le mini-tampon qui propose le chemin actuel et on se sert de la complétion pour écrire le fichier.
Exemple:
Redémarrer SLIME:
,(virgule) puis dans le mini-tampon: quit
M-x slime
C-c C-l
Dans le mini-tampon:
Load file: ~/LISP/Clisp/
ajouter: salut.fasl
Le fichier compilé est ajouté dans REPL.