Leximnesia.org

Tutriel : afficher de la documentation PHP hors ligne avec GoldenDict

19/08/2016

Avant-propos

GoldenDict

GoldenDict est une application de dictionnaire indépendante et libre qui permet d’interroger des dictionnaires. On pourrait croire que c’est pareil qu’un grand nombre d’autres applications similaires, mais GoldenDict possède des atouts de taille :
  • il est beaucoup plus rapide qu’un navigateur classique (Firefox par exemple) pour charger et afficher une page Wikipédia ou autre : on gagne du temps
  • son interface très bien conçue et ses raccourcis clavier sont très pratiques : Ctrl+F11+F11 permet par exemple de faire surgir la fenêtre (autrement réduite dans la barre des tâches), pas besoin de cliquer dans un champ de recherche pour taper…
Ça fait déjà longtemps que je l’utilise pour la traduction (comme dictionnaire monolingue ou bilingue) mais aussi pour consulter Wikipédia rapidement quand j’en ai besoin.

PHP

Je programme beaucoup en PHP actuellement, mais ce n’est pas mon langage préféré. J’ai souvent besoin de me documenter sur des fonctions assez basiques, mais je ne connais pas toujours leur nom exact.

Dans un premier temps, quand j’avais une recherche de ce genre à faire, je tapais sur Google ce que je cherchais à faire et j’obtenais plus ou moins rapidement une réponse en fonction de la pertinence des termes recherchés.

Ensuite, j’ai téléchargé une version hors ligne de la documentation de PHP, qui, il faut le reconnaître, est d’une qualité remarquable. À ce moment, dès que j’avais du PHP à chercher, j’ouvrais un onglet dans le navigateur, je retrouvais l’index des fonctions dans mes marque-pages, je cherchais dans la page les mots-clés qui m’intéressaient et je cliquais sur le nom de la fonction une fois trouvée. C’était plus satisfaisant qu’avec Google, mais toujours pas assez rapide !

C’est là que j’ai eu l’idée d’utiliser GoldenDict. J’ai d’abord cherché si quelqu’un avait déjà compilé une documentation PHP dans un format exploité par GoldenDict, mais sans résultat.

Utiliser des programmes comme sources dans GoldenDict

Plutôt que de compiler moi-même la documentation, j’ai choisi d’utiliser une autre option de GoldenDict : l’affichage de la sortie de lignes de commandes.

Pour ça, il fallait

  • créer un programme adéquat en ligne de commande (j’ai choisi python) – j’y reviendrai
  • configurer GoldenDict pour utiliser ce programme

Dans la configuration des dictionnaires-sources de GoldenDict (F3), on va dans l’onglet "Programs" et on ajoute non pas une, mais deux entrées :

  • la première va nous permettre d’obtenir des suggestions en cours de frappe dans la barre de recherche
    • la ligne de commande est : python chemin/d/acces/getphpdoc.py list %GDWORD% et est de type "Prefix Match"
  • la seconde permettra l’affichage de la documentation d’une fonction précise
    • la ligne de commande est : python chemin/d/acces/getphpdoc.py show %GDWORD% et est de type "HTML"

Les deux lignes de commande appellent donc le même programme et ne diffèrent que par le premier paramètre passé : "list" pour les suggestions, "show" pour l’affichage.

Le programme python en question

Le programme lui-même est extrêmement simple, car il se contente de sortir le contenu d’un fichier de la la documentation PHP téléchargée ou de sortir des noms de fonctions extraits de l’index des fonctions.

La seule partie un peu complexe a été d’extraire du fichier HTML d’index les informations d’index.

