La coloration syntaxique permet de mettre certain mot d'un langage donné en évidence grace à un changement de couleur et de style. Cette page à pour but d'indiquer comment écrire une coloration syntaxique pour un langage donné. Une fois ce fichier de coloration écrit, nous pourrons l'utiliser avec la balise %%(xxx)
Prérequis
Pour écrire une nouvelle coloration syntaxique, nous allons utiliser la classe
Highlighter présente dans le fichier
formatters/highlighter.class.inc.php. Notre fichier de coloration syntaxique aura pour nom
formatters/coloration_xxxx.php avec
xxxx le nom du langage tel qu'il apparaitra dans la balise %%.
Pour les besoins de l'explication, nous allons écrire une coloration incomplète du langage SQL ANSI. Le langage SQL est un langage permettant d'interroger des bases de données relationnel, c'est une norme ANSI mais beaucoup d'éditeur ajoutent des fonction supplémentaires.
NB.: avant la version
0.5.0 de
WikiNi, cette classe s'appelait
Hightlighter et se trouvait dans le fichier
hightlighter.class.inc (voir
WikiNiChangeLog050)
1ère étape
Création d'un fichier
formatters/coloration_sql.php. Comme nous devons utiliser la classe
Highlighter notre script php commencera donc par :
- include_once('formatters/highlighter.class.inc.php');
Ensuite nous créons une instance de cette classe :
- $SQLH = new Highlighter();
Le langage SQL n'est pas sensible à la casse des caratères, c'est a dire que "DROP TABLE" est équivalent à "drop table" :
- $SQLH->isCaseSensitiv = false;
2eme étape
La 2eme étape consiste à configurer les différents attributs de la classe
Highlighter. La plupart des éléments sont simple à configurer, mais certains nécessite la connaissance des expressions régulières PCRE (
voir le doc php).
Les commentaires
La plupart des langages de programmation possèdent des commentaires multi-lignes (répartie sur plusieurs lignes) et des commentaire mono-ligne ( le commentaire se termine avec une fin de ligne). La configuration des commentaire se fait grace aux tableaux
Highlighter::comment et
Highlighter::commentLine. La mise en forme est confié à l'attribut
Highlighter::commentStyle .
Pour définir les commentaires multi-ligne, indiquons les expressions régulières définissant les commentaires multi-ligne.
Notez que la classe Highlighter utilise le mode PCRE_UNGREEDY comme option de recherche (voir options de recherche PCRE).
En SQL, les commentaires multi-lignes commencent par
/* et finissent par
*/. Notre code sera donc :
- $SQLH->comment[] = '(/\*(.*)\*/)';
Les parentèses les plus externes sont importante car elle servent à définir ce qui sera remplacé par le texte colorié.
Les commentaires mono-ligne commencent avec
-- ou
# et terminent avec la marque de fin de ligne ou la fin du code. Nous aurons donc :
- $SQLH->commentLine[] = '(--.*(\n|$))';
- $SQLH->commentLine[] = '(#.*(\n|$))';
- Notez que, grâce à l'option de recherche PCRE_UNGREEDY, le $ signifiera toujours "fin du texte", malgré l'option PCRE_MULTILINE.
Enfin, les commentaires seront affichés en rouge et en italic. Définissons le style à appliquer a la balise
<SPAN></SPAN> qui entourera notre code colorié.
- $SQLH->commentStyle = "color: red; font-style: italic";
Les chaînes de caractères
Les chaines de caratères sont délimitées par des
"(guillemet) ou par
'(quotes simple) et ceux-ci peuvent être utilisés à l'intérieur de la chaine si on les échappe avec un
\ (antislash). Notez qu'une chaine pourrait très bien se terminer par un antislash ! ex.:
'cette chaine finit par un \\'
L'attribut à utiliser est
Highlighter::string et pour définir le style
Highlighter::stringStyle
- $SQLH->string[] = "('(.*[^\\\\])?(\\\\\\\\)*')";
- $SQLH->string[] = '("(.*[^\\\\])?(\\\\\\\\)*")';
- $SQLH->stringStyle = "background: yellow";
- Les deux expressions régulières signifient donc:
- Un guillemet
- Expression facultative (à cause du ?):
- N'importe quel carractère, 0 fois ou plus
- Suivi de n''importe quel carractère qui n'est pas un antislash. Il en faut 4:
- côté php: le 1er échappe le 2e, le 3e échappe le 4e, donc il en reste deux
- côté PCRE: le premier échappe le 2e, sinon c'est le crochet fermant qui sera échappé
- Deux antislashs consécutifs, répétés 0 fois ou plus. Il en faut 8 !
- côté php: un sur deux échappe celui qui suit, il en reste 4.
- côté PCRE: idem, il en reste donc deux.
- Un guillemet
- ... Vous pouvez constater que cela fonctionne très bien avec la ColorationSyntaxiqueOz.
- Dans un langage où un guillemet s'échepperait avec un autre guillemet, vous pouvez utiliser simplement l'expression "('.*')": Grâce à l'option PCRE_UNGREEDY cela cherchera le premier guillemet qui suit un guillemet. Côté HTML, s'il y a un échappement de guillemet, la chaine sera séparée en deux parties colorées séparément, mais en apparence cela ne changera rien. C'est ce qui est utilisé pour la ColorationSyntaxiqueMatlab. Notez que vous pourriez aussi faire le même petit jeu qu'avec les antislash, mais cela ne servirait qu'à supprimer un "</span><span style="...">"...
Les nombres
Les nombres seront traités avec les attributs
Highlighter::number et
Highlighter::numberStyle.
- $SQLH->number[] = '(\b\d+(\.\d*)?([eE][+-]?\d+)?)'; //123 ou 123. ou 123.456 ou 123.E-34 ou 123.e-34 123.45E+34 ou 4e54
- $SQLH->numberStyle = 'color: blue';
Le SQL ne supporte pas les nombres hexadécimaux, mais nous aurions pu ajouter
$SQLH->number[] = '(\$[0-9A-Fa-f]+\b)'; si cela avait été le cas.
Les mots clés
Les langages de programmation possèdent une liste de mots qui sont réservés au langage, utiliser un de ces mot dans un mauvais contexte engendre une erreur dans la pluspart des cas. Il peut être interressant d'avoir plusieurs liste de mots clés pour les colorier de manière différentes.
L'attribut utilisé pour les mots clés est
Highlighter::keywords. C'est un tableau qui va contenir des tableaux contenant les différentes listes de mots clés et leurs styles associés.
La première liste de mots clé du SQL concernera le langage lui même, appelons cette liste "Commands" :
- $SQLH->keywords['Commands']['words'] = array(
- 'ALL','ALTER','AND','AS','ASC',
- 'BEFORE','BETWEEN','BY',
- 'CASCADE','CHECK','COLUMN','CONSTRAINT','CREATE',
- 'DATABASE','DATABASES','DEFAULT','DELETE','DESC','DISTINCT','DROP',
- 'EXISTS','EXPLAIN','FROM','GRANT','GROUP','HAVING',
- 'IN','INDEX','INFILE','INNER','INSERT','INTO',
- 'JOIN','KEY','KEYS','LEFT','LIKE','LIMIT','NOT','NULL',
- 'ON','OR','ORDER','OUTER','PRIMARY','REVOKE','RIGHT',
- 'SELECT','STRAIGHT_JOIN','TABLE','TABLES',
- 'UNION','UNIQUE','UPDATE','VALUES','WHERE');
La clé "words" du tableau
$SQLH->keywords['Commands'] indique que la liste représente les mots clés. Pour le style de la liste Commands :
- $SQLH->keywords['Commands']['style'] = 'font-weight: bold';
Le deuxième liste de mots clés concernera les type de données, appelons cette liste "datatype" :
- $SQLH->keywords['datatype']['words'] = array(
- 'BIGINT','BINARY','BIT','BLOB','BOOL','BOOLEAN',
- 'CHAR','DATE','DATETIME','DEC','DECIMAL','DOUBLE',
- 'FIXED','FLOAT','INT','INTEGER','LONGBLOB','LONGTEXT',
- 'MEDIUMBLOB','MEDIUMINT','MEDIUMTEXT',
- 'NUMERIC','PRECISION','REAL','SET','SMALLINT',
- 'TEXT','TIME','TIMESTAMP','TINYBLOB','TINYINT','TINYTEXT',
- 'UNICODE','UNSIGNED','VARCHAR');
Et le style associé :
- $SQLH->keywords['datatype']['style'] = 'font-weight: bold; color: blue';
Les symboles
Les symboles sont les caractères comme l'addition ou l'étoile(*). Les attributs
Highlighter::symboles et
Highlighter::symbolesStyle sont utilisé :
- $SQLH->symboles = array('#','$','&','(','(.',')','*','+',',','-','.','.)','..',':',':=',';','<','<=','<>','=','>','>=','@','[',']','^');
- $SQLH->symbolesStyle = '';
Les symboles n'ont pas de style associé, il n'y aura donc pas de recherche des symboles lors de la coloration et les symboles seront affichés comme le reste de la page.
Pour qu'un attribut définissant une famille de caractères/mots/symbole ne soit pas utilisé, il suffit de mettre son attribut de style associé à vide.
Les identifiants
Les identifiants sont tous les mots valide dans le langage pour définir une variable ou un nom. En SQL ce sera le nom des tables, des colonnes et des indexes. Les attributs concernés sont
Highlighter::identifier et
Highlighter::identStyle:
- $SQLH->identifier = array('[_A-Za-z]?[_A-Za-z0-9]+');
- $SQLH->identStyle = '';
3ème étape
Utilisons l'instance de la classe
Highlighter que nous avons configurer. Lorsque
WikiNi appel un
"formatters" pour colorier un texte, il lui passe une variable
$text contenant le texte à colorier. A charge du
"formatters" d'afficher le résultat de la mise en forme. Le code sera donc :
- echo "<pre>".$SQLH->Analyse($text)."</pre>\n";
- unset($SQLH);
La méthode
Highlighter::Analyse() va analyser le texte passé en paramètre et renvoyer ce texte colorié selons la configuration utilisée.
Il ne reste plus qu'a placer notre fichiers
coloration_sql.php dans le répertoire
formatters de
WikiNi et nous pourrons l'utiliser via la balise :
- %%(sql)
...code sql ici ...
%%
Voici le code source (mais incomplet) de notre coloration syntaxique SQL :
<?php
include_once('formatters/highlighter.class.inc.php');
$SQLH = new Highlighter();
$SQLH->isCaseSensitiv = false;
$SQLH->comment[] = '(/\*(.*)\*/)';
$SQLH->commentLine[] = '(--.*(\n|$))';
$SQLH->commentLine[] = '(#.*(\n|$))';
$SQLH->commentStyle = "color: red; font-style: italic";
$SQLH->string[] = "('(.*[^\\\\])?(\\\\\\\\)*')";
$SQLH->string[] = '("(.*[^\\\\])?(\\\\\\\\)*")';
$SQLH->stringStyle = "background: yellow";
$SQLH->number[] = '(\b\d+(\.\d*)?([eE][+-]?\d+)?)';
$SQLH->numberStyle = 'color: blue';
$SQLH->keywords['Commands']['words'] = array(
'ALL','ALTER','AND','AS','ASC',
'BEFORE','BETWEEN','BY',
'CASCADE','CHECK','COLUMN','CONSTRAINT','CREATE',
'DATABASE','DATABASES','DEFAULT','DELETE','DESC','DISTINCT','DROP',
'EXISTS','EXPLAIN','FROM','GRANT','GROUP','HAVING',
'IN','INDEX','INFILE','INNER','INSERT','INTO',
'JOIN','KEY','KEYS','LEFT','LIKE','LIMIT','NOT','NULL',
'ON','OR','ORDER','OUTER','PRIMARY','REVOKE','RIGHT',
'SELECT','STRAIGHT_JOIN','TABLE','TABLES',
'UNION','UNIQUE','UPDATE','VALUES','WHERE');
$SQLH->keywords['Commands']['style'] = 'font-weight: bold';
$SQLH->keywords['datatype']['words'] = array(
'BIGINT','BINARY','BIT','BLOB','BOOL','BOOLEAN',
'CHAR','DATE','DATETIME','DEC','DECIMAL','DOUBLE',
'FIXED','FLOAT','INT','INTEGER','LONGBLOB','LONGTEXT',
'MEDIUMBLOB','MEDIUMINT','MEDIUMTEXT',
'NUMERIC','PRECISION','REAL','SET','SMALLINT',
'TEXT','TIME','TIMESTAMP','TINYBLOB','TINYINT','TINYTEXT',
'UNICODE','UNSIGNED','VARCHAR');
$SQLH->keywords['datatype']['style'] = 'font-weight: bold; color: blue';
$SQLH->symboles = array('#','$','&','(','(.',')','*','+',',','-','.','.)','..',':',':=',';','<','<=','<>','=','>','>=','@','[',']','^');
$SQLH->symbolesStyle = '';
$SQLH->identifier = array('[_A-Za-z]?[_A-Za-z0-9]+');
$SQLH->identStyle = '';
echo "<pre>".$SQLH->Analyse($text)."</pre>\n";
unset($SQLH);
?>
Question bête
J'utilise la version 0.4.1 de wikini. Où trouve-je highlighter.class.inc ? --
JeanMorlet
Tu dois avoir eu une version assez vieille de 0.4.1 je pense si tu ne l'as pas, sinon il est dans le répertoire
/formatters. Si tu ne l'as pas, tu peux le récupérer du CVS. Si tu ecris ta propre coloration syntaxique, n'oublis pas de la proposer !! --
GarfieldFr
OK, voici un premier jet pour le C/C++ qui fonctionne pas trop mal : --
JeanMorlet
<?php
include_once('formatters/highlighter.class.inc.php');
/* Création instance pour langage C */
$C = new Highlighter();
$C->isCaseSensitiv = true;
/* Définition des commentaires */
$C->comment[] = '(/\*(.*)\*/)';
$C->commentLine[] = '(//.*(\n|$))';
$C->commentStyle = "color: green; font-style: italic";
/* Définition des chaines de caractères */
$C->string[] = '("[^"]*")';
$C->stringStyle = "background: yellow";
/* Définition des nombres */
$C->number[] = '(\b\d+(\.\d*)?\b)'; //123 ou 123.456
$C->number[] = '(\b0[xX][0-9A-Fa-f]+\b)'; //ajout des nombres hexadecimaux : 0xAF ou 0Xdead
$C->numberStyle = 'font-weight:bold; color: #00AAAA';
/* Définition des directives de compilation */
$C->directive = array('#define','#undef','#if','#elif','#else','#endif','#ifdef','#ifndef','#include','#pragma','#error','#import','#using','#line');
$C->directiveStyle = 'font-weight: bold; color: red';
/* Définition des mots réservés */
$C->keywords['MotCle']['words'] = array(
'auto','break','case','char','const','continue','default','defined',
'do','double','else','enum','extern','float','for','goto','if',
'int','long','register','return','short','sizeof','static','struct','switch',
'typedef','union','unsigned','void','while',
'class','delete','finally','friend','inline','new','operator','overload',
'private','protected','public','this','virtual',
'bool','true','false','explicit','mutable','typename',
'static_cast','const_cast','reinterpret_cast','dynamic_cast','using','typeid',
'asm','_asm','__asm','catch','EXEC',
'signed','template','throw','try','volatile','namespace'
);
$C->keywords['MotCle']['style'] = 'font-weight: bold; color: blue';
/* Définition des symboles */
$C->symboles = array('$','&','(',')','*','+',',','-','.',':',';','<','<=','!=','=','>','>=','@','[',']','^','%','?','/','|','{','}');
$C->symbolesStyle = 'font-weight: bold; color: blue';
/* Définition du reste... */
$C->identifier = array('[_A-Za-z]?[_A-Za-z0-9]+');
$C->identStyle = '';
echo "<pre>".$C->Analyse($text)."</pre>\n";
unset($C);
?>
Ca semble pas mal ca !! Dès que c'est complet, n'oublie pas de le publier !!! --
GarfieldFr
Question à deux centimes: pourquoi la classe
Highlighter s'appelle ainsi alors que le mot correct est "highlighter" ? :-D Ce serait peut-être une bonne idée de corriger cela dans les prochaines versions de
WikiNi, car même si beaucoup de gens l'utilisent actuellement avec ce nom, cette faute (de frappe ?) est un peu... hum... disons
ridicule :-j -
LordFarquaad Réponse : Faute de frappe en effet --GarfieldFr
- Tout à fait d'accord, tu peux faire le changement si tu veux dans le CVS de la 0.5 ! Par ailleurs, on peut intégrer dans la prochaine version tous les colorateurs ayant acquis un degré de maturité suffisant (je pense notamment à ceux présentés ci-dessus). -- CharlesNepote
- Je veux bien mais comment on fait pour renommer un fichier du cvs (avec Tortoise de préférence) ? Au fait ne devrait-on pas tout de même lui mettre l'extension php à ce fichier ? Sinon pour les deux colorations que j'ai faites hier, je pense que matlab ça peut servir mais oz c'est vraiment trop peu utilisé à mon avis... -- LordFarquaad
- Tu supprime le fichier et tu le recré dans le CVS. Il existe des commande pour renommer un fichier du CVS mais tu ne peu pas les avoir depuis Tortoise (je crois) et il faut peut être même intervenir sur le serveur--GarfieldFr
- Oki ça marche :-) En tout cas tu as été persévérant pour la faute de frappe: c'était écrit partout comme ça lol
- J'ai aussi corrigé cette page entièrement comme vous pouvez le voir (par remplacement auto, j'espère qu'il n'y a pas d'erreur...) -- LordFarquaad
- Copier/coller du nom du fichier/classe ... donc partout pareil --GarfieldFr
- Ah oui au fait pour le C/C++, je viens de faire la correction pour les commentaires en fin de fichier, ainsi qu'une correction pour les nombres hexa (ça reconnaissait avant les 0|a13f comme des nombres hexa) par contre j'imagine qu'il doit aussi y avoir des carractères d'échappement pour les guillemets dans les chaines, mais comme je ne connais pas le c, je n'ai pas osé modifier... En tout cas le [^"] peut être au moins remplacé par un simple point (grâce au PCRE_UNGREEDY) -- LordFarquaad
- Même remarques pour le code delphi: il faut ternir compte de l'échappement des guillemets simples dans les chaines. Je l'ai mis dans un todo. -- LordFarquaad