Coloration syntaxique

Description

Voici un petit programme qui gère la coloration syntaxique façon Delphi. Je ne souhaite absolument pas rivaliser avec des composants tel que SynEdit (qui gère tout ça très bien) mais pour des besoins professionnels, j'ai été amené à coder moi même ce programme justement pour éviter les installations de composants en plus.
Tout est codé sous forme de procédures et fonctions, simple à comprendre et assez rapide d'exécution. J'ai vu qu'il existait déjà au moins deux sources présentant la même fonctionnalité mais après tests des différents codes trouvés, aucun ne fonctionne sous Delphi 2009 et/ou est très lent à exécuter.

Le code est simple et assez commenté pour que des débutants puissent le comprendre facilement. Je pense que c'est une bonne base pour ceux qui veulent faire quelque chose de plus complexe. Vous pouvez modifier le code sans trop de soucis.

Source / Exemple :


unit U_Color;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    Btn_Colorier: TButton;
    procedure Btn_ColorierClick(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
procedure HightLight_Syntax(ARE : TRichEdit);
{$REGION 'Sub-functions'}
// Sous fonction seulement visible à l'intérieur de HighLight_Syntax et qui a accès à ARE
procedure HighLight_Others(AStart, AEnd : String; AColor : TColor);
var
  iNext, iPos, iPos_End : Integer;
begin
  iNext := 0;
  iPos := ARE.FindText(AStart, iNext, Length(ARE.Text), [stMatchCase]);
  while iPos <> -1 do // FindText renvoit -1 si il n'a pas trouvé AStart dans le RichEdit
  begin
    iNext := iPos + Length(AStart); // On rétrécit le texte à parcourir pour ne pas boucler sur toujours le même mot
    ARE.SelStart := iPos; // On initialise la position de départ du RichEdit
    iPos_End := ARE.FindText(AEnd, iNext, Length(ARE.Text), [stMatchCase]); // On cherche la position du deuxième caractère qui doit arrêter la coloration
    if iPos_End = -1 then
      if AStart = '''' then
        iPos_End := ARE.FindText(#13, iNext, Length(ARE.Text), [stMatchCase]) // Quand il s'agit d'une ouverture de chaine ('), on termine la coloration à la fin de la ligne
      else
        iPos_End := Length(ARE.Text); // Par défaut, s'il manque le caractère de fin, on termine la coloration à la fin du texte

    ARE.SelLength := (iPos_End  - iPos) + Length(AEnd); // On définit jusqu'à où doit être coloré le texte
    ARE.SelAttributes.Color := AColor; // Et on colore
    if AStart = '''' then
      iPos := ARE.FindText('''', iNext + iPos_End, Length(ARE.Text), [stMatchCase]) // Quand il s'agit d'une ouverture de chaine, la position de la chaine suivante doit commencer après la fermeture de la dernière chaine
    else
      iPos := ARE.FindText(AStart, iNext, Length(ARE.Text), [stMatchCase]);
  end;
end;
{$ENDREGION}

var
  SL_Key_Word : TStringList;
  i, iPos, iNext, iPos_Symb_Start, iPos_Symb_End, iTest : Integer;
const
  C_Path = 'KeyWords.txt';
begin
  ARE.SelectAll;
  ARE.SelAttributes.Color := clBlack;
  SL_Key_Word := TStringList.Create;
  try
    SL_Key_Word.LoadFromFile(C_Path);
    i := 0;
    while i < SL_Key_Word.Count do
    begin
      iNext := 0;
      iPos := ARE.FindText(SL_Key_Word[i], iNext, Length(ARE.Text), [stWholeWord]); // On ne recherche que les mots ENTIERS qui correspondent à un mot clef
      while iPos <> -1 do
      begin
        iPos_Symb_Start := ARE.FindText('_', iPos - 1, 1, [stMatchCase]); // Pour éviter que les mots précédés de "_" ne soient colorés aussi (FindText ne gère pas ça)
        if iPos = 0 then
          iTest := 0 // Si la position est égale à 0, c'est qu'il n'y a obligatoirement aucun "_" avant. Pour éviter que iPos - iPos_Symb_Start = 1.
        else
          iTest := iPos - iPos_Symb_Start;

        iPos_Symb_End := ARE.FindText('_', iPos, Length(SL_Key_Word[i]) + 1, [stMatchCase]); // Pour éviter que les mots suivis de "_" ne soient colorés aussi
        if (iTest <> 1) and (((Length(SL_Key_Word[i]) + iPos) - iPos_Symb_End) + 1 <> 1) then // Si le mot n'est pas entouré de "_"
        begin
          iNext := iPos + Length(SL_Key_Word[i]); // La prochaine recherche se fait à partir de la fin du dernier mot clef trouvé
          ARE.SelStart := iPos;
          ARE.SelLength := Length(SL_Key_Word[i]);
          ARE.SelAttributes.Color := clNavy;
        end
        else
          iNext := iPos + Length(SL_Key_Word[i]) - 1; // Ici ce n'est pas un mot clef

        iPos := ARE.FindText(SL_Key_Word[i], iNext, Length(ARE.Text), [stWholeWord]); // Recherche du prochain mot clef
      end;
      inc(i);
    end;

    HighLight_Others('(*', '*)', clGreen);
    HighLight_Others('//', #13, clGreen); // #13 représente le saut de ligne
    HighLight_Others('{', '}', clGreen);
    HighLight_Others('{$', '}', clTeal);
    HighLight_Others('''', '''', clBlue);

  finally
    SL_Key_Word.Free;
  end;
end;

procedure TForm1.Btn_ColorierClick(Sender: TObject);
begin
  HightLight_Syntax(RichEdit1);
end;

end.

Conclusion :


J'ai essayé de gérer un maximum de cas à ma portée, normalement il fonctionne correctement. Si vous avez des suggestions ou des choses qui vous paraissent fausses, n'hésitez pas à me contacter

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.