n);}}, 1000);})('//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/highlight.min.js','//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/styles/default.min.css','http:')"> #!/usr/bin/python2 # -*- coding: utf-8 -*- """ © Florian MORTGAT """ import os, sys import re from _getphpdoc_indexdata import funcIndex # funcIndex is a dictionary of the following form: # funcIndex = { # 'funcName': ('docfile.html', 'description'), # 'str_replace': ('function.str-replace.html', 'Replace all occurrences of the search string with the replacement string'), # 'array_push': ('function.array-push.html', 'Push one or more elements onto the end of array') # } # It has been extracted from indexes.functions.html using some regexes # bdir = '/home/florian/Documents/documentation info/php/manual/php-chunked-xhtml' os.chdir(bdir) class O:'' G=O() USAGE="""Usage: getphpdoc.py [MODE] [QUERY] MODE:   list  prints a list of all functions whose name partially         matches QUERY.   show  prints the documentation of the function specified in         QUERY or, if not found, a list of partially matching         functions. QUERY:   QUERY is the name of the function to display or the first   letters of that name (or even a regular expression). """ SUGGEST_LIMIT = 50 def main (): try: action = sys.argv[1] q = sys.argv[2] except: print USAGE return if action=='list': # list entries starting with 2nd arg n=0 for name in sorted (funcIndex): if n >= SUGGEST_LIMIT: break if re.match ('^'+q, name): print name n+=1 elif action=='show': # show entry # if q is a file, print it if os.path.isfile (q): print open (q,'r').read () # if it is a whole function name, print it elif q in funcIndex: filename,desc = funcIndex[q] if os.path.isfile (filename): print open (filename,'r').read () else: print "file not found: %s"%filename # if it is a partial function name, print suggestions else: print '<pre style="font-size:130%;font-family:arial">' print 'requested: "%s"n'%q for name in sorted (funcIndex): if re.search (q, name): filename, desc = funcIndex[name] print '<a href="%s">%s</a>: <span style="font-size: 70%%">%s</span>'%( filename, name, desc) if __name__ == "__main__": try: main () except KeyboardInterrupt: print ("Leaving: User typed Ctrl+C")

La route du copyvio involontaire

  • Étape 1 : vous commencez à compiler des infos pour vos besoins strictement personnels (par exemple, vous vous constituez un glossaire).
  • Étape 2 : dans ce glossaire, qui n’est destiné qu’à votre usage privé, vous ne vous souciez pas trop d’indiquer vos sources, et n’hésitez pas à recopier des informations provenant d’ouvrages soumis au droit d’auteur (encore une fois, c’est totalement admissible pour un usage personnel uniquement). Vos sources sont très diverses : parfois, c’est votre propre travail, parfois, c’est tel journal, parfois, tel site Web, etc.
  • Étape 3 : un beau jour, vous vous rendez compte que votre œuvre est vraiment chouette, pratique, classe, bref, que ce serait dommage que vous seul en profitiez alors que le monde assoiffé de connaissance crie famine, plongé qu’il est dans son obscurantisme. Ni une, ni deux, généreux comme vous l’êtes, vous mettez en ligne votre travail sous une licence CC, GFDL ou autre.

Et Paf le chien. Ben oui, à présent, vous avez commis un copyvio, alors que vous n’en avez jamais eu l’intention, et qu’en plus, vous avez fait un véritable travail.

Autre problème avec ce procédé : la fiabilité. Si une de vos sources s’avère pourrie après-coup, vous ne pourrez jamais nettoyer à fond votre recueil.

Pour éviter ça, mettez toujours une mention (même minimale) de la source dans chacune de vos entrées. Plus tard, vous pourrez ainsi faire le tri entre le fiable et le moins fiable, entre le copyrighté et ce qui vous appartient. J’ai pris ce réflexe (la plupart du temps, j’écris juste le prénom de la personne qui m’a donné la terminologie, le nom d’un journal ou une abréviation, plus rarement une URL entière). En tout cas, je ne le regrette pas du tout : à présent, je suis sûr de ne publier que de la terminologie "clean".

Petit truc pour utilisateurs de GNU/Linux ou autres Unixes

18/10/2013

En tant qu’interprète ou traducteur, on est sans cesse amené à noter du vocabulaire ou des trucs sur des petits bouts de papier, sur son PDA, sur son téléphone ou dans divers fichiers temporaires de son ordinateur. Et c’est vite le bazar : une grande partie de ces notes ne seront jamais recopiées dans votre base de données terminologique centralisée (si vous avez la chance d’en avoir une).

Pourquoi ne pas entrer directement ces informations dans la BDD ? Tout simplement parce que ça prend beaucoup trop de temps si vous êtes concentré sur autre chose au moment où vous devez noter l’info (en réunion par exemple). Même si sur votre ordinateur, vous avez prévu un fichier tampon dans lequel vous mettez ce genre de notes, le chercher puis l’ouvrir peut parfois prendre trop de temps.

J’ai eu une idée pour régler (plus ou moins) ce problème. Tout d’abord, je dois reconnaître que

  1. cette solution n’est pas le remède ultime car elle nécessite quand même l’ordinateur
  2. elle ne casse pas trois pattes à un canard : plus basique, tu meurs
  3. elle est bordélique (certes, mais largement moins que ce qu’elle remplace).
Mais elle est quand même suffisamment pratique pour mériter une entrée de blog. En fait, elle est très pratique.

Cette solution se base sur des outils assez standards : bash, grep, zenity et mousepad (qui peut être remplacé par n’importe quel éditeur, soit dit en passant).

Mode d’emploi :

  1. (facultatif, je le laisse pour la compréhension) créez ~/.my_log (touch ~/.my_log)
  2. si ce n’est fait, créez ~/bin (ou si vous préférez ~/.local/bin, ça m’est égal) et ajoutez-le à votre $PATH
  3. créez ~/bin/my_log_append et rendez-le exécutable
  4. créez ~/bin/my_log_find et rendez-le exécutable
  5. remplissez my_log_append et my_log_find (contenu ci-dessous)
  6. créez des raccourcis clavier dans votre gestionnaire de bureau pour my_log_append et my_log_find (j’ai choisi respectivement Win+L et Win+Maj+L, mais vous faites comme vous voulez)

Contenu de my_log_append :

#!/bin/bash logfile="$HOME/.my_log" date=`date` text=`zenity --entry --text="Écris qqch."` && echo "$date" >> "$logfile" && echo "$text" >> "$logfile"

Contenu de my_log_find :

#!/bin/bash myeditor="mousepad" logfile="$HOME/.my_log" if [ $# -eq 0 ]; then arg=`zenity --entry --text="Recherche dans le journal"` else arg="$*" fi grep -i "$arg" "$logfile" > /tmp/logfindresult.dic && $myeditor /tmp/logfindresult.dic

À présent, quand vous êtes devant un film et que tout à coup, vous voulez noter rapidement que apple = pomme, tapez Win+L, apple = pomme, validez et c’est tout ! Zéro clic de souris, zéro usine à gaz.

Plus tard, si vous êtes plongé dans une traduction ardue et que vous rencontrez ce terme difficile, apple, que vous êtes sûr d’avoir déjà noté quelque part, tapez Win+Maj+L, apple, validez. La liste de toutes les lignes de votre fichier bazar qui contiennent apple (y compris celle que vous aviez ajoutée, apple = pomme) s’affiche. Fermez la fenêtre et traduisez.

Certes, ça n’a pas la sophistication d’une bonne base de données, mais rien ne vous empêche, plus tard, quand vous aurez le temps (haha), de recopier les entrées de ~/.my_log dans votre superbe base de données centralisée.

Conseil utile : essayez de systématiquement indiquer la source de l’info entre parenthèses quand vous rajoutez une entrée. Plus tard, ça peut vous sauver la vie quand vous essayerez de déterminer la fiabilité ou le droit d’auteur de telle ou telle entrée.

Vous allez me dire que ma solution est un fichier tampon, que je décriais il y a une minute. Oui, certes, mais la façon d’y accéder est différente : en utilisant un éditeur de texte classique pour ajouter une ligne, vous devez 1) attendre que l’éditeur se charge (c’est forcément plus long qu’avec zenity) et 2) aller à la fin du fichier et éventuellement passer à la ligne. Ensuite, quand vous tapez votre ligne, vous avez le reste du fichier qui peut vous déconcentrer. D’accord, tout ça fait perdre très peu de temps (de l’ordre d’une ou deux secondes maxi) mais c’est déjà trop de temps. Ma solution est rapide.

Le langage Go

10/02/2013

En 2010, je disais que ma hantise de programmeur était la distribution d’une version Windows de mon logiciel. Cela n’a pas beaucoup changé, mais peut-être que le langage Go (aussi appelé « golang » pour l’indexation dans les moteurs de recherche) va m’aider.

Le Go est un langage compilé qui essaye de ressembler à un langage interprété. Il intègre par défaut des types modernes et pratiques. Mais surtout, il est extrêmement facile de mettre en place un environnement de programmation Go sous Windows, et du premier coup, on obtient un beau fichier .exe qui fonctionne !

Côté Linux, l’environnement est assez vite mis en place (même si l’outil de gestion de révision préféré est Git, qui fonctionne mal chez moi). Bonne surprise : d’excellents fichiers Vim sont disponibles : pas la peine d’utiliser un gros IDE, on se sent chez soi !

Du côté des freins, je compte :

  • la difficulté de se remettre à un langage compilé (le typage statique et les conversions explicites sont encore un peu difficiles pour moi).
  • l’absence (pour l’instant) d’un GUI multiplateforme mûr (Go est fait pour programmer des serveurs, et c’est la solution que je choisirai même si je trouve ça un peu dommage parfois)
  • le compilateur très strict (il refuse de compiler un code avec des bibliothèques ou des variables inutilisées)

Par contre, j’ai été surpris par la réactivité des utilisateurs (qui sont encore peu nombreux, jeunesse oblige). J’ai posé quelques questions de débutant sur IRC et la réponse précise et patiente est arrivée dans les secondes qui ont suivi. Ah, et j’oublie bien sûr de mentionner tous les outils de documentation sans lesquels j’aurais abandonné rapidement (le GoTour est un magnifique didacticiel). La syntaxe permet un code lisible mais déroute un peu au début. Son système d’interfaces qui remplace la POO est loin d’être idiot. Son choix de l’UTF-8 est excellent (même si c’est un peu dommage que certaines bibliothèques – je pense à encodings/csv – partent du principe que les fichiers à lire sont encodés en UTF-8, ce qui n’est pas forcément le cas et peut provoquer des bugs).

Go vs. Python

  • Le Go est plus rapide car compilé. (Go : avantage léger)
  • Le Go peut compiler des binaires pour Windows. (Go : avantage décisif)
  • Le Python est plus riche, plus beau et permet un plus grand choix de bibliothèques natives. (Python : avantage léger)
  • Le Python est introspectif (on peut explorer les objets puisque c’est interprété). (Python : avantage important)
  • Le Go est libre et son code source bien écrit et facile à trouver. Le Python est libre et son code source est bien écrit et facile à trouver. (égalité)
  • Le Go est encore peu utilisé (même si Google, c’est pas n’importe qui). Le Python est très populaire parmi les scientifiques et les entreprises d’informatique (la NASA non plus, c’est pas le premier venu). (Python : avantage léger)

Go vs. C/C++

  • Le Go est sans doute moins rapide, mais c’est négligeable.
  • Le Go produit des exécutables avec la runtime liée statiquement → les exécutables sont plus lourd, mais c’est pratiquement négligeable pour moi. (C : avantage)
  • Développer en C/C++ sous Windows requiert les droits d’administrateur et l’installation d’une grosse machine de guerre. En Go, il suffit de dézipper une archive, certes un peu lourde, mais rien comparé aux dinosaures. (Go : gros avantage)
  • Le C++ impose sa POO rigide et verbeuse (on passe son temps à coder des getters/setters à moins de faire faire ça par un IDE, ce que j’abhorre). Pour les codeurs hors pair, ce n’est peut-être pas un problème (ça oblige à bien programmer). Le Go, avec ses interfaces, est très flexible. (Go : gros avantage)
  • Pour apprendre le C, il existe des milliers de cours et on ne sait pas lequel choisir. Pour apprendre le Go, il n’y en a qu’un, presque parfait : le GoTour. (Go : bel avantage)
  • Le C n’est pas lié à une entreprise et on peut être pratiquement sûr qu’aucune surprise ne se cache dans GCC. Le Go est lié à Google (sans lui appartenir – c’est un logiciel libre) et il faut avoir confiance. De plus, si un jour Google se met à « doer du évil », le Go deviendra lingua non grata chez les programmeurs. Le C restera toujours le C. (C : avantage modéré)

Papier ou livre en e-paper ?

24/01/2011

Le livre électronique, actuellement, comporte

  • Un écran en papier électronique (le papier lui-même ne comporte pas de composants électroniques, mais en dessous de cette "feuille", il y a une grille électronique qui sert à effacer l’encre électronique ou à écrire avec.
  • Un petit ordinateur sur batterie (une mémoire pour le système d’exploitation, l’application de lecture d’e-book et les livres eux-mêmes)

Comparaison

Écologie : Le livre électronique coûte cher par rapport au matériel impliqué et sa durée de vie est courte (probablement moins de 5 ans). On ne coupe pas directement d’arbres pour le fabriquer, mais comme il y a quand même pas mal d’électronique dedans, et je doute que sa fabrication soit très écologique. Le livre en papier traditionnel, lui, nécessite de couper des arbres qui, souvent, « proviennent de forêt gérées durablement et d’autres sources contrôlées » (la personne qui a trouvé cette formulation devrait recevoir le prix Nobel du marketing). Bref, c’est pas très écologique non plus, mais la durée de vie est très souvent supérieure à 20 ans (certains livres sont même encore manipulables par une personne un peu soigneuse après 80 ans). Et puis c’est du carbone immobilisé jusqu’à ce que vous les brûliez (ou jetiez dans le mauvais bac) ! (oubliez cet argument, c’était pour rire) → gagnant : livre papier

Poids : là, la balance penche en faveur du livre électronique actuel (haha) : il est beaucoup plus léger qu’un seul bouquin de 500 pages, sans parler du fait qu’il peut transporter l’équivalent de bibliothèques entières. Si vous devez transporter cinq livres et que vous n’avez pas besoin de les ouvrir simultanément, un seul livre électronique pourra les remplacer et tenir dans votre poche. → gagnant : livre électronique

Autonomie : un livre électronique neuf n’a pas besoin d’être rechargé très souvent, mais les batteries s’essoufflent après une ou deux années d’utilisation (en raison de leur faible qualité – il existe des batteries autrement plus durables), et ça devient un problème par rapport au papier qui n’a pas besoin d’électricité. → gagnant : livre papier

Lisibilité : la lisibilité du livre électronique est, à lumière égale et à taille du texte égale, largement inférieure à celle du papier. Par contre, les personnes ayant une mauvaise vision apprécieront la possibilité de grossir le texte. → gagnant : aucun

Mise en page : la plupart des livres papier ont une mise en page parfaite. En théorie, c’est tout aussi possible pour les livres électroniques, mais en pratique, c’est rarement le cas. Les blocs de textes manquent d’harmonie, la coupure des mots ne se fait pas ou pas au bon endroit, etc. → gagnant : livre papier

Manipulation : un livre en papier ne met pas 30 secondes à démarrer, si on cherche à l’ouvrir à environ la moitié, on peut le faire sans passer par d’obscurs menus, et on peut facilement évaluer sa longueur et l’endroit où on est en regardant son épaisseur (même si c’est peu précis). Sur le livre électronique, on a des informations très précises mais moins "parlantes" et qui nécessitent que le livre soit allumé. Pour votre entourage, ça peut aussi être embêtant : si vous tenez un livre électronique dans les mains, à moins de regarder par dessus votre épaule, personne ne peut savoir si vous lisez Proust ou bien le manuel d’utilisation d’une machine à laver. La taille des livres électroniques leur donne toutefois quelques avantages. → gagnant : livre papier

Simplicité : Pour utiliser un livre papier, il suffit de savoir lire et d’avoir des mains et des yeux en bon état. Pour le livre électronique, il faut des connaissances (ne serait-ce que pour éviter les incompatibilités de formats, sachant que les e-éditeurs cherchent à tout verrouiller). Je ne m’étendrai pas là-dessus. → gagnant : livre papier

Contenu et prix. Là, le papier électronique a des avantages en théorie : un texte électronique peut se copier en des milliers d’exemplaires et être envoyé à l’autre bout de la planète en quelques secondes, pour un coût énergétique très faible (vu que les infrastructures existent déjà). Il devrait donc être vendu beaucoup moins cher… mais en pratique c’est rarement le cas. On constate souvent des prix élevés (et je doute que ça serve à rémunérer l’auteur, en particulier quand ce dernier est déjà mort). La diversité des contenus disponibles laisse encore beaucoup à désirer : même si les catalogues numériques s’enrichissent vite, il y a énormément de livres passionnants qu’on ne trouvera pas dedans. Là où le livre électronique se démarque, c’est que n’importe quel texte que vous avez tapé ou trouvé sur Internet peut assez facilement être transformé en livre électronique, et Internet est plein de textes intéressants (de la recette de cuisine au récit d’expédition dans la jungle par un entomologiste amateur). → gagnant : livre papier, à nuancer

Mon expérience

J’ai acheté un livre électronique (un Cybook Gen3 de Bookeen), il y a un peu plus d’un an.

Ce que j’ai trouvé génial, c’est :

  • de pouvoir lire Moby Dick et quelques autres livres confortablement et en version originale sans payer 15 € (mais j’ai déboursé près de 250 € pour la machine, donc oubliez la rentabilité, c’est bien plus une satisfaction psychologique)
  • de pouvoir faire mes traductions sur ordinateur sans avoir d’imprimante : je les apporte en cours sur le livre électronique et je prends la correction sur une feuille de papier séparée.
  • de pouvoir lire mes cours dessus sans avoir à les imprimer.

Ce que j’ai trouvé nul, c’est :

  • le petit bug dans l’application de lecture de PDF qui fait planter l’appareil sur certains PDF (heureusement, ce bug est toujours le même et il y a toujours un moyen de génerer un PDF très légèrement différent qui ne posera pas ce problème).
  • les formats incompatibles : soit on a droit à ePub, soit à mobipocket, mais pas les deux à la fois. Et si on choisit l’ePub, les images des PDF sont moins bien affichées (car l’application est elle aussi différente).
  • la batterie qui a perdu 50% de sa capacité au bout de 8 mois, et qui est maintenant totalement morte après 1 an et 3 mois d’utilisation, malgré une utilisation parfaitement normale et précautionneuse de l’appareil.

Conclusion

Le principe d’un papier où l’encre se réorganise électroniquement est excellent en soi. Les avantages du texte numérique sur le texte imprimé sont immenses. Le principal inconvénient du livre électronique est la nécessité d’associer un matériel électronique à chaque page d’e-paper. J’aimerais bien qu’apparaîssent des imprimantes dédiées et qu’on puisse acheter 200 feuilles d’e-paper qu’on "imprimerait" et relierait pour les lire ensuite tranquille. On perdrait certains avantages tels que la possibilité de changer de document quand on est en déplacement, ou bien la légèreté. Et encore, on peut imaginer des "imprimantes électroniques" qui tiendraient dans la poche, même si la vitesse d’impression s’en ressentirait.

Il y a sûrement des applications possibles au livre électronique (pour les personnes malvoyantes en particulier), mais vu son prix de vente actuel et sa durée de vie (au moins en ce qui me concerne), l’intérêt est faible.

Le plus dur…

18/11/2010

Le plus dur lorsqu’on crée un logiciel comme Leximnesia, ce n’est pas la programmation en elle-même. C’est la distribution. Voilà pourquoi je fais maintenant du JavaScript.

Leximnesia est gratuit, libre, même, et suscite un certain intérêt quand j’en parle. Pourtant, presque personne ne le télécharge. Pourquoi ? C’est simple : la motivation et/ou les compétences pour installer un logiciel dont on ignore si l’on va vraiment s’en servir manquent.

Depuis près de quatre ans, j’ai fait beaucoup d’efforts pour rendre Leximnesia facile à installer (en changeant 6 fois d’outils de programmation). J’ai aussi envisagé de changer de langage car bien que le python soit de loin mon préféré, il n’est pas encore très répandu dans les PME, et encore moins chez les particuliers (ma “cible”). J’ai envisagé d’apprendre le Java ou de me remettre au C, mais ça m’aurait pris trop de temps.

Dans la toute dernière version (janvier 2011), j’utilise presque exclusivement JavaScript, et Leximnesia se présente sous forme de page Web. Ça simplifie énormément les choses (l’utilisateur n’a plus qu’à rentrer une URL dans le navigateur de son ordinateur, voire de son mobile), mais avec des inconvénients assez lourds pour une utilisation régulière (pas de sauvegarde possible par exemple).

Je suis toutefois très content, car l’apprentissage de JavaScript a été très rapide (grâce à Freenode et Eloquent JavaScript). Mon code n’est pas très agréable à lire (ce qui s’explique par la vitesse à laquelle je l’ai écrit), mais je pourrai le reprendre quand j’aurai un peu de temps. Le concept du “tout javascript” est assez anti-accessibilité et peu conforme aux bonnes pratiques du Web, mais comme je continue à distribuer et développer la version python, les puristes y trouveront plus qu’une alternative. De plus, le code python est bien écrit, assez clair et assez bien structuré.

Design et site: Florian Mortgat
Moteur wiki dérivé de: Wikiss
Page modifiée le: 19 Aug 2016
fr en de
cached
edit topics  edit subpage menu
Your public IP: 44.220.251.236