Voici quelques expérimentations faites alors que je voulais explorer les documentations contenues dans Pharo. Dans ce billet nous verrons comment ressortir les commentaires des classes d'un package donné. Puis je décrirai le codage d'une application Seaside minimaliste pour visualiser cette documentation depuis un navigateur Web.
1. Voyage au centre du package
Les classes sont regroupées dans des packages gérées par
Monticello. On peut faire l'analogie avec les
gems du monde
Ruby ou les gestionnaires de paquets des distributions Linux.
Chaque package étant une instance de la classe
MCPackage, on peut en sortir la liste. Ouvrez un
Workspace et affichez le résultat du code suivant (via click-droit,
print it)
MCPackage allInstances
Cela devrait vous retourner une longue liste de packages:
Comptons en le nombre en évaluant la taille du tableau retourné:
MCPackage allInstances size.
Sur mon image je trouve 155 packages.
Chaque package a un nom via l'accesseur name. On peut ainsi en sortir la liste:
MCPackage allInstances collect: [:p| p name]
En triant par ordre alphabétique:
(MCPackage allInstances collect: [:p| p name]) sort
Affichons le tout dans un Transcript. Ouvrez-le via le menu World > Tools > Transcript.
Puis évaluez le code suivant dans le Workspace:
|packageNames|
packageNames := MCPackage allInstances collect: [:p| p name].
packageNames sort do:[:name| Transcript show:name; cr]
Les objects PackageInfo référencent toutes les classes d'un package. Chaque objet MCPackage est associé à un objet PackageInfo.
Prenons par exemple le premier package et affichons toutes les classes qu'il contient via l'accesseur classes:
MCPackage allInstances first packageInfo classes
Pour extraire toutes les classes d'un package donné, une petite sélection fait l'affaire. Le code suivant renvoie toutes les classes du package System-Tools:
|systemTools|
systemTools := (MCPackage allInstances select: [:p| p name = 'System-Tools']) first.
systemTools packageInfo classes.
On peut accéder au commentaire de chaque classe via l'accesseur comment. Affichons le commentaire de la classe SpaceTally dans un Transcript:
Transcript show:SpaceTally comment
De là à afficher toutes les classes d'un package avec leurs commentaires, il n'y a qu'un pas:
|systemTools|
systemTools := (MCPackage allInstances select: [:p| p name = 'System-Tools']) first.
systemTools packageInfo classes do:[:c|
Transcript show: '***',c name; cr.
Transcript show: c comment; cr; cr]
2. Application Seaside pour consulter les commentaires
Rajoutons maintenant un peu de bling-bling à tout ça. Un Transcript c'est bien, une page web c'est plus rigolo.
Créons le package SimpleWebDoc qui contiendra une application Seaside minimaliste permettant de parcourir les commentaires des classes des packages.
Le navigateur de classes utilisé par défaut est
Browser (pour des raisons de performances et stabilité), or je vais utiliser le
Package Browser. Pour changer le navigateur par défaut, ouvrez le navigateur de classe et dans le menu de la fenêtre sélectionnez
Choose new default Browser.
Ici sélectionnez O2PackageBrowserAdaptator.
Lancez un nouveau navigateur de classe, vous devriez obtenir le Package Browser.
Ajoutons maintenant le package SimpleWebDoc: click droit, create package.
Nouveau clic droit sur le package et choisissez various > add to smart groups pour le rajouter dans l'onglet groups du Package Browser.
Créer application Seaside nécessite d'hériter WAComponent et de l'enregistrer comme application. Voici la déclaration de la classe SWDocView:
WAComponent subclass: #SWDocView
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'SimpleWebDoc'
Pour afficher un composant, Seaside lui envoie le messager
renderContentOn: en lui passant un objet
WARenderCanvas sur lequel
dessiner notre page web (
en utilisant des brosses/brush). Nous allons ici construire un formulaire affichant tous les packages:
renderContentOn: html
html form: [
html select
list: (MCPackage allInstances collect: [:p| p name])
].
Améliorons la lisibilité du code en créant
allPackageNames qui retourne les noms de tous les packages, dans l'ordre alphabétique:
allPackageNames
^ (MCPackage allInstances collect: [:p| p name]) sort
et ajustons
renderContentOn: en conséquence:
renderContentOn: html
html form: [
html select
list: self allPackageNames;
].
Testons ce que donne ce premier code. Déclarez le composant
SWDocView comme application en évaluant ce qui suit dans un
Workspace:
SWDocView registerAsApplication: 'simple-web-doc'
Pointez ensuite votre navigateur Web à l'adresse:
http://localhost:8080/seaside/simple-web-doc
Ajoutons un bouton pour valider le formulaire:
renderContentOn: html
html form: [
html select
list: self allPackageNames;
html submitButton with:'show'
].
Maintenant la partie intéressante: lorsqu'on valide le formulaire, on affiche la documentation du package. Pour cela nous stockons le nom sélectionné dans la variable d'instance
selectedPackage en utilisant le callback de la brosse
WASelectTag:
renderContentOn: html
html form: [
html select
list: self allPackageNames;
callback: [:value| selectedPackage := value].
html submitButton with:'show'
].
Si
selectedPackage est définit, affichons la documentation:
renderContentOn: html
html form: [
html select
list: self allPackageNames;
callback: [:value| selectedPackage := value].
html submitButton with:'show'
].
selectedPackage ifNotNil: [
self renderPackage:selectedPackage On:html.
]
La méthode
SWDocView>>renderPackage:On: qui reprends l'exemple précédent:
renderPackage:packageName On:html
|package|
package := (MCPackage allInstances select: [:p| p name = packageName]) first.
package packageInfo classes do: [:c|
html heading level:2; with: c name.
html break.
html text: c comment.
html horizontalRule.
]
et voici le résultat:
Amenons un peu de lisibilté en écrivant une méthode qui retourne toutes les classes d'un package:
classesOfPackageNamed: packageName
|package|
package := (MCPackage allInstances select: [:p| p name = packageName]) first.
^ package packageInfo classes
d'où une mise à jour de
renderPackage:On:
renderPackage:packageName On:html
(self classesOfPackageNamed:packageName) do: [:c|
html heading level:2; with: c name.
html break.
html text: c comment.
html horizontalRule.
]