3
This is an example how to implement your own highlighter.
5
This example extends the Simple and Context HL:
6
- The token -(- and -)- (must be surrounded by space or line-begin/end to be
7
a token of their own) will add foldable sections
9
Multply -(- and -)- can be nested.
11
See comments below and http://wiki.lazarus.freepascal.org/SynEdit_Highlighter
20
Classes, SysUtils, Graphics, SynEditTypes, SynEditHighlighter, SynEditHighlighterFoldBase, ContextHL;
24
(* This is an EXACT COPY of SynEditHighlighter
26
ONLY the base class is changed to add support for folding
28
The new code follows below
31
TSynDemoHlFoldBase = class(TSynCustomFoldHighlighter)
33
FNotAttri: TSynHighlighterAttributes;
34
fSpecialAttri: TSynHighlighterAttributes;
35
fIdentifierAttri: TSynHighlighterAttributes;
36
fSpaceAttri: TSynHighlighterAttributes;
37
procedure SetIdentifierAttri(AValue: TSynHighlighterAttributes);
38
procedure SetNotAttri(AValue: TSynHighlighterAttributes);
39
procedure SetSpaceAttri(AValue: TSynHighlighterAttributes);
40
procedure SetSpecialAttri(AValue: TSynHighlighterAttributes);
42
// accesible for the other examples
43
FTokenPos, FTokenEnd: Integer;
46
procedure SetLine(const NewValue: String; LineNumber: Integer); override;
47
procedure Next; override;
48
function GetEol: Boolean; override;
49
procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override;
50
function GetTokenAttribute: TSynHighlighterAttributes; override;
52
function GetToken: String; override;
53
function GetTokenPos: Integer; override;
54
function GetTokenKind: integer; override;
55
function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes; override;
56
constructor Create(AOwner: TComponent); override;
58
(* Define 4 Attributes, for the different highlights. *)
59
property SpecialAttri: TSynHighlighterAttributes read fSpecialAttri
60
write SetSpecialAttri;
61
property NotAttri: TSynHighlighterAttributes read FNotAttri
63
property IdentifierAttri: TSynHighlighterAttributes read fIdentifierAttri
64
write SetIdentifierAttri;
65
property SpaceAttri: TSynHighlighterAttributes read fSpaceAttri
69
(* This is a COPY of SynEditHighlighter
71
ONLY the base class is changed to add support for folding
73
The new code follows below
76
TSynDemoHlContextFoldBase = class(TSynDemoHlFoldBase)
80
procedure Next; override;
81
function GetTokenAttribute: TSynHighlighterAttributes; override;
83
(* The below needed to be changed and are in TSynDemoHlFold
84
TSynDemoHlContextFoldBase uses Ranges itself.
85
The Range needed here is therefore stored in a diff location
87
//procedure SetRange(Value: Pointer); override;
88
//procedure ResetRange; override;
89
//function GetRange: Pointer; override;
94
(* You can base this on either
95
TSynDemoHlFoldBase or TSynDemoHlContextFoldBase
97
Using ranges is NOT a condition for fold.
98
(If changing, remove Range related code)
100
Note that ranges to change.
103
//TSynDemoHlFold = class(TSynDemoHlFoldBase)
104
TSynDemoHlFold = class(TSynDemoHlContextFoldBase)
106
procedure Next; override;
108
procedure SetRange(Value: Pointer); override;
109
procedure ResetRange; override;
110
function GetRange: Pointer; override;
117
procedure TSynDemoHlFold.Next;
120
if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '-(-') then
121
StartCodeFoldBlock(nil);
122
if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '-)-') then
126
procedure TSynDemoHlFold.SetRange(Value: Pointer);
128
// must call the SetRange in TSynCustomFoldHighlighter
129
inherited SetRange(Value);
130
FCurRange := PtrInt(CodeFoldRange.RangeType);
133
procedure TSynDemoHlFold.ResetRange;
135
inherited ResetRange;
139
function TSynDemoHlFold.GetRange: Pointer;
141
// Store the range first
142
CodeFoldRange.RangeType := Pointer(PtrInt(FCurRange));
143
Result := inherited GetRange;
147
(* This is an EXACT COPY of SynEditHighlighter
149
ONLY the base class is changed to add support for folding
152
constructor TSynDemoHlFoldBase.Create(AOwner: TComponent);
154
inherited Create(AOwner);
156
(* Create and initialize the attributes *)
157
fSpecialAttri := TSynHighlighterAttributes.Create('special', 'special');
158
AddAttribute(fSpecialAttri);
159
fSpecialAttri.Style := [fsBold];
161
FNotAttri := TSynHighlighterAttributes.Create('not', 'not');
162
AddAttribute(FNotAttri);
163
FNotAttri.Background := clRed;
165
fIdentifierAttri := TSynHighlighterAttributes.Create('ident', 'ident');
166
AddAttribute(fIdentifierAttri);
168
fSpaceAttri := TSynHighlighterAttributes.Create('space', 'space');
169
AddAttribute(fSpaceAttri);
170
fSpaceAttri.FrameColor := clSilver;
171
fSpaceAttri.FrameEdges := sfeAround;
174
(* Setters for attributes / This allows using in Object inspector*)
175
procedure TSynDemoHlFoldBase.SetIdentifierAttri(AValue: TSynHighlighterAttributes);
177
fIdentifierAttri.Assign(AValue);
180
procedure TSynDemoHlFoldBase.SetNotAttri(AValue: TSynHighlighterAttributes);
182
FNotAttri.Assign(AValue);
185
procedure TSynDemoHlFoldBase.SetSpaceAttri(AValue: TSynHighlighterAttributes);
187
fSpaceAttri.Assign(AValue);
190
procedure TSynDemoHlFoldBase.SetSpecialAttri(AValue: TSynHighlighterAttributes);
192
fSpecialAttri.Assign(AValue);
195
procedure TSynDemoHlFoldBase.SetLine(const NewValue: String; LineNumber: Integer);
198
FLineText := NewValue;
199
// Next will start at "FTokenEnd", so set this to 1
204
procedure TSynDemoHlFoldBase.Next;
208
// FTokenEnd should be at the start of the next Token (which is the Token we want)
209
FTokenPos := FTokenEnd;
210
// assume empty, will only happen for EOL
211
FTokenEnd := FTokenPos;
214
// FTokenEnd will be set 1 after the last char. That is:
215
// - The first char of the next token
216
// - or past the end of line (which allows GetEOL to work)
218
l := length(FLineText);
219
If FTokenPos > l then
223
if FLineText[FTokenEnd] in [#9, ' '] then
224
// At Space? Find end of spaces
225
while (FTokenEnd <= l) and (FLineText[FTokenEnd] in [#0..#32]) do inc (FTokenEnd)
227
// At None-Space? Find end of None-spaces
228
while (FTokenEnd <= l) and not(FLineText[FTokenEnd] in [#9, ' ']) do inc (FTokenEnd)
231
function TSynDemoHlFoldBase.GetEol: Boolean;
233
Result := FTokenPos > length(FLineText);
236
procedure TSynDemoHlFoldBase.GetTokenEx(out TokenStart: PChar; out TokenLength: integer);
238
TokenStart := @FLineText[FTokenPos];
239
TokenLength := FTokenEnd - FTokenPos;
242
function TSynDemoHlFoldBase.GetTokenAttribute: TSynHighlighterAttributes;
244
// Match the text, specified by FTokenPos and FTokenEnd
246
if FLineText[FTokenPos] in [#9, ' '] then
249
if LowerCase(FLineText[FTokenPos]) in ['a', 'e', 'i', 'o', 'u'] then
250
Result := SpecialAttri
252
if LowerCase(copy(FLineText, FTokenPos, FTokenEnd - FTokenPos)) = 'not' then
255
Result := IdentifierAttri;
258
function TSynDemoHlFoldBase.GetToken: String;
260
Result := copy(FLineText, FTokenPos, FTokenEnd - FTokenPos);
263
function TSynDemoHlFoldBase.GetTokenPos: Integer;
265
Result := FTokenPos - 1;
268
function TSynDemoHlFoldBase.GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
270
// Some default attributes
272
SYN_ATTR_COMMENT: Result := fSpecialAttri;
273
SYN_ATTR_IDENTIFIER: Result := fIdentifierAttri;
274
SYN_ATTR_WHITESPACE: Result := fSpaceAttri;
279
function TSynDemoHlFoldBase.GetTokenKind: integer;
281
a: TSynHighlighterAttributes;
283
// Map Attribute into a unique number
284
a := GetTokenAttribute;
286
if a = fSpaceAttri then Result := 1;
287
if a = fSpecialAttri then Result := 2;
288
if a = fIdentifierAttri then Result := 3;
289
if a = FNotAttri then Result := 4;
293
(* This is an EXACT COPY of SynEditHighlighter
295
ONLY the base class is changed to add support for folding
298
procedure TSynDemoHlContextFoldBase.Next;
301
if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '--') then
303
if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '++') and (FCurRange > 0) then
307
function TSynDemoHlContextFoldBase.GetTokenAttribute: TSynHighlighterAttributes;
309
Result := inherited GetTokenAttribute;
310
if (Result = SpecialAttri) and (FCurRange > 0) then
311
Result := IdentifierAttribute;