AdvMemo - creating own syntax styler

Hello,

I am developing a code editor for my own domain specific language and I would like to create a syntax styler for that purpose. But, I don't see how or if it is even possible to do so with the existing components?

For example, I would like to define a set of keywords and default color for all keywords, but also to be able to set specific color some some of the keywords. Is it possible that you provide a 'AdvCustomMemoStyler' like component with these capabilities?

Have a look at the code of the provided styler. You typically descend from TAdvCustomMemoStyler and define the settings for your custom styler in the constructor override of your custom styler class.


This is the code from the Pascal language styler:

{ TAdvPascalMemoStyler }
constructor TAdvPascalMemoStyler.Create(AOwner: TComponent);
var
  itm:TElementStyle;
begin
  inherited;
  FVersion := '3.0';
  Description := 'Pascal';
  Filter := 'Pascal Files (.pas,.dpr,.dpk,.inc)|.pas;.dpr;.dpk;.inc';
  DefaultExtension := '.pas';
  StylerName := 'Pascal';
  Extensions := 'pas;dpr;dpk;inc';

  LineComment := '//';
  MultiCommentLeft := '{';
  MultiCommentRight := '}';
  CommentStyle.TextColor := clNavy;
  CommentStyle.BkColor := clNone;
  CommentStyle.Style := [fsItalic];
  NumberStyle.TextColor := clFuchsia;
  NumberStyle.BkColor := clNone;
  NumberStyle.Style := [fsBold];
  BlockStart := 'begin,try,case,class,record,interface';
  BlockEnd := 'end';
  HexIdentifier := '$';
  //------------Pascal Standard Default-------------
  itm := AllStyles.Add;
  itm.Info := 'Pascal Standard Default';
  itm.Font.Color := clGreen;
  itm.Font.Style := [fsBold];
  itm.BGColor := clNone;
  with itm.KeyWords do
  begin
    Add('UNIT');
    Add('INTERFACE');
    Add('IMPLEMENTATION');
    Add('USES');
    Add('CONST');
    Add('PROGRAM');
    Add('PRIVATE');
    Add('PUBLIC');
    Add('PUBLISHED');
    Add('PROTECTED');
    Add('PROPERTY');
    Add('FUNCTION');
    Add('FINALISE');
    Add('INITIALISE');
    Add('VAR');
    Add('BEGIN');
    Add('WITH');
    Add('END');
    Add('FOR');
    Add('TO');
    Add('DO');
    Add('NOT');
    Add('IF');
    Add('THEN');
    Add('ELSE');
    Add('TYPE');
    Add('WHILE');
    Add('REPEAT');
    Add('UNTIL');
    Add('BREAK');
    Add('CONTINUE');
    Add('VIRTUAL');
    Add('OVERRIDE');
    Add('DEFAULT');
    Add('CLASS');
    Add('STORED');
    Add('INHERITED');
    Add('PROCEDURE');
    Add('CONSTRUCTOR');
    Add('DESTRUCTOR');
    Add('FINALLY');
    Add('RAISE');
    Add('STRING');
    Add('TRY');
    Add('EXCEPT');
    Add('STDCALL');
    Add('CDECL');
    Add('PASCAL');
    Add('NIL');
    Add('CASE');
    Add('REINTRODUCE');
    Add('PACKED');
    Add('RECORD');
    Add('MESSAGE');
    Add('IN');
    Add('IS');
    Add('SHL');
    Add('SHR');
    Add('MOD');
    Add('DIV');
    Add('XOR');
    Add('OR');
    Add('AND');
    Add('OF');
    Add('SET');
    Add('DOWNTO');
    Add('EXPORTS');
    Add('LIBRARY');
    Add('AS');
    Add('ASM');
    Add('DYNAMIC');
    Add('OBJECT');
    Add('THREADVAR');
    Add('FILE');
    Add('ABSTRACT');
    Add('OVERLOAD');
    Add('ASSEMBLER');
    Add('ABSOLUTE');
    Add('AUTOMATED');
    Add('EXTERNAL');
    Add('REGISTER');
    Add('DISPINTERFACE');
    Add('RESOURCESTRING');
    Add('NEAR');
    Add('FAR');
    Add('LABEL');
    Add('OUT');
    Add('SAFECALL');
    Add('DISPID');
    Add('ARRAY');
    Add('INLINE');
    Add('FORWARD');
    Add('PLATFORM');
    Add('DEPRECATED');
  end;
  
  //------------Simple Quote ' '----------------
  itm := AllStyles.Add;
  itm.StyleType := stBracket;
  itm.Info := 'Simple Quote';
  itm.Font.Color := clBlue;
  itm.Font.Style := [];
  itm.BracketStart := #39;
  itm.BracketEnd := #39;
  itm.BGColor := clNone;
  //------------Double Quote " "----------------
  itm := AllStyles.Add;
  itm.StyleType := stBracket;
  itm.Info := 'Double Quote';
  itm.Font.Color := clBlue;
  itm.Font.Style := [];
  itm.BracketStart := '"';
  itm.BracketEnd := '"';
  itm.BGColor := clNone;
  //----------SYMBOL --------------
  itm := AllStyles.Add;
  itm.StyleType := stSymbol;
  itm.Info := 'Symbols Delimiters';
  itm.Font.Color := clred;
  itm.Font.Style := [];
  itm.Symbols := #32+',;:.(){}[]=+-/^%<>#'+#13+#10;
  itm.BGColor := clNone;
  //----------MULTI LINE COMMENT --------------
  itm := AllStyles.Add;
  itm.StyleType := stComment;
  itm.Info := 'Multi line comment';
  itm.CommentLeft := '(';
  itm.CommentRight := '*)';
  itm.BGColor := clNone;
  itm.Font.Color := clGray;
  itm.Font.Style := [fsItalic];

  with HintParameter.Parameters do
  begin
    Add('ShowMessage(const Msg: string);');
    Add('MessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer);');
  end;

  with AutoCompletion do
  begin
    Add('ShowMessage');
    Add('MessageDlg');
  end;

  //-------------- Region Definition
  with RegionDefinitions.Add do
  begin
    Identifier := 'procedure';
    RegionStart := 'begin';
    RegionEnd := 'end';
    RegionType := rtClosed;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := 'procedure';
    RegionStart := '';
    RegionEnd := 'forward';
    RegionType := rtClosed;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := 'constructor';
    RegionStart := 'begin';
    RegionEnd := 'end';
    RegionType := rtClosed;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := 'destructor';
    RegionStart := 'begin';
    RegionEnd := 'end';
    RegionType := rtClosed;
  end;

  with RegionDefinitions.Add do
  begin
    Identifier := 'interface';
    RegionStart := 'interface';
    RegionType := rtOpen;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := 'unit';
    RegionStart := 'unit';
    RegionType := rtFile;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := 'implementation';
    RegionStart := 'implementation';
    RegionType := rtOpen;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := 'case';
    RegionStart := 'case';
    RegionEnd := 'end';
    RegionType := rtIgnore;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := 'try';
    RegionStart := 'try';
    RegionEnd := 'end';
    RegionType := rtIgnore;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := 'function';
    RegionStart := 'begin';
    RegionEnd := 'end';
    RegionType := rtClosed;
  end;
  with RegionDefinitions.Add do
  begin
    Identifier := '{$region';
    RegionStart := '{$region';
    RegionEnd := '{$endregion';
    RegionType := rtClosed;
  end;
end;

This seams to me as completely wrong approach. Instead having so many
MemoStyler components (one for each language) and creating additional
components for other languages one styler component could be enough. A
single styler component could have a list of predefined styles to choose
from and "custom" option that would allow to define a new style.

Then we differ in opinion.


Each styler is in its own unit and when you do not use styles, the unit isn't used and the unused style isn't linked with your app. With your approach, regardless of using one style or 10 styles, everything would be always linked with your app.
No, I am not suggesting to have one component that links to other components, but to have one component that uses "items" to enumerate keywords, regions etc., and to populate those items by using already predefined list of programming languages/scripts. 

This would simply require to parametrize one styler component so that keywords and everything could be defined by using object inspector. I hope you understand what I mean.

That is what you can do now. For example in the TAdvPascalMemoStyler, you can add/remove keywords, change comment identifiers etc..