GeSHi utilisée dans le langage PHP pour colorer des codes sources dans différents langages de programmation dans le but de les afficher sur votre site web. Elle est par exemple utilisée sur ce site pour colorer les codes sources dans les messages du forum et les tutoriels ^^ . Cette bibliothèque est bien pratique et efficace, mais cependant, nous ne nous intéresserons pas à elle dans ce tutoriel : en effet, GeSHi a l’inconvénient de n’exister qu’en langage PHP, et ne nous concerne donc pas en tant qu’utilisateurs du langage Python ;) . Les utilisateurs de Python manquant de tels modules pour programmer par exemple des sites webs ou des applications affichant du code source, des programmeurs se lancèrent dans un projet : celui de recréer une bibliothèque du même type que GeSHi. Ils la nommèrent Pygments, un nom qui est un collage du mot pigment avec le début du mot python ;) . Cette bibliothèque est au moment où j’écris ce tutoriel dans sa version 0.9, de nom de code Herbstzeitlose :) . Intéressons nous dans ce tutoriels à comment installer Pygments chez vous pour pouvoir ensuite apprendre à l’utiliser dans vos applications python, puis voyons enfin les points avancés de Pygments, qui n’intéresserons sûrement pas tout le monde, mais qui peuvent être utile lorsque l’on cherche à réaliser des choses avancées avec cette bibliothèque ;) .]]> faut que Python soit installé sur votre ordinateur, cela parraît logique :D . Installation sous Windows Pour vous simplifier la vie si vous êtes sous Windows, j’ai demandé à Mickael de vous créer un petit installateur pour installer Pygments sans se prendre la tête ;) . Cet installateur est disponible à l’adresse suivante : http://delroth.alwaysdata.net/sdz/tuto-pygments/Pygments-0.9.win32.exe . Ensuite, suivez le guide :p . Téléchargez l’installateur, puis double-cliquez dessus. Une fenêtre s’ouvre, ressemblant à celle-ci : uploads/fr/files/109001_110000/109655.png Comme à l’habitude sous Windows, cliquez sur Suivant pour arriver sur cette fenêtre : uploads/fr/files/109001_110000/109654.png Continuez, et l’installation est terminée, vous pouvez passer au chapitre suivant ;) . Installation sous Linux avec le gestionnaire de paquets Souvent, sous GNU/Linux, Pygments est directement fourni par le gestionnaire de paquet de votre distribution (apt-get, urpmi, pacman, etc.), ce qui vous permet de l’installer comme tout autre logiciel ou bibliothèque que vous voudriez installer ;) . Le paquet se nomme le plus souvent python-pygments, pour vous aider dans vos recherches :) . Un exemple ici avec la réinstallation de Pygments chez moi, sous ArchLinux ;) . uploads/fr/files/109001_110000/109656.png Installation avec easy_install Si vous avez installé easy_install sur votre ordinateur, vous pouvez également l’utiliser pour installer Pygments ;) . Il suffit pour cela de taper la commande suivante dans une console : easy_install pygments Et easy_install s’occupe de tout :p . Installation avec les sources Tout d’abord, téléchargez les sources de Pygments depuis le site officiel, à l’adresse suivante : http://pypi.python.org/packages/source/P/Pygments/Pygments-0.9.tar.gz . Ensuite, décompressez l’archive, puis entrez dans le dossier avec une console (commande cd Pygments-0.9). Il suffit ensuite de lancer une commande, en tant qu’administrateur, ou root (donc sous ubuntu, n’oubliez par exemple pas sudo ;) ) : python setup.py install Et Python s’occupe de tout, ou plus précisément les distutils :) . À ce stade, chez tout le monde, Pygments est installé. Nous pouvons enfin commencer l’apprentissage de cette bibliothèque fantastique qu’est Pygments :p .]]> Le fonctionnement interne de Pygments En interne, Pygments utilise plusieurs composants indépendants qui correspondent chacun à une couche de traitement du code source pour arriver au code source final, coloré. Expliquons un à un le rôle de ces composants ;) . Le lexer Tout d’abord, le premier à travailler votre code source est le lexer : il s’agit de celui qui fait la plus grosse partie du travail, qui est de découper le code source original en ce qu’on appelle dans le jargon des tokens. Un token, c’est un indicateur qui va dire à Pygments « ceci est un mot clé du langage », ou « ceci est une chaîne de caractères » . Ce travail difficile est effectué de plusieurs manières différentes en interne, que vous connaissez peut-être, comme les RegExps ou d’autres types de parsers. uploads/fr/files/109001_110000/109657.png Le filter Ensuite, après le travail du lexer vient celui du filter. Les filters sont des éléments ayant un but précis sur le code, comme par exemple « mettre tous les mots clés en majuscule », mais ces éléments ne doivent pas avoir de rapport avec le formattage du code : en effet, on ne peut pas imaginer un filter faisant l’opération « mettre tous les commentaires en rouge ». Ces filters font partie des composants les plus simples à mettre en oeuvre dans Pygments étant donné leur faible rayon d’action et leur simplicité. Le formatter Le composant suivant le filter est le formatter, dont le rôle est crucial : il transforme la suite de tokens que vous pouvez voir ci-dessus en une belle sortie dans le format que vous voulez. On aura par exemple un formatter pour sortir du code HTML, un pour sortir du code affiché en mode console, ou un autre pour sortir par exemple une image SVG. Pour transformer les tokens en un format de sortie, le formatter va être configuré par l’utilisateur pour utiliser un style choisi, ou plein d’autres options intéressantes que nous tripoterons dans la troisième partie de ce tutoriel ;) . Pygments est fourni avec toute une ribambelle de lexers supportant les langages de programmations communs comme les plus exotiques, et une dixaine de formatters pour sortir votre code dans des formats comme le HTML, le LaTeX, le SVG ou le RTF. Bien entendu, rien n’empêche de rajouter vos propres composants dans la liste, comme nous le verrons en troisième partie du tutoriel ;) . Utilisation de Pygments en Python Tout d’abord, comme tout module Python, on doit importer pygments. Dans cette bibliothèque, une seule fonction nous intéresse : il s’agit de la fonction nommée highlight. Pour cela, on utilise donc le code suivant : from pygments import highlighter Ensuite, il nous faut du code à colorer. Voyons-voir... pourquoi pas du Python, d’ailleurs ? :D . Pour traduire le code Python en tokens, on utilise la classe pygments.lexers.PythonLexer : from pygments.lexers import PythonLexer Enfin, on va colorer ce code en le formattant par exemple en HTML. Pour cela, il nous faut le formatter pygments.formatters.HtmlFormatter : from pygments.formatters import HtmlFormatter Ça y est, nous avons tout ce qu’il nous faut :p . Reste à trouver un code source Python à colorer. Pour ma part, je vous propose ceci : source = '''def suite(n):    if n <= 1: return [1, 1]    prev = suite(n - 1)    ret = []    last = prev[0]    num = 0    for i, e in enumerate(prev):        if e == last: num += 1        else:            ret += [num, last]            num = 1            last = e    ret += [num, last]    return ret''' C’est un code source Python que j’ai codé il y a assez longtemps qui donne la suite logique assez connue suivante : 1 11 21 1211 111221 312211 ... Maintenant que nous avons tout, y compris une source à colorer, attaquons nous au code nécessaire à la coloration. Et c’est là que Pygments dégoute : code_colore = highlight(source, PythonLexer(), HtmlFormatter()) Et ceci est suffisant pour colorer notre code o_O . En effet, tout ce qu’on a vu précedemment sur les lexxers, les formatters et tout le tralala, c’est interne à Pygments : du côté du programme, on s’en fiche de comment Pygments va manipuler les tokens pour colorer notre code :p . Notre code coloré étant dans notre variable, on peut en faire ce que l’on veut :) . Récapitulons donc le code : from pygments import highlight from pygments.lexers import PythonLexer from pygments.formatters import HtmlFormatter   source = '''def suite(n):    if n <= 1: return [1, 1]    prev = suite(n - 1)    ret = []    last = prev[0]    num = 0    for i, e in enumerate(prev):        if e == last: num += 1        else:            ret += [num, last]            num = 1            last = e    ret += [num, last]    return ret'''   code_colore = highlight(source, PythonLexer(), HtmlFormatter()) Et voilà, vous savez colorer un code basique avec Pygments, félicitations :p . Voyons maintenant comme obtenir des informations depuis Pygments, comme par exemple les lexers disponibles, ou les formatters installés :) . Récupérer la feuille de style associée Si vous avez regardé un tant soit peu le code obtenu en sortie de Pygments, vous avez du vous rendre compte qu’il utilise du CSS, mais qu’il ne définit nulle part ces styles CSS. Si vous voulez récupérer ces styles, il faut donc ainsi faire comme ceci : f = HtmlFormatter() styles = f.get_style_defs() Rien de bien compliqué, encore une fois ;) . Récupérer tous les lexers connus Pygments définit une fonction pour obtenir les lexers utilisables pour parser votre code source : il s’agit de pygments.lexers.getall_lexers(), renvoyant des résultats du type suivant : (nom long, liste de noms courts, noms de fichiers correspondants, types MIME correspondants) Voilà qui termine cette courte introduction à Pygments. Dans la partie suivante, nous allons étudier plus en détail cette bibliothèque, en créant par exemple nos propres lexers, et en spécialisant nos formatters pour afficher par exemple les numéros de lignes ;) . ]]> options des formatters fournis par Pygments, qui permettent de totalement personnaliser l’affichage de notre code coloré. Ensuite, attaquons nous à un autre gros morceau, qui est celui de la création de nos propres lexers, qui parseront par exemple dans notre cas un langage simple : du bbcode ;) . Comment configurer un formatter ? La réponse à cette question est simple : en utilisant ce qu’on appelle les kwargs du constructeur ;) . Si vous ne savez pas ce que c’est, faisons en vitesse un bref topo là dessus : une fonction ou une méthode peut prendre X arguments nommés. Pour qu’elle puisse prendre un nombre indéfini d’arguments supplémentaires, on utilise les *args, qui ont l’effet par exemple des ... en C ou en C++. Mais ces arguments en nombre indéfini ne sont pas nommés : pour cela, on doit utiliser les (on y vient :p ) **kwargs . Un petit exemple ne vous fera sûrement pas de mal ;) . def fonction(x, y):     # fonction prend 2 arguments, ni plus, ni moins     print x, y   def fonction_args(*args):     # fonction_args prend de 0 à une infinité d'arguments, placés dans     # la liste "args"     print args   def fonction_fixe_args(x, y, *args):     # fonction_fixe_args prend de 2 à une infinité d'arguments : les     # deux premiers sont placés dans x et y, le reste dans args     print x, y, args   def fonction_kwargs(**kwargs):     # fonction_kwargs prend une infinité d'arguments nommés     # Par exemple, fonction_kwargs(truc=5, machin="meuh")     # Les arguments sont placés dans le dico kwargs.     print kwargs Je ne saurais trop vous conseiller de tester des appels de ces fonctions pour comprendre plus facilement le fonctionnement des *args et **kwargs. Alors comment utilise-t-on ces **kwargs pour configurer notre formatter :) ? Il suffit de passer vos arguments au constructeur du formatter, par exemple HtmlFormatter(arg=valeur). Voyons maintenant les différents paramètres modifiables dans le formatter le plus couramment utilisé : le HtmlFormatter :) . Les options du formatter HTML Voyons les options utilisables pour configurer votre HtmlFormatter et avoir un affichage de sortie associé à vos besoins ;) . La numérotation des lignes Tout comme GeSHi, Pygments supporte sans aucun problème la numérotation des lignes de code dans la sortie. Cela est réalisé par le biais de 4 options différentes :) . linenos : c’est l’option qui sert à ajouter les numéros de lignes sur le côté de votre code. Elle peut prendre dans la version actuelle 3 valeurs différentes : False si vous ne voulez pas de numéros de lignes "inline" si vous voulez des numéros de lignes en au début des lignes de code "table" si vous voulez des numéros de lignes bien séparés du code en utilisant un tableau. linenostart : cette option définit le numéro associé à la première ligne de votre code. C’est l’équivalent du debut="x" de la balise code en zCode ;) . Elle est bien entendu par défaut à la valeur 1. linenostep : une option pas forcèment utile pour du code, mais par exemple utile pour l’affichage d’un texte simple : elle permet l’affichage d’un numéro de ligne sur X. Ainsi, si on règle à deux cette option, un numéro de ligne sur deux sera affiché ;) . linenospecial : cette option permet de rendre une ligne sur X spéciale en lui donnant une classe CSS particulière (en l’occurence, special :p ). Voilà tout ce qui concerne la numérotation des lignes :) . Et si on passait à autre chose ? :) La gestion du CSS généré Pour colorer son code, Pygments, ou plutôt le HtmlFormatter, va utiliser des tags HTML utilisant également une feuille de style CSS. Tout le comportement vis-à-vis de ce CSS est configurable, via les options exposées ci-dessous : classprefix : cela ajoute un préfixe aux classes CSS de coloration, permettant ainsi de les distinguer de vos autres classes CSS en cas de conflit de nom ;) . cssclass : cela modifie la classe CSS associée au conteneur du code (un div dans la plupart des cas), permettant ainsi de distinguer les différents blocs de code au niveau du CSS. Par défaut, cette option a comme valeur "highlight" ;) . cssstyles : cette option permet d’ajouter des styles inline au conteneur du code, au cas où ceci serait nécessaire ;) . noclasses : comme son nom l’indique, l’option noclasses supprime l’utilisation des classes au profit de styles inline, augmentant donc énormément le poids de la page web générée, mais permettant une utilisation sans code CSS à rajouter dans la page. Voyons encore un autre domaine pour les options, puis on passera à la suite ;) . Génération d’un fichier HTML complet Par défaut, Pygments ne génère qu’un morceau de code HTML, à insérer dans une page web par exemple. Cela le rend très pratique quand il est utilisé dans un projet assez gros, mais rend impossible à priori la visualisation directe de la sortie HTML de Pygments. Que nenni, Pygments gère bien entendu tout cela par le biais d’un autre jeu d’option ;) . full : si cette option est mise à la valeur True, elle active la génération d’un document HTML complet, contenant donc tout le baratin habituel du HTML, tel que la doctype, les balises ou , etc. Elle est nécessaire pour toutes les autres options que nous allons voir plus bas. title : cette option permet de rajouter, via des balises HTML, un titre à votre document HTML généré. Il suffit de le spécifier, et Pygments s’occupe de l’intégrer dans la page ;) . cssfile : cette option permet de mettre le code CSS généré par Pygments dans un fichier CSS externe plutôt que directement dans la page web, soulagant ainsi son poids ;) . Voilà qui est fini sur les options utiles du formatter HTML. Avant de passer à la suite, concernant les styles de Pygments, je tiens d’abord à vous préciser que la documentation de toutes les options de tous les formatters est disponible à l’URL suivante : http://pygments.org/docs/formatters/ . N’hésitez pas à y faire un tour de temps en temps :) . Les styles de coloration Si vous avez lu la documentation dont je vous ai donné le lien juste au dessus, vous avez du vous rendre compte que les formatters prenaient très souvent une option style parmi leurs options. Ce style est en fait un composant de Pygments permettant de gérer les couleurs de coloration des différents tokens (les éléments constituants de votre code source, rappelez vous :) ). Voyons maintenant comment les utiliser pour modifier à souhait la coloration de votre code :) . Obtenir la liste des styles disponibles Il existe une fonction permettant d’obtenir tous les styles installés soit par Pygments, soit par des plugins externes que vous utilisez. Cette fonction est nommée pygments.styles.get_all_styles, et renvoie un itérateur qu’il vous faut transformer en liste avec la fonction list. from pygments.styles import get_all_styles all_styles = list(get_all_styles()) Utiliser un style pour mon formatter Il suffit d’utiliser l’option style dont j’ai parlé plus haut pour réaliser ceci : f = HtmlFormatter(style='native') # par exemple, pour le style native Rien de plus simple, n’est-ce-pas :) ? La plupart des formatters complexes supportent cette option, mais il en existe malheureusement pour lesquels cette option n’existe pas, car elle serait trop difficile à programmer, ou même totalement impossible :D . Vérifiez donc si cette option existe pour le formatter sur lequel vous souhaitez l’utiliser :) Créer son propre style Et oui, il est également possible de créer vous même votre propre style pour l’utiliser dans votre code :) . Pour cela, il suffit de créer une classe héritant de pygments.styles.Style, et de définir un dictionnaire nommé styles dedans :) . Si vous voulez en savoir plus sur le sujet, rendez-vous dans la documentation de Pygments, sur cette page : http://pygments.org/docs/styles/#creating-own-styles . Créer votre propre lexer Comme je l’avais promis, nous allons maintenant voir comment réaliser un lexer simple, qui colorera un langage de notre choix. Comme langage à colorer, j’ai choisi bien entendu le zCode, langage phare de ce site web, permettant l’écriture facile de tutoriaux ou de messages :) . Les tokens Tout d’abord, notre lexer devra sortir une série de tokens correspondant à notre code sous sa forme hachée. Mettons-nous déjà au courant de la liste des tokens existants et que nous pourrons utiliser dans notre code, disponible à l’adresse suivante : http:/pygments.orgdocs/tokens/ . Comme vous le voyez, il existe différents types de tokens, divisés en sous-types, par exemple : Token Token.Text Token.Error Token.Operator Keyword Keyword.Constant Keyword.Reserved Keyword.Type Il vous suffit de piocher dans ces catégories quand vous cherchez un token correspondant à vos besoins ;) . Le lexer Pour créer un lexer, il faut tout d’abord savoir le type de parser que nous allons mettre en place. Le plus utilisé est celui utilisant les RegExps, que vous avez peut-être apprises dans le tutoriel PHP de M@teo21 :) . Ce lexer de base peut être hérité pour créer vos propres lexers, et c’est ce qui est fait pour la plupart des langages de programmation supportés par Pygments ;) . Créons donc notre classe : from pygments.lexers import RegexLexer from pygments.tokens import *   class ZCodeLexer(RegexLexer):   name = 'zCode' # Nom du lexer   aliases = ['zcode'] # Noms courts du lexer   filenames = ['*.zcode'] # Type de fichiers gérés     tokens = {       'root': [           # Définir ici nos regexps qui traiteront le code           # Par exemple, j'ai mis une regexp qui transforme une balise           # zcode en un token "Keyword"           (r'<(.+?)>', Keyword),       ]   } Comme vous pouvez le voir, le code est plus que simple, et tout réside dans le choix des regexps, qui est hors du sujet de ce tutoriel (à bon entendeur, il n’y a pas encore de tutoriel sur les regexps en Python sur ce site :-° ). Vous savez donc maintenant réaliser des lexers simples pour vos langages de programmations non supportés par Pygments :) . ]]> GeSHi, Pygments se rattrape très bien, avec des performances 8 à 10 fois supérieure à la fameuse librairie PHP, et en fournissant une interface très simple permettant une grande configuration de la part de l’utilisateur pour créer une sortie vraiment personnelle. Malgré sa faible utilisation actuellement dans des projets connus, Pygments est soutenu par une large communauté rendant son développement rapide et dynamique, permettant ainsi des mises à jour et des corrections de bugs régulières. Tutoriel écrit en mdown. Sources disponibles sur demande. Placé sous licence CC-by-sapar delroth.]]>