IDE, SynEdit: PascalHighlighter, CustomWords (Tokens, must be identifier) for comment and string. Custom color for comment by type // vs (* . Includes Issue #40881

This commit is contained in:
Martin 2025-03-24 00:45:01 +01:00
parent ee60271592
commit 8e59857521
5 changed files with 419 additions and 92 deletions

View File

@ -61,9 +61,16 @@ type
TSynPasMultilineStringMode = (spmsmDoubleQuote); TSynPasMultilineStringMode = (spmsmDoubleQuote);
TSynPasMultilineStringModes = set of TSynPasMultilineStringMode; TSynPasMultilineStringModes = set of TSynPasMultilineStringMode;
TtkTokenKind = (tkAsm, tkComment, tkIdentifier, tkKey, tkModifier, tkNull, tkNumber, TtkTokenKindEx = (
tkAsm, tkComment, tkIdentifier, tkKey, tkModifier, tkNull, tkNumber,
tkSpace, tkString, tkSymbol, tkDirective, tkIDEDirective, tkSpace, tkString, tkSymbol, tkDirective, tkIDEDirective,
tkUnknown); tkUnknown,
// for custom token only
tkSlashComment, tkAnsiComment, tkBorComment
);
TtkTokenKindExs= set of TtkTokenKindEx;
TtkTokenKind = tkAsm..tkUnknown;
TtkTokenKinds= set of TtkTokenKind; TtkTokenKinds= set of TtkTokenKind;
TRangeState = ( TRangeState = (
@ -498,16 +505,16 @@ type
procedure DoTokensChanged(Sender: TObject); procedure DoTokensChanged(Sender: TObject);
private private
FMarkup: TSynHighlighterAttributesModifier; FMarkup: TSynHighlighterAttributesModifier;
FMatchTokenKinds: TtkTokenKinds; FMatchTokenKinds: TtkTokenKindExs;
FTokens: TStrings; FTokens: TStrings;
procedure SetMatchTokenKinds(AValue: TtkTokenKinds); procedure SetMatchTokenKinds(AValue: TtkTokenKindExs);
property OnChange: TNotifyEvent read FOnChange write FOnChange; property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnMarkupChange: TNotifyEvent read FOnMarkupChange write FOnMarkupChange; property OnMarkupChange: TNotifyEvent read FOnMarkupChange write FOnMarkupChange;
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
property MatchTokenKinds: TtkTokenKinds read FMatchTokenKinds write SetMatchTokenKinds; property MatchTokenKinds: TtkTokenKindExs read FMatchTokenKinds write SetMatchTokenKinds;
property Tokens: TStrings read FTokens; property Tokens: TStrings read FTokens;
property Markup: TSynHighlighterAttributesModifier read FMarkup; property Markup: TSynHighlighterAttributesModifier read FMarkup;
end; end;
@ -582,7 +589,7 @@ type
TSynPasSyn = class(TSynCustomFoldHighlighter) TSynPasSyn = class(TSynCustomFoldHighlighter)
private type private type
TSynPasSynCustomTokenInfoListEx = record TSynPasSynCustomTokenInfoListEx = record
TokenKind: TtkTokenKind; TokenKind: TtkTokenKindEx;
List: TStringList; List: TStringList;
end; end;
PSynPasSynCustomTokenInfoListEx = ^TSynPasSynCustomTokenInfoListEx; PSynPasSynCustomTokenInfoListEx = ^TSynPasSynCustomTokenInfoListEx;
@ -594,11 +601,12 @@ type
FSynCustomTokens: array of TSynPasSynCustomToken; FSynCustomTokens: array of TSynPasSynCustomToken;
FNeedCustomTokenBuild: boolean; FNeedCustomTokenBuild: boolean;
FCustomTokenInfo: array [byte] of record FCustomTokenInfo: array [byte] of record
MatchTokenKinds: TtkTokenKinds; MatchTokenKinds: TtkTokenKindExs;
Lists: array of TSynPasSynCustomTokenInfoListEx; Lists: array of TSynPasSynCustomTokenInfoListEx;
end; end;
FCustomTokenMarkup: TSynHighlighterAttributesModifier; FCustomTokenMarkup, FCustomCommentTokenMarkup: TSynHighlighterAttributesModifier;
FCustomTokenMergedMarkup: TSynSelectedColorMergeResult; FCustomTokenMarkupSlash, FCustomTokenMarkupAnsi, FCustomTokenMarkupBor: TSynHighlighterAttributesModifier;
FCustomTokenMergedMarkup, FCustomCommentTokenMergedMarkup: TSynSelectedColorMergeResult;
FCurIDEDirectiveAttri: TSynSelectedColorMergeResult; FCurIDEDirectiveAttri: TSynSelectedColorMergeResult;
FCurCaseLabelAttri: TSynSelectedColorMergeResult; FCurCaseLabelAttri: TSynSelectedColorMergeResult;
@ -637,7 +645,7 @@ type
FStringKeywordMode: TSynPasStringMode; FStringKeywordMode: TSynPasStringMode;
FStringMultilineMode: TSynPasMultilineStringModes; FStringMultilineMode: TSynPasMultilineStringModes;
FSynPasRangeInfo: TSynPasRangeInfo; FSynPasRangeInfo: TSynPasRangeInfo;
FAtLineStart: Boolean; // Line had only spaces or comments sofar FAtLineStart, FInString: Boolean; // Line had only spaces or comments sofar
fLineStr: string; fLineStr: string;
fLine: PChar; fLine: PChar;
fLineLen: integer; fLineLen: integer;
@ -824,6 +832,7 @@ type
procedure SemicolonProc; //mh 2000-10-08 procedure SemicolonProc; //mh 2000-10-08
procedure SlashProc; procedure SlashProc;
procedure SlashContinueProc; procedure SlashContinueProc;
procedure SlashCommentProc;
procedure SpaceProc; procedure SpaceProc;
procedure StringProc; procedure StringProc;
procedure DoubleQuoteProc; procedure DoubleQuoteProc;
@ -833,6 +842,16 @@ type
procedure SetD4syntax(const Value: boolean); procedure SetD4syntax(const Value: boolean);
function CanApplyExtendedDeclarationAttribute(AMode: TSynPasTypeAttributeMode): boolean; inline; function CanApplyExtendedDeclarationAttribute(AMode: TSynPasTypeAttributeMode): boolean; inline;
function GetCustomSymbolToken(ATokenID: TtkTokenKindEx; ALen: integer;
out ACustomMarkup: TSynHighlighterAttributesModifier;
APeekOnly: boolean = False
): boolean; inline;
function GetCustomTokenAndNext(ATokenID: TtkTokenKindEx; out ACustomMarkup: TSynHighlighterAttributesModifier;
APeekOnly: boolean = False
): boolean; inline;
function GetCustomToken(ATokenID: TtkTokenKindEx; AnHash: byte; ATokenStart: PChar; ATokenLen: integer;
out ACustomMarkup: TSynHighlighterAttributesModifier
): boolean; inline;
procedure CheckForAdditionalAttributes; procedure CheckForAdditionalAttributes;
// Divider // Divider
@ -1548,7 +1567,7 @@ begin
end; end;
procedure TSynPasSyn.RebuildCustomTokenInfo; procedure TSynPasSyn.RebuildCustomTokenInfo;
function FindList(AnHash: Byte; ATokenKind: TtkTokenKind): PSynPasSynCustomTokenInfoListEx; function FindList(AnHash: Byte; ATokenKind: TtkTokenKindEx): PSynPasSynCustomTokenInfoListEx;
var var
x: Integer; x: Integer;
begin begin
@ -1570,11 +1589,16 @@ procedure TSynPasSyn.RebuildCustomTokenInfo;
var var
i, j, h: Integer; i, j, h: Integer;
t: String; t: String;
tk: TtkTokenKind; mtk: TtkTokenKindExs;
tk: TtkTokenKindEx;
Lst: PSynPasSynCustomTokenInfoListEx; Lst: PSynPasSynCustomTokenInfoListEx;
begin begin
FNeedCustomTokenBuild := False; FNeedCustomTokenBuild := False;
FCustomTokenMarkup := nil; FCustomTokenMarkup := nil;
FCustomCommentTokenMarkup := nil;
FCustomTokenMarkupSlash := nil;
FCustomTokenMarkupAnsi := nil;
FCustomTokenMarkupBor := nil;
for i := 0 to 255 do begin for i := 0 to 255 do begin
for j := 0 to length(FCustomTokenInfo[i].Lists) - 1 do for j := 0 to length(FCustomTokenInfo[i].Lists) - 1 do
FreeAndNil(FCustomTokenInfo[i].Lists[j].List); FreeAndNil(FCustomTokenInfo[i].Lists[j].List);
@ -1583,8 +1607,11 @@ begin
end; end;
for i := 0 to Length(FSynCustomTokens) - 1 do begin for i := 0 to Length(FSynCustomTokens) - 1 do begin
if FSynCustomTokens[i].MatchTokenKinds = [] then mtk := FSynCustomTokens[i].MatchTokenKinds;
if mtk = [] then
continue; continue;
if tkComment in mtk then
mtk := mtk - [tkComment] + [tkSlashComment, tkAnsiComment, tkBorComment];
for j := 0 to FSynCustomTokens[i].FTokens.Count - 1 do begin for j := 0 to FSynCustomTokens[i].FTokens.Count - 1 do begin
t := FSynCustomTokens[i].FTokens[j]; t := FSynCustomTokens[i].FTokens[j];
@ -1596,8 +1623,25 @@ begin
fToIdent := 0; fToIdent := 0;
h := KeyHash and 255; h := KeyHash and 255;
FCustomTokenInfo[h].MatchTokenKinds := FCustomTokenInfo[h].MatchTokenKinds + FSynCustomTokens[i].MatchTokenKinds; FCustomTokenInfo[h].MatchTokenKinds := FCustomTokenInfo[h].MatchTokenKinds + mtk;
for tk in FSynCustomTokens[i].MatchTokenKinds do begin for tk in mtk do begin
case tk of
tkSlashComment:
if t = '*' then begin
FCustomTokenMarkupSlash := FSynCustomTokens[i].Markup;
continue;
end;
tkAnsiComment:
if t = '*' then begin
FCustomTokenMarkupAnsi := FSynCustomTokens[i].Markup;
continue;
end;
tkBorComment:
if t = '*' then begin
FCustomTokenMarkupBor := FSynCustomTokens[i].Markup;
continue;
end;
end;
Lst := FindList(h, tk); Lst := FindList(h, tk);
Lst^.List.AddObject(UpperCase(t), FSynCustomTokens[i]); Lst^.List.AddObject(UpperCase(t), FSynCustomTokens[i]);
end; end;
@ -3980,6 +4024,7 @@ begin
FPasDocWordList := TStringList.Create; FPasDocWordList := TStringList.Create;
FCustomTokenMergedMarkup := TSynSelectedColorMergeResult.Create; FCustomTokenMergedMarkup := TSynSelectedColorMergeResult.Create;
FCustomCommentTokenMergedMarkup := TSynSelectedColorMergeResult.Create;
FNestedBracketAttribs := TSynHighlighterAttributesModifierCollection.Create(Self); FNestedBracketAttribs := TSynHighlighterAttributesModifierCollection.Create(Self);
FNestedBracketAttribs.OnAttributeChange := @DefHighlightChange; FNestedBracketAttribs.OnAttributeChange := @DefHighlightChange;
@ -4010,6 +4055,7 @@ begin
FreeAndNil(FCurStructMemberExtraAttri); FreeAndNil(FCurStructMemberExtraAttri);
FreeAndNil(FCurPasDocAttri); FreeAndNil(FCurPasDocAttri);
FreeAndNil(FCustomTokenMergedMarkup); FreeAndNil(FCustomTokenMergedMarkup);
FreeAndNil(FCustomCommentTokenMergedMarkup);
FreeAndNil(FPasDocWordList); FreeAndNil(FPasDocWordList);
CustomTokenCount := 0; CustomTokenCount := 0;
for i := 0 to 255 do for i := 0 to 255 do
@ -4041,6 +4087,8 @@ begin
FSynPasRangeInfo.MinLevelRegion := FSynPasRangeInfo.EndLevelRegion; FSynPasRangeInfo.MinLevelRegion := FSynPasRangeInfo.EndLevelRegion;
fLineNumber := LineNumber; fLineNumber := LineNumber;
FAtLineStart := True; FAtLineStart := True;
FInString := False;
FCustomCommentTokenMarkup := nil;
if not IsCollectingNodeInfo then if not IsCollectingNodeInfo then
Next; Next;
end; { SetLine } end; { SetLine }
@ -4132,26 +4180,50 @@ end;
procedure TSynPasSyn.BorProc; procedure TSynPasSyn.BorProc;
var var
p: LongInt; p: LongInt;
IsInWord, WasInWord, ct: Boolean;
begin begin
p:=Run; FCustomCommentTokenMarkup := FCustomTokenMarkupBor;
fTokenID := tkComment; fTokenID := tkComment;
if rsIDEDirective in fRange then if rsIDEDirective in fRange then
fTokenID := tkIDEDirective; fTokenID := tkIDEDirective;
if FUsePasDoc and not(rsIDEDirective in fRange) and (fLine[Run] = '@') then begin if (not (FIsInNextToEOL or IsScanning)) and not(rsIDEDirective in fRange) then begin
if FUsePasDoc and (fLine[Run] = '@') then begin
if CheckPasDoc then if CheckPasDoc then
exit; exit;
end; end;
if (IsLetterChar[fline[Run]]) and
( (Run = 0) or
not((IsLetterChar[fline[Run-1]] or IsUnderScoreOrNumberChar[fline[Run-1]]))
)
then begin
if GetCustomTokenAndNext(tkBorComment, FCustomTokenMarkup) then
exit;
end;
end;
IsInWord := False;
WasInWord := (FIsInNextToEOL or IsScanning) or (rsIDEDirective in fRange); // don't run checks
p:=Run;
repeat repeat
case fLine[p] of case fLine[p] of
#0,#10,#13: break; #0,#10,#13: break;
'}': '}': begin
if (not (FIsInNextToEOL or IsScanning)) and not(rsIDEDirective in fRange) then begin
Run := p;
ct := GetCustomSymbolToken(tkAnsiComment, 1, FCustomTokenMarkup, Run <> fTokenPos);
if ct and (Run <> fTokenPos) then
exit;
end;
if TopPascalCodeFoldBlockType=cfbtNestedComment then if TopPascalCodeFoldBlockType=cfbtNestedComment then
begin begin
Run:=p; Run:=p;
EndPascalCodeFoldBlock; EndPascalCodeFoldBlock;
p:=Run; p:=Run;
if FCustomTokenMarkup <> nil then begin
inc(Run);
exit;
end;
end else begin end else begin
fRange := fRange - [rsBor, rsIDEDirective]; fRange := fRange - [rsBor, rsIDEDirective];
Inc(p); Inc(p);
@ -4159,12 +4231,22 @@ begin
EndPascalCodeFoldBlock; EndPascalCodeFoldBlock;
break; break;
end; end;
end;
'{': '{':
if NestedComments then begin if NestedComments then begin
Run := p;
if (not (FIsInNextToEOL or IsScanning)) and not(rsIDEDirective in fRange) then begin
ct := GetCustomSymbolToken(tkAnsiComment, 1, FCustomTokenMarkup, Run <> fTokenPos);
if ct and (Run <> fTokenPos) then
exit;
end;
fStringLen := 1; fStringLen := 1;
Run:=p;
StartPascalCodeFoldBlock(cfbtNestedComment); StartPascalCodeFoldBlock(cfbtNestedComment);
p:=Run; p:=Run;
if FCustomTokenMarkup <> nil then begin
inc(Run);
exit;
end;
end; end;
'@': begin '@': begin
if fLine[p+1] = '@' then if fLine[p+1] = '@' then
@ -4177,8 +4259,20 @@ begin
inc(p) inc(p)
end; end;
end; end;
otherwise begin
if (not WasInWord) and IsLetterChar[fline[p]] then begin
Run := p;
if GetCustomTokenAndNext(tkBorComment, FCustomTokenMarkup, True) then
exit;
end
end;
end; end;
Inc(p); Inc(p);
if (not (FIsInNextToEOL or IsScanning)) and not(rsIDEDirective in fRange) then begin
WasInWord := IsInWord;
IsInWord := (IsLetterChar[fline[p]] or IsUnderScoreOrNumberChar[fline[p]]);
end;
until (p>=fLineLen); until (p>=fLineLen);
Run:=p; Run:=p;
end; end;
@ -4401,10 +4495,18 @@ begin
end; end;
end end
else begin else begin
fTokenID := tkComment;
fRange := fRange + [rsBor]; fRange := fRange + [rsBor];
dec(Run); dec(Run);
StartPascalCodeFoldBlock(cfbtBorCommand); StartPascalCodeFoldBlock(cfbtBorCommand);
FCustomCommentTokenMarkup := FCustomTokenMarkupBor;
if not (FIsInNextToEOL or IsScanning) then
GetCustomSymbolToken(tkBorComment, 1, FCustomTokenMarkup);
inc(Run); inc(Run);
if FCustomTokenMarkup <> nil then
exit;
end; end;
if FUsePasDoc and (fLine[Run] = '@') and CheckPasDoc(True) then if FUsePasDoc and (fLine[Run] = '@') and CheckPasDoc(True) then
exit; exit;
@ -4631,21 +4733,45 @@ begin
end; end;
procedure TSynPasSyn.AnsiProc; procedure TSynPasSyn.AnsiProc;
var
IsInWord, WasInWord, ct: Boolean;
begin begin
fTokenID := tkComment; fTokenID := tkComment;
FCustomCommentTokenMarkup := FCustomTokenMarkupAnsi;
if (not (FIsInNextToEOL or IsScanning)) then begin
if FUsePasDoc and (fLine[Run] = '@') then begin if FUsePasDoc and (fLine[Run] = '@') then begin
if CheckPasDoc then if CheckPasDoc then
exit; exit;
end; end;
if (IsLetterChar[fline[Run]]) and
( (Run = 0) or
not((IsLetterChar[fline[Run-1]] or IsUnderScoreOrNumberChar[fline[Run-1]]))
)
then begin
if GetCustomTokenAndNext(tkAnsiComment, FCustomTokenMarkup) then
exit;
end;
end;
IsInWord := False;
WasInWord := (FIsInNextToEOL or IsScanning); // don't run checks
repeat repeat
if fLine[Run]=#0 then if fLine[Run]=#0 then
break break
else if (fLine[Run] = '*') and (fLine[Run + 1] = ')') then else if (fLine[Run] = '*') and (fLine[Run + 1] = ')') then
begin begin
if not (FIsInNextToEOL or IsScanning) then begin
ct := GetCustomSymbolToken(tkAnsiComment, 2, FCustomTokenMarkup, Run <> fTokenPos);
if ct and (Run <> fTokenPos) then
exit;
end;
Inc(Run, 2); Inc(Run, 2);
if TopPascalCodeFoldBlockType=cfbtNestedComment then begin if TopPascalCodeFoldBlockType=cfbtNestedComment then begin
EndPascalCodeFoldBlock; EndPascalCodeFoldBlock;
if FCustomTokenMarkup <> nil then
exit;
end else begin end else begin
fRange := fRange - [rsAnsi]; fRange := fRange - [rsAnsi];
if TopPascalCodeFoldBlockType=cfbtAnsiComment then if TopPascalCodeFoldBlockType=cfbtAnsiComment then
@ -4657,9 +4783,16 @@ begin
if (pcsNestedComments in ModeSwitches) and if (pcsNestedComments in ModeSwitches) and
(fLine[Run] = '(') and (fLine[Run + 1] = '*') then (fLine[Run] = '(') and (fLine[Run + 1] = '*') then
begin begin
if not (FIsInNextToEOL or IsScanning) then begin
ct := GetCustomSymbolToken(tkAnsiComment, 2, FCustomTokenMarkup, Run <> fTokenPos);
if ct and (Run <> fTokenPos) then
exit;
end;
fStringLen := 2; fStringLen := 2;
StartPascalCodeFoldBlock(cfbtNestedComment); StartPascalCodeFoldBlock(cfbtNestedComment);
Inc(Run,2); Inc(Run,2);
if FCustomTokenMarkup <> nil then
exit;
end else end else
if FUsePasDoc and (fLine[Run] = '@') then begin if FUsePasDoc and (fLine[Run] = '@') then begin
if fLine[Run+1] = '@' then if fLine[Run+1] = '@' then
@ -4669,8 +4802,18 @@ begin
exit; exit;
Inc(Run); Inc(Run);
end end
else
if (not WasInWord) and IsLetterChar[fline[Run]] then begin
if GetCustomTokenAndNext(tkAnsiComment, FCustomTokenMarkup, True) then
exit;
end
else else
Inc(Run); Inc(Run);
if not (FIsInNextToEOL or IsScanning) then begin
WasInWord := IsInWord;
IsInWord := (IsLetterChar[fline[Run]] or IsUnderScoreOrNumberChar[fline[Run]]);
end;
until (Run>=fLineLen) or (fLine[Run] in [#0, #10, #13]); until (Run>=fLineLen) or (fLine[Run] in [#0, #10, #13]);
end; end;
@ -4719,7 +4862,14 @@ begin
fStringLen := 2; // length of "(*" fStringLen := 2; // length of "(*"
Dec(Run); Dec(Run);
StartPascalCodeFoldBlock(cfbtAnsiComment); StartPascalCodeFoldBlock(cfbtAnsiComment);
FCustomCommentTokenMarkup := FCustomTokenMarkupAnsi;
if not (FIsInNextToEOL or IsScanning) then
GetCustomSymbolToken(tkAnsiComment, 2, FCustomTokenMarkup);
Inc(Run, 2); Inc(Run, 2);
if FCustomTokenMarkup <> nil then
exit;
if not (fLine[Run] in [#0, #10, #13]) then begin if not (fLine[Run] in [#0, #10, #13]) then begin
if FUsePasDoc and (fLine[Run] = '@') and CheckPasDoc(True) then if FUsePasDoc and (fLine[Run] = '@') and CheckPasDoc(True) then
exit; exit;
@ -4830,8 +4980,6 @@ begin
end; end;
procedure TSynPasSyn.EqualSignProc; procedure TSynPasSyn.EqualSignProc;
var
tfb: TPascalCodeFoldBlockType;
begin begin
inc(Run); inc(Run);
fTokenID := tkSymbol; fTokenID := tkSymbol;
@ -4913,6 +5061,9 @@ end;
procedure TSynPasSyn.SlashProc; procedure TSynPasSyn.SlashProc;
begin begin
if fLine[Run+1] = '/' then begin if fLine[Run+1] = '/' then begin
FCustomCommentTokenMarkup := FCustomTokenMarkupSlash;
FIsInSlash := True;
fTokenID := tkComment; fTokenID := tkComment;
if FAtLineStart then begin if FAtLineStart then begin
fRange := fRange + [rsSlash]; fRange := fRange + [rsSlash];
@ -4920,19 +5071,16 @@ begin
if not(TopPascalCodeFoldBlockType = cfbtSlashComment) then if not(TopPascalCodeFoldBlockType = cfbtSlashComment) then
StartPascalCodeFoldBlock(cfbtSlashComment); StartPascalCodeFoldBlock(cfbtSlashComment);
end; end;
if (not (FIsInNextToEOL or IsScanning)) and
GetCustomSymbolToken(tkSlashComment, 2, FCustomTokenMarkup)
then begin
inc(Run, 2); inc(Run, 2);
FIsInSlash := True;
while not(fLine[Run] in [#0, #10, #13]) do
if FUsePasDoc and (fLine[Run] = '@') then begin
if fLine[Run+1] = '@' then
inc(Run, 2)
else
if CheckPasDoc(True) then
exit; exit;
Inc(Run); end;
end inc(Run, 2);
else
Inc(Run); SlashCommentProc;
end else begin end else begin
Inc(Run); Inc(Run);
fTokenID := tkSymbol; fTokenID := tkSymbol;
@ -4941,27 +5089,41 @@ begin
end; end;
procedure TSynPasSyn.SlashContinueProc; procedure TSynPasSyn.SlashContinueProc;
var
AtSlashOpen: Boolean;
begin begin
if FIsInSlash and (fLine[Run] = '@') then begin if FIsInSlash and (not (FIsInNextToEOL or IsScanning)) then begin
FCustomCommentTokenMarkup := FCustomTokenMarkupSlash;
fTokenID := tkComment;
if (fLine[Run] = '@') then begin
if CheckPasDoc then if CheckPasDoc then
exit; exit;
end; end;
if (IsLetterChar[fline[Run]]) and
( (Run = 0) or
not((IsLetterChar[fline[Run-1]] or IsUnderScoreOrNumberChar[fline[Run-1]]))
)
then begin
if GetCustomTokenAndNext(tkSlashComment, FCustomTokenMarkup) then
exit;
end;
end;
if FIsInSlash or ((fLine[Run] = '/') and (fLine[Run + 1] = '/')) then begin AtSlashOpen := (fLine[Run] = '/') and (fLine[Run + 1] = '/') and not FIsInSlash;
if FIsInSlash or AtSlashOpen then begin
FIsInSlash := True; FIsInSlash := True;
// Continue fold block // Continue fold block
fTokenID := tkComment; fTokenID := tkComment;
while not(fLine[Run] in [#0, #10, #13]) do
if FUsePasDoc and (fLine[Run] = '@') then begin if (not (FIsInNextToEOL or IsScanning)) and AtSlashOpen and
if fLine[Run+1] = '@' then GetCustomSymbolToken(tkSlashComment, 2, FCustomTokenMarkup)
inc(Run, 2) then begin
else inc(Run, 2);
if CheckPasDoc(True) then
exit; exit;
Inc(Run); end;
end
else SlashCommentProc;
Inc(Run);
exit; exit;
end; end;
@ -4982,6 +5144,37 @@ begin
Next; Next;
end; end;
procedure TSynPasSyn.SlashCommentProc;
var
IsInWord, WasInWord: Boolean;
begin
IsInWord := False;
WasInWord := (FIsInNextToEOL or IsScanning); // don't run checks
while not(fLine[Run] in [#0, #10, #13]) do begin
if FUsePasDoc and (fLine[Run] = '@') then begin
if fLine[Run+1] = '@' then
inc(Run, 2)
else
if CheckPasDoc(True) then
exit;
Inc(Run);
end
else
if (not WasInWord) and IsLetterChar[fline[Run]] then begin
if GetCustomTokenAndNext(tkSlashComment, FCustomTokenMarkup, True) then
exit;
end
else
Inc(Run);
if not (FIsInNextToEOL or IsScanning) then begin
WasInWord := IsInWord;
IsInWord := (IsLetterChar[fline[Run]] or IsUnderScoreOrNumberChar[fline[Run]]);
end;
end;
end;
procedure TSynPasSyn.SpaceProc; procedure TSynPasSyn.SpaceProc;
begin begin
inc(Run); inc(Run);
@ -5002,18 +5195,82 @@ begin
end; end;
procedure TSynPasSyn.StringProc; procedure TSynPasSyn.StringProc;
var
IsInWord, WasInWord, ct: Boolean;
begin begin
fTokenID := tkString; fTokenID := tkString;
if FInString then begin
if not (FIsInNextToEOL or IsScanning) then begin
if (fLine[Run] = '''') and (fLine[Run+1] = '''') and
GetCustomSymbolToken(tkString, 2, FCustomTokenMarkup)
then begin
inc(Run, 2);
exit;
end;
if (IsLetterChar[fline[Run]]) and
( (Run = 0) or
not((IsLetterChar[fline[Run-1]] or IsUnderScoreOrNumberChar[fline[Run-1]]))
)
then begin
if GetCustomTokenAndNext(tkString, FCustomTokenMarkup) then
exit;
end;
end;
end
else begin
FInString := True;
if not (FIsInNextToEOL or IsScanning) and
GetCustomSymbolToken(tkString, 1, FCustomTokenMarkup)
then begin
Inc(Run); Inc(Run);
exit;
end;
Inc(Run);
end;
IsInWord := False;
WasInWord := (FIsInNextToEOL or IsScanning); // don't run checks
while (not (fLine[Run] in [#0, #10, #13])) do begin while (not (fLine[Run] in [#0, #10, #13])) do begin
if fLine[Run] = '''' then begin if fLine[Run] = '''' then begin
if (fLine[Run+1] = '''') then begin
// escaped
if (not (FIsInNextToEOL or IsScanning)) and
GetCustomSymbolToken(tkString, 2, FCustomTokenMarkup, Run <> fTokenPos)
then begin
if (Run = fTokenPos) then
inc(Run, 2);
exit
end;
Inc(Run);
end
else begin
// string end
if not (FIsInNextToEOL or IsScanning) then begin
ct := GetCustomSymbolToken(tkString, 1, FCustomTokenMarkup, Run <> fTokenPos);
if ct and (Run <> fTokenPos) then
exit;
end;
Inc(Run); Inc(Run);
if (fLine[Run] <> '''') then
break; break;
end; end;
Inc(Run); end
else
if (not WasInWord) and IsLetterChar[fline[Run]] then begin
if GetCustomTokenAndNext(tkString, FCustomTokenMarkup, True) then
exit;
end; end;
Inc(Run);
if not (FIsInNextToEOL or IsScanning) then begin
WasInWord := IsInWord;
IsInWord := (IsLetterChar[fline[Run]] or IsUnderScoreOrNumberChar[fline[Run]]);
end;
end;
FInString := False;
// modifiers like "alias" take a string as argument // modifiers like "alias" take a string as argument
if (PasCodeFoldRange.BracketNestLevel = 0) then begin if (PasCodeFoldRange.BracketNestLevel = 0) then begin
if (fRange * [rsInProcHeader, rsProperty, rsAfterEqualOrColon, rsWasInProcHeader] = [rsInProcHeader]) and if (fRange * [rsInProcHeader, rsProperty, rsAfterEqualOrColon, rsWasInProcHeader] = [rsInProcHeader]) and
@ -5085,26 +5342,67 @@ begin
; ;
end; end;
procedure TSynPasSyn.CheckForAdditionalAttributes; function TSynPasSyn.GetCustomSymbolToken(ATokenID: TtkTokenKindEx; ALen: integer; out
ACustomMarkup: TSynHighlighterAttributesModifier; APeekOnly: boolean): boolean;
var var
i, h: integer; TempMarkup: TSynHighlighterAttributesModifier;
CustTkList: TStringList;
tfb: TPascalCodeFoldBlockType;
begin begin
h := FTokenHashKey and 255; ACustomMarkup := nil;
if FTokenID in FCustomTokenInfo[h].MatchTokenKinds then begin Result := GetCustomToken(ATokenID, 0, @fLine[Run], ALen, TempMarkup);
CustTkList := nil; if Result and (not APeekOnly) then
for i := 0 to Length(FCustomTokenInfo[h].Lists) - 1 do ACustomMarkup := TempMarkup;
if FCustomTokenInfo[h].Lists[i].TokenKind = FTokenID then begin end;
CustTkList := FCustomTokenInfo[h].Lists[i].List;
function TSynPasSyn.GetCustomTokenAndNext(ATokenID: TtkTokenKindEx; out
ACustomMarkup: TSynHighlighterAttributesModifier; APeekOnly: boolean): boolean;
var
h: Integer;
TempTokenMarkup: TSynHighlighterAttributesModifier;
begin
ACustomMarkup := nil;
fToIdent := Run;
h := KeyHash;
Result := fStringLen > 0;
if not Result then
exit;
Result := GetCustomToken(ATokenID, byte(h and 255), @fLine[Run], fStringLen, TempTokenMarkup);
if Result and (not APeekOnly) then begin
ACustomMarkup := TempTokenMarkup;
Run := Run + fStringLen;
end;
end;
function TSynPasSyn.GetCustomToken(ATokenID: TtkTokenKindEx; AnHash: byte; ATokenStart: PChar;
ATokenLen: integer; out ACustomMarkup: TSynHighlighterAttributesModifier): boolean;
var
CustTkList: TStringList;
i, j: integer;
s: string;
begin
Result := False;
ACustomMarkup := nil;
if ATokenID in FCustomTokenInfo[AnHash].MatchTokenKinds then begin
for i := 0 to Length(FCustomTokenInfo[AnHash].Lists) - 1 do
if FCustomTokenInfo[AnHash].Lists[i].TokenKind = ATokenID then begin
CustTkList := FCustomTokenInfo[AnHash].Lists[i].List;
if CustTkList <> nil then begin
SetString(s, ATokenStart, ATokenLen);
j := CustTkList.IndexOf(UpperCase(s));
Result := j >= 0;
if Result then
ACustomMarkup := TSynPasSynCustomToken(CustTkList.Objects[j]).Markup;
end;
break; break;
end; end;
if CustTkList <> nil then begin
i := CustTkList.IndexOf(UpperCase(GetToken));
if i >= 0 then
FCustomTokenMarkup := TSynPasSynCustomToken(CustTkList.Objects[i]).Markup;
end;
end; end;
end;
procedure TSynPasSyn.CheckForAdditionalAttributes;
var
tfb: TPascalCodeFoldBlockType;
begin
if not (FTokenID in [tkString, tkComment]) then
GetCustomToken(FTokenID, byte(FTokenHashKey and 255), @fLine[fTokenPos], Run - fTokenPos, FCustomTokenMarkup);
case FTokenState of case FTokenState of
tsAtProcName: begin tsAtProcName: begin
@ -5280,13 +5578,16 @@ begin
BorProc BorProc
else if rsDirective in fRange then else if rsDirective in fRange then
DirectiveProc DirectiveProc
else if rsSlash in fRange then else if (rsSlash in fRange) or FIsInSlash then
SlashContinueProc SlashContinueProc
else if FInString then
StringProc
else begin else begin
FNextTokenState := tsNone; FNextTokenState := tsNone;
OldNestLevel := PasCodeFoldRange.BracketNestLevel; OldNestLevel := PasCodeFoldRange.BracketNestLevel;
if (PasCodeFoldRange.BracketNestLevel = 1) then // procedure foo; [attr...] if (PasCodeFoldRange.BracketNestLevel = 1) then // procedure foo; [attr...]
FOldRange := FOldRange - [rsWasInProcHeader]; FOldRange := FOldRange - [rsWasInProcHeader];
FCustomCommentTokenMarkup := nil;
FTokenExtraAttribs := []; FTokenExtraAttribs := [];
FTokenTypeDeclExtraAttrib := eaNone; FTokenTypeDeclExtraAttrib := eaNone;
//if rsAtEqual in fRange then //if rsAtEqual in fRange then
@ -5549,6 +5850,11 @@ begin
FCustomTokenMergedMarkup.Merge(FCustomTokenMarkup); FCustomTokenMergedMarkup.Merge(FCustomTokenMarkup);
Result := FCustomTokenMergedMarkup; Result := FCustomTokenMergedMarkup;
end; end;
if FCustomCommentTokenMarkup <> nil then begin
FCustomCommentTokenMergedMarkup.Assign(Result);
FCustomCommentTokenMergedMarkup.Merge(FCustomCommentTokenMarkup);
Result := FCustomCommentTokenMergedMarkup;
end;
if (FTokenID = tkSymbol) and (Run - fTokenPos = 1) and (fLine[fTokenPos] in ['(', ')']) if (FTokenID = tkSymbol) and (Run - fTokenPos = 1) and (fLine[fTokenPos] in ['(', ')'])
then begin then begin
@ -5605,7 +5911,8 @@ end;
function TSynPasSyn.GetTokenIsCommentEnd: Boolean; function TSynPasSyn.GetTokenIsCommentEnd: Boolean;
begin begin
Result := (FTokenID = tkComment) and Result := (FTokenID = tkComment) and
(FRange * [rsAnsi, rsBor, rsSlash] = []); // rsIDEDirective (FRange * [rsAnsi, rsBor, rsSlash] = []) and // rsIDEDirective
(not (FIsInSlash and (Run < fLineLen)));
end; end;
function TSynPasSyn.GetRange: Pointer; function TSynPasSyn.GetRange: Pointer;
@ -7244,7 +7551,7 @@ begin
FOnChange(Self); FOnChange(Self);
end; end;
procedure TSynPasSynCustomToken.SetMatchTokenKinds(AValue: TtkTokenKinds); procedure TSynPasSynCustomToken.SetMatchTokenKinds(AValue: TtkTokenKindExs);
begin begin
if FMatchTokenKinds = AValue then Exit; if FMatchTokenKinds = AValue then Exit;
FMatchTokenKinds := AValue; FMatchTokenKinds := AValue;

View File

@ -3622,6 +3622,11 @@ resourcestring
lisCodeToolsOptsNewLine = 'Newline'; lisCodeToolsOptsNewLine = 'Newline';
lisCodeToolsOptsSpace = 'Space'; lisCodeToolsOptsSpace = 'Space';
lisCodeToolsOptsSymbol = 'Symbol'; lisCodeToolsOptsSymbol = 'Symbol';
lisCodeToolsOptsString = 'String';
lisCodeToolsOptsComment= 'Comment';
lisCodeToolsOptsCommentSlash= 'Slash Comment: //';
lisCodeToolsOptsCommentAnsi = 'Ansi Comment: (*';
lisCodeToolsOptsCommentBor = 'Curly Comment: {';
lisCodeToolsOptsBracket = 'Bracket'; lisCodeToolsOptsBracket = 'Bracket';
lisCodeToolsOptsCaret = 'Caret (^)'; lisCodeToolsOptsCaret = 'Caret (^)';

View File

@ -4042,7 +4042,7 @@ begin
TokenTxt, TokenType, Start, Attri); TokenTxt, TokenType, Start, Attri);
inc(xy.x); inc(xy.x);
if Start + Length(TokenTxt) = xy.X then begin if Start + Length(TokenTxt) = xy.X then begin
IdentFound := TtkTokenKind(TokenType) in [tkAsm, tkComment, tkIdentifier, tkString]; IdentFound := (TokenType >= 0) and (TtkTokenKind(TokenType) in [tkAsm, tkComment, tkIdentifier, tkString]);
StringFound := TtkTokenKind(TokenType) = tkString; StringFound := TtkTokenKind(TokenType) = tkString;
end; end;
cont := True; cont := True;
@ -4050,7 +4050,7 @@ begin
if not (IdentFound or StringFound) then begin if not (IdentFound or StringFound) then begin
ASrcEdit.EditorComponent.GetHighlighterAttriAtRowColEx(xy, ASrcEdit.EditorComponent.GetHighlighterAttriAtRowColEx(xy,
TokenTxt, TokenType, Start, Attri, cont); TokenTxt, TokenType, Start, Attri, cont);
IdentFound := TtkTokenKind(TokenType) in [tkAsm, tkComment, tkIdentifier, tkString]; IdentFound := (TokenType >= 0) and (TtkTokenKind(TokenType) in [tkAsm, tkComment, tkIdentifier, tkString]);
StringFound := TtkTokenKind(TokenType) = tkString; StringFound := TtkTokenKind(TokenType) = tkString;
end; end;
end; end;

View File

@ -379,9 +379,9 @@ type
TSynHighlighterLazCustomPasAttribute = class(TSynHighlighterAttributesModifier) TSynHighlighterLazCustomPasAttribute = class(TSynHighlighterAttributesModifier)
private private
FCustomWords: TStrings; FCustomWords: TStrings;
FCustomWordTokenKind: TtkTokenKind; FCustomWordTokenKind: TtkTokenKindEx;
procedure DoWordsChanged(Sender: TObject); procedure DoWordsChanged(Sender: TObject);
procedure SetCustomWordTokenKind(AValue: TtkTokenKind); procedure SetCustomWordTokenKind(AValue: TtkTokenKindEx);
protected protected
procedure AssignFrom(Src: TLazSynCustomTextAttributes); override; procedure AssignFrom(Src: TLazSynCustomTextAttributes); override;
procedure DoClear; override; procedure DoClear; override;
@ -390,7 +390,7 @@ type
destructor Destroy; override; destructor Destroy; override;
property CustomWords: TStrings read FCustomWords; property CustomWords: TStrings read FCustomWords;
published published
property CustomWordTokenKind: TtkTokenKind read FCustomWordTokenKind write SetCustomWordTokenKind; property CustomWordTokenKind: TtkTokenKindEx read FCustomWordTokenKind write SetCustomWordTokenKind;
end; end;
{ TIDESynPasSyn } { TIDESynPasSyn }
@ -2155,7 +2155,7 @@ end;
{ TSynHighlighterLazCustomPasAttribute } { TSynHighlighterLazCustomPasAttribute }
procedure TSynHighlighterLazCustomPasAttribute.SetCustomWordTokenKind(AValue: TtkTokenKind); procedure TSynHighlighterLazCustomPasAttribute.SetCustomWordTokenKind(AValue: TtkTokenKindEx);
begin begin
if FCustomWordTokenKind = AValue then Exit; if FCustomWordTokenKind = AValue then Exit;
FCustomWordTokenKind := AValue; FCustomWordTokenKind := AValue;

View File

@ -258,6 +258,11 @@ begin
2: FCurHighlightElement.CustomWordTokenKind := tkModifier; 2: FCurHighlightElement.CustomWordTokenKind := tkModifier;
3: FCurHighlightElement.CustomWordTokenKind := tkNumber; 3: FCurHighlightElement.CustomWordTokenKind := tkNumber;
4: FCurHighlightElement.CustomWordTokenKind := tkSymbol; 4: FCurHighlightElement.CustomWordTokenKind := tkSymbol;
5: FCurHighlightElement.CustomWordTokenKind := tkString;
6: FCurHighlightElement.CustomWordTokenKind := tkComment;
7: FCurHighlightElement.CustomWordTokenKind := tkSlashComment;
8: FCurHighlightElement.CustomWordTokenKind := tkAnsiComment;
9: FCurHighlightElement.CustomWordTokenKind := tkBorComment;
end; end;
end; end;
@ -790,6 +795,11 @@ begin
tkModifier: dropCustomWordKind.ItemIndex := 2; tkModifier: dropCustomWordKind.ItemIndex := 2;
tkNumber: dropCustomWordKind.ItemIndex := 3; tkNumber: dropCustomWordKind.ItemIndex := 3;
tkSymbol: dropCustomWordKind.ItemIndex := 4; tkSymbol: dropCustomWordKind.ItemIndex := 4;
tkString: dropCustomWordKind.ItemIndex := 5;
tkComment: dropCustomWordKind.ItemIndex := 6;
tkSlashComment: dropCustomWordKind.ItemIndex := 7;
tkAnsiComment: dropCustomWordKind.ItemIndex := 8;
tkBorComment: dropCustomWordKind.ItemIndex := 9;
end; end;
UpdatingColor := False; UpdatingColor := False;
@ -870,6 +880,11 @@ begin
dropCustomWordKind.Items.Add(dlgModifier); dropCustomWordKind.Items.Add(dlgModifier);
dropCustomWordKind.Items.Add(lisCodeToolsOptsNumber); dropCustomWordKind.Items.Add(lisCodeToolsOptsNumber);
dropCustomWordKind.Items.Add(lisCodeToolsOptsSymbol); dropCustomWordKind.Items.Add(lisCodeToolsOptsSymbol);
dropCustomWordKind.Items.Add(lisCodeToolsOptsString);
dropCustomWordKind.Items.Add(lisCodeToolsOptsComment);
dropCustomWordKind.Items.Add(lisCodeToolsOptsCommentSlash);
dropCustomWordKind.Items.Add(lisCodeToolsOptsCommentAnsi);
dropCustomWordKind.Items.Add(lisCodeToolsOptsCommentBor);
dropCustomWordKind.ItemIndex := 0; dropCustomWordKind.ItemIndex := 0;
//Constraints.MinHeight := max(Constraints.MinHeight, //Constraints.MinHeight := max(Constraints.MinHeight,