mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-10 20:09:24 +01:00
SynEdit: Refactored fold-highlighters: unify methods to get fold-nest info
git-svn-id: trunk@35115 -
This commit is contained in:
parent
e10dc0f7ea
commit
7a03599f16
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -2438,6 +2438,8 @@ components/synedit/test/testbasicsynedit.pas svneol=native#text/pascal
|
||||
components/synedit/test/testblockindent.pas svneol=native#text/pascal
|
||||
components/synedit/test/testbookmarks.pas svneol=native#text/pascal
|
||||
components/synedit/test/testfoldedview.pas svneol=native#text/pascal
|
||||
components/synedit/test/testhighlighterlfm.pas svneol=native#text/pascal
|
||||
components/synedit/test/testhighlightfoldbase.pas svneol=native#text/pascal
|
||||
components/synedit/test/testhighlightmulti.pas svneol=native#text/pascal
|
||||
components/synedit/test/testhighlightpas.pas svneol=native#text/pascal
|
||||
components/synedit/test/testhighlightxml.pas svneol=native#text/pascal
|
||||
|
||||
@ -284,6 +284,50 @@ type
|
||||
end;
|
||||
|
||||
TSynEditFoldProviderNodeInfoList = array of TSynEditFoldProviderNodeInfo;
|
||||
TSynEditFoldProvider = class;
|
||||
|
||||
(* TLazSynEditNestedFoldsList
|
||||
Provides Info on all foldable-blocks containing a given line (0 based index).
|
||||
That are:
|
||||
- All foldable blocks opening on a previous line, that are still open
|
||||
at the start of the line. (May end on this line or later)
|
||||
- Foldable blocks opening on that line. (OpeningOnLineCount)
|
||||
|
||||
The data is NOT automatically invalidated.
|
||||
*)
|
||||
|
||||
TLazSynEditNestedFoldsListEntry = record
|
||||
HNode: TSynFoldNodeInfo; // Highlighter Node
|
||||
//FNode: TSynTextFoldAVLNode; // AvlFoldNode
|
||||
//Text, Keyword: String;
|
||||
LineIdx: TLineIdx;
|
||||
//ColIndex: Integer;
|
||||
//OpenCount: Integer;
|
||||
end;
|
||||
|
||||
TLazSynEditNestedFoldsList = class
|
||||
private
|
||||
FFoldProvider: TSynEditFoldProvider;
|
||||
FFoldGroup: Integer;
|
||||
FLine: TLineIdx;
|
||||
procedure SetFoldGroup(AValue: Integer);
|
||||
procedure SetLines(AValue: TLineIdx);
|
||||
private
|
||||
FGroupCount: Integer;
|
||||
FGroupEndLevels, FGroupEndLevelsAtEval: Array of integer;
|
||||
FCount, FOpeningOnLineCount: Integer;
|
||||
FNestInfo: Array of TLazSynEditNestedFoldsListEntry;
|
||||
FEvaluationIndex: Integer;
|
||||
procedure InitSubGroupEndLevels;
|
||||
procedure InitNestInfoForIndex(AnIndex: Integer);
|
||||
public
|
||||
constructor Create(aFoldProvider: TSynEditFoldProvider);
|
||||
procedure Clear;
|
||||
function Count: Integer;
|
||||
function OpeningOnLineCount: Integer;
|
||||
property Line: TLineIdx read FLine write SetLines;
|
||||
property FoldGroup: Integer read FFoldGroup write SetFoldGroup;
|
||||
end;
|
||||
|
||||
TSynEditFoldProvider = class
|
||||
private
|
||||
@ -292,17 +336,21 @@ type
|
||||
FSelection: TSynEditSelection;
|
||||
FFoldTree : TSynTextFoldAVLTree;
|
||||
function GetFoldsAvailable: Boolean;
|
||||
function GetHighLighterWithLines: TSynCustomFoldHighlighter;
|
||||
function GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
|
||||
function GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications;
|
||||
procedure SetHighLighter(const AValue: TSynCustomFoldHighlighter);
|
||||
protected
|
||||
property HighLighterWithLines: TSynCustomFoldHighlighter read GetHighLighterWithLines;
|
||||
public
|
||||
constructor Create(aTextView : TSynEditStrings; AFoldTree : TSynTextFoldAVLTree);
|
||||
function FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
|
||||
function FoldOpenInfo(ALineIdx, AFoldIdx: Integer; AType: Integer = 0): TSynFoldNodeInfo;
|
||||
|
||||
// Info about Folds opening on ALineIdx
|
||||
function FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
|
||||
function FoldOpenInfo(ALineIdx, AFoldIdx: Integer; AType: Integer = 0): TSynFoldNodeInfo;
|
||||
//property FoldOpenInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldOpenInfo;
|
||||
//property FoldInfoCount[ALineIdx: Integer]: Integer read GetFoldInfoCount;
|
||||
//property FoldInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldInfo;
|
||||
function FoldLineLength(ALine, AFoldIndex: Integer): integer;
|
||||
|
||||
function FoldLineLength(ALine, AFoldIndex: Integer): integer;
|
||||
function InfoForFoldAtTextIndex(ALine, AFoldIndex : Integer;
|
||||
HideLen: Boolean = False;
|
||||
NeedLen: Boolean = True): TSynEditFoldProviderNodeInfo;
|
||||
@ -2724,6 +2772,131 @@ begin
|
||||
fNestedNodesTree := nil;
|
||||
end;
|
||||
|
||||
{ TLazSynEditNestedFoldsList }
|
||||
|
||||
procedure TLazSynEditNestedFoldsList.SetLines(AValue: TLineIdx);
|
||||
begin
|
||||
if FLine = AValue then Exit;
|
||||
FLine := AValue;
|
||||
// Todo: might be able to re-use old data
|
||||
Clear;
|
||||
end;
|
||||
|
||||
procedure TLazSynEditNestedFoldsList.Clear;
|
||||
begin
|
||||
FGroupCount := -1;
|
||||
FCount := -1;
|
||||
FOpeningOnLineCount := -1;
|
||||
FEvaluationIndex := -1;
|
||||
SetLength(FNestInfo, 0);
|
||||
end;
|
||||
|
||||
procedure TLazSynEditNestedFoldsList.InitSubGroupEndLevels;
|
||||
var
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
i: integer;
|
||||
begin
|
||||
if FGroupCount > 0 then
|
||||
exit;
|
||||
|
||||
hl := FFoldProvider.HighLighterWithLines;
|
||||
if hl = nil then exit;
|
||||
|
||||
if FFoldGroup = 0 then begin
|
||||
// special, join other groups (or some other...)
|
||||
FGroupCount := hl.FoldTypeCount;
|
||||
// start at 1, so FoldGroup can be used as index
|
||||
SetLength(FGroupEndLevels, FGroupCount + 1);
|
||||
SetLength(FGroupEndLevelsAtEval, FGroupCount + 1);
|
||||
for i := 1 to FGroupCount do
|
||||
FGroupEndLevels[i] := hl.FoldBlockEndLevel(FLine - 1, i) + OpeningOnLineCount;
|
||||
FGroupEndLevelsAtEval[i] := FGroupEndLevels[i];
|
||||
end
|
||||
else begin
|
||||
FGroupCount := 1;
|
||||
SetLength(FGroupEndLevels, 1);
|
||||
SetLength(FGroupEndLevelsAtEval, 1);
|
||||
FGroupEndLevels[0] := Count;
|
||||
FGroupEndLevelsAtEval[0] := FGroupEndLevels[0];
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLazSynEditNestedFoldsList.InitNestInfoForIndex(AnIndex: Integer);
|
||||
var
|
||||
CurLine: TLineIdx;
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
i: Integer;
|
||||
begin
|
||||
if (AnIndex >= Count) or (AnIndex >= FEvaluationIndex) then exit;
|
||||
hl := FFoldProvider.HighLighterWithLines;
|
||||
if hl = nil then exit;
|
||||
|
||||
InitSubGroupEndLevels;
|
||||
|
||||
if FEvaluationIndex = Count then
|
||||
CurLine := Line
|
||||
else
|
||||
CurLine := FNestInfo[FEvaluationIndex].LineIdx;
|
||||
// need index/column...
|
||||
|
||||
inc(CurLine);
|
||||
while CurLine > 0 do begin
|
||||
dec(CurLine);
|
||||
|
||||
if FFoldGroup = 0 then begin
|
||||
i := FGroupCount;
|
||||
|
||||
while (i > 0) do begin
|
||||
// hl.MinimumFoldLevel(CurLine, i) // minimumPas
|
||||
dec(i);
|
||||
end;
|
||||
if i < 0 then continue;
|
||||
end
|
||||
else begin
|
||||
//if ... continue
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure TLazSynEditNestedFoldsList.SetFoldGroup(AValue: Integer);
|
||||
begin
|
||||
if FFoldGroup = AValue then Exit;
|
||||
FFoldGroup := AValue;
|
||||
Clear;
|
||||
end;
|
||||
|
||||
constructor TLazSynEditNestedFoldsList.Create(aFoldProvider: TSynEditFoldProvider);
|
||||
begin
|
||||
FFoldProvider := aFoldProvider;
|
||||
end;
|
||||
|
||||
function TLazSynEditNestedFoldsList.Count: Integer;
|
||||
var
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
Result := FCount;
|
||||
if Result >= 0 then exit;
|
||||
hl := FFoldProvider.HighLighterWithLines;
|
||||
if hl = nil then exit(-1);
|
||||
|
||||
FCount := hl.FoldBlockEndLevel(FLine - 1, FFoldGroup) + OpeningOnLineCount;
|
||||
FEvaluationIndex := FCount;
|
||||
SetLength(FNestInfo, FCount);
|
||||
Result := FCount;
|
||||
end;
|
||||
|
||||
function TLazSynEditNestedFoldsList.OpeningOnLineCount: Integer;
|
||||
begin
|
||||
Result := FOpeningOnLineCount;
|
||||
if Result >= 0 then exit;
|
||||
|
||||
FOpeningOnLineCount := FFoldProvider.FoldOpenCount(FLine);
|
||||
Result := FOpeningOnLineCount;
|
||||
end;
|
||||
|
||||
{ TSynEditFoldProvider }
|
||||
|
||||
function TSynEditFoldProvider.GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
|
||||
@ -2744,8 +2917,8 @@ begin
|
||||
exit;
|
||||
|
||||
FHighlighter.CurrentLines := FLines;
|
||||
if FHighlighter.FoldNestCount(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody];
|
||||
if FHighlighter.FoldCloseCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody];
|
||||
if FHighlighter.FoldBlockEndLevel(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody];
|
||||
if FHighlighter.FoldBlockClosingCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody];
|
||||
|
||||
c := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([]);
|
||||
if c > 0 then begin
|
||||
@ -2761,7 +2934,7 @@ begin
|
||||
Result := Result + [cfHideStart, cfSingleLineHide];
|
||||
end
|
||||
else
|
||||
if FHighlighter.FoldOpenCount(ALineIdx) > 0 then include(Result, cfFoldStart);
|
||||
if FHighlighter.FoldBlockOpeningCount(ALineIdx) > 0 then include(Result, cfFoldStart);
|
||||
end;
|
||||
|
||||
function TSynEditFoldProvider.GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications;
|
||||
@ -2777,6 +2950,14 @@ begin
|
||||
((FSelection <> nil) and FSelection.SelAvail);
|
||||
end;
|
||||
|
||||
function TSynEditFoldProvider.GetHighLighterWithLines: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
Result := FHighlighter;
|
||||
if (Result = nil) then
|
||||
exit;
|
||||
Result.CurrentLines := FLines;
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldProvider.SetHighLighter(const AValue: TSynCustomFoldHighlighter);
|
||||
begin
|
||||
if FHighlighter = AValue then exit;
|
||||
@ -2790,30 +2971,18 @@ begin
|
||||
end;
|
||||
|
||||
function TSynEditFoldProvider.FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if (FHighlighter = nil) or (ALineIdx < 0) then begin
|
||||
if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then exit(1);
|
||||
exit(0);
|
||||
end;
|
||||
|
||||
// Need to check alll nodes with FoldNodeInfoCount
|
||||
// Hide-able nodes can open and close on the same line "(* cmment *)"
|
||||
FHighlighter.CurrentLines := FLines;
|
||||
Result := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold]);
|
||||
if (result > 0) and (AType > 0) then begin
|
||||
i := Result ;
|
||||
Result := 0;
|
||||
while i > 0 do begin
|
||||
dec(i);
|
||||
if FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(i, [sfaOpen, sfaFold]).FoldGroup = AType then
|
||||
inc(Result);
|
||||
end;
|
||||
end
|
||||
//Result := Result + FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOpen, sfaFoldHide]];
|
||||
//Result := Result + FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOneLineOpen, sfaFoldHide]];
|
||||
else
|
||||
Result := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold], AType);
|
||||
// fallback for HL without GetFoldNodeInfoCountEx
|
||||
if Result < 0 then
|
||||
Result := FHighlighter.FoldOpenCount(ALineIdx, AType);
|
||||
Result := FHighlighter.FoldBlockOpeningCount(ALineIdx, AType);
|
||||
if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then
|
||||
inc(Result);
|
||||
end;
|
||||
@ -2837,8 +3006,6 @@ function TSynEditFoldProvider.FoldOpenInfo(ALineIdx, AFoldIdx: Integer;
|
||||
Result.FoldGroup := -1;
|
||||
end;
|
||||
|
||||
var
|
||||
i, x: Integer;
|
||||
begin
|
||||
Result.FoldAction := [sfaInvalid];
|
||||
if (FHighlighter = nil) or (ALineIdx < 0) then begin
|
||||
@ -2848,27 +3015,13 @@ begin
|
||||
end;
|
||||
|
||||
FHighlighter.CurrentLines := FLines;
|
||||
if AType = 0 then
|
||||
if (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) and
|
||||
(AFoldIdx = FoldOpenCount(ALineIdx, 0)-1)
|
||||
then
|
||||
Result := BlockSelInfo(AFoldIdx-1)
|
||||
else
|
||||
Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(AFoldIdx, [sfaOpen, sfaFold])
|
||||
else begin
|
||||
x := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold]);
|
||||
i := 0;
|
||||
while i < x do begin
|
||||
Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(i, [sfaOpen, sfaFold]);
|
||||
if (Result.FoldGroup = AType) then begin
|
||||
if AFoldIdx = 0 then
|
||||
exit;
|
||||
dec(AFoldIdx);
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
Result.FoldAction := [sfaInvalid];
|
||||
end;
|
||||
if (AType = 0) and (FSelection <> nil) and FSelection.SelAvail and
|
||||
(FSelection.FirstLineBytePos.Y=ALineIdx+1) and
|
||||
(AFoldIdx = FoldOpenCount(ALineIdx, AType)-1)
|
||||
then
|
||||
Result := BlockSelInfo(AFoldIdx)
|
||||
else
|
||||
Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(AFoldIdx, [sfaOpen, sfaFold], AType);
|
||||
end;
|
||||
|
||||
function TSynEditFoldProvider.FoldLineLength(ALine, AFoldIndex: Integer): integer;
|
||||
@ -3369,7 +3522,7 @@ begin
|
||||
while i < fLines.Count do begin
|
||||
// Todo: Highlighter should return a list of types that can return default folded
|
||||
// Currently PascalHl Type 2 = Region
|
||||
c := hl.FoldOpenCount(i, 2);
|
||||
c := hl.FoldBlockOpeningCount(i, 2);
|
||||
if c > 0 then begin
|
||||
c := hl.FoldNodeInfo[i].CountEx([sfaOpen, sfaFold]);
|
||||
j := 0;
|
||||
@ -3855,9 +4008,9 @@ begin
|
||||
fFoldTree.Clear;
|
||||
i := 0;
|
||||
while i < fLines.Count do begin
|
||||
if (hl.FoldOpenCount(i, t) > 0)
|
||||
and (hl.FoldNestCount(i, t) > StartLevel) then begin
|
||||
c := hl.FoldOpenCount(i) -1;
|
||||
if (hl.FoldBlockOpeningCount(i, t) > 0)
|
||||
and (hl.FoldBlockEndLevel(i, t) > StartLevel) then begin
|
||||
c := hl.FoldBlockOpeningCount(i) -1;
|
||||
fldinf := FoldProvider.InfoForFoldAtTextIndex(i, c);
|
||||
// i is 0-based
|
||||
// FoldTree is 1-based AND first line remains visble
|
||||
@ -4111,7 +4264,7 @@ begin
|
||||
hl := TSynCustomFoldHighlighter(HighLighter);
|
||||
if not assigned(hl) then
|
||||
exit(-1);
|
||||
Result := hl.FoldNestCount(AStartIndex-1, AType) + FoldProvider.FoldOpenCount(AStartIndex);
|
||||
Result := hl.FoldBlockEndLevel(AStartIndex-1, AType) + FoldProvider.FoldOpenCount(AStartIndex);
|
||||
end;
|
||||
|
||||
function TSynEditFoldedView.OpenFoldInfo(aStartIndex, ColIndex: Integer; AType: Integer = 0): TFoldViewNodeInfo;
|
||||
@ -4126,13 +4279,13 @@ var
|
||||
begin
|
||||
if AType = 0 then begin;
|
||||
for i := 1 to TypeCnt do begin
|
||||
EndLvl[i] := hl.FoldNestCount(l-1, i);
|
||||
EndLvl[i] := hl.FoldBlockEndLevel(l-1, i);
|
||||
EndLvl[i] := EndLvl[i] + FoldProvider.FoldOpenCount(l, i);
|
||||
CurLvl[i] := EndLvl[i];
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
EndLvl[0] := hl.FoldNestCount(l-1, AType);
|
||||
EndLvl[0] := hl.FoldBlockEndLevel(l-1, AType);
|
||||
EndLvl[0] := EndLvl[0] + FoldProvider.FoldOpenCount(l, AType);
|
||||
CurLvl[0] := EndLvl[0];
|
||||
end;
|
||||
@ -4146,7 +4299,7 @@ begin
|
||||
TypeCnt := 1
|
||||
else
|
||||
TypeCnt := hl.FoldTypeCount;
|
||||
Lvl := hl.FoldNestCount(AStartIndex-1, AType);
|
||||
Lvl := hl.FoldBlockEndLevel(AStartIndex-1, AType);
|
||||
if ColIndex >= Lvl then begin
|
||||
n := ColIndex - Lvl;
|
||||
if AType = 0 then begin
|
||||
@ -4165,8 +4318,8 @@ begin
|
||||
aStartIndex := aStartIndex;
|
||||
while (ColIndex < Lvl) and (aStartIndex > 0) do begin
|
||||
dec(aStartIndex);
|
||||
o := hl.FoldOpenCount(AStartIndex, AType);
|
||||
if (o > 0) or (hl.FoldCloseCount(aStartIndex, AType) > 0) then begin
|
||||
o := hl.FoldBlockOpeningCount(AStartIndex, AType);
|
||||
if (o > 0) or (hl.FoldBlockClosingCount(aStartIndex, AType) > 0) then begin
|
||||
n := o;
|
||||
c := hl.FoldNodeInfo[aStartIndex].CountEx([], AType) - 1;
|
||||
for i := c downto 0 do begin
|
||||
@ -4194,7 +4347,7 @@ begin
|
||||
end;
|
||||
end
|
||||
else
|
||||
if hl.FoldNestCount(AStartIndex-1, AType) = 0 then break;
|
||||
if hl.FoldBlockEndLevel(AStartIndex-1, AType) = 0 then break;
|
||||
end;
|
||||
end;
|
||||
Result.HNode := nd;
|
||||
@ -4220,7 +4373,7 @@ begin
|
||||
exit;
|
||||
|
||||
i := ALine;
|
||||
l := hl.FoldOpenCount(i - 1);
|
||||
l := hl.FoldBlockOpeningCount(i - 1);
|
||||
if l > 0 then begin
|
||||
node := fFoldTree.FindFoldForLine(ALine, true);
|
||||
if node.IsInFold and (node.StartLine = ALine +1) then begin
|
||||
@ -4234,19 +4387,19 @@ begin
|
||||
else
|
||||
exit(ALine);
|
||||
end
|
||||
else if hl.FoldCloseCount(i - 1) > 0 then
|
||||
else if hl.FoldBlockClosingCount(i - 1) > 0 then
|
||||
dec(i);
|
||||
if (i < 0) or (hl.FoldNestCount(i-1) = 0) then
|
||||
if (i < 0) or (hl.FoldBlockEndLevel(i-1) = 0) then
|
||||
exit;
|
||||
|
||||
l := 0;
|
||||
while (i > 0) and (l >= 0) do begin // (FoldMinLevel[i] >= l) do
|
||||
dec(i);
|
||||
l := l - hl.FoldOpenCount(i);
|
||||
l := l - hl.FoldBlockOpeningCount(i);
|
||||
if l >= 0 then
|
||||
l := l + hl.FoldCloseCount(i);
|
||||
l := l + hl.FoldBlockClosingCount(i);
|
||||
end;
|
||||
if (hl.FoldNestCount(i) > 0) then // TODO, check for collapsed at index = 0
|
||||
if (hl.FoldBlockEndLevel(i) > 0) then // TODO, check for collapsed at index = 0
|
||||
Result := i + 1;
|
||||
end;
|
||||
|
||||
|
||||
@ -22,9 +22,25 @@ $Id: synedithighlighter.pp 19051 2009-03-21 00:47:33Z martin $
|
||||
You may retrieve the latest version of this file at the SynEdit home page,
|
||||
located at http://SynEdit.SourceForge.net
|
||||
|
||||
Known Issues:
|
||||
-------------------------------------------------------------------------------}
|
||||
|
||||
(* Naming Conventions:
|
||||
- FoldBlock:
|
||||
A continuous range of lines, that can (optional) be folded.
|
||||
Which Foldblocks can be folded is decided by the Highlighter. It may be
|
||||
configurable.
|
||||
A Foldblock can contain other Foldbloccks (nested), but two Foldblocks can
|
||||
not overlap.
|
||||
- FoldBlockLevel (FoldBlockNestLevel):
|
||||
The amount of FoldBlocks in which a line (or a point of text) is.
|
||||
- FoldGroup:
|
||||
An independent set of FoldBlocks. FoldBlocks in different Groups may overlap.
|
||||
(e.g. IFDEF/REGION in the SynPasSyn allow for overlaps, rather than strict nesting)
|
||||
Some older code use "FoldType" instead
|
||||
- FoldNode
|
||||
Start or End of a FoldBlock
|
||||
*)
|
||||
|
||||
unit SynEditHighlighterFoldBase;
|
||||
|
||||
{$I synedit.inc}
|
||||
@ -54,6 +70,42 @@ type
|
||||
);
|
||||
TSynFoldActions = set of TSynFoldAction;
|
||||
|
||||
(* TSynFoldBlockFilter
|
||||
used to specify which folds to include for:
|
||||
- FoldOpenCount, FoldCloseCount, FoldNestCount
|
||||
- maybe in future TLazSynFoldNodeInfoList
|
||||
TLazSynFoldNodeInfoList has additional filters
|
||||
TLazSynFoldNodeInfoList always uses the full set (sfbIncludeDisabled)
|
||||
|
||||
A Highlighter is not required to implement this, or can choose to implement
|
||||
a subset only. For any field/value a Highlighter may simple assume default.
|
||||
- Highlighter that have only one "FoldGroup" do not require this.
|
||||
- Highlighter that do not store foldblocks that are unavailable (e.g. off by
|
||||
config) always return the same set
|
||||
|
||||
Using a record, as argument is the virtual methods, allows to add further
|
||||
fields/values, without breaking inheritance.
|
||||
New fields values are expected to be ignored (handled as default) by existing
|
||||
highlighter.
|
||||
|
||||
Callers of the method can:
|
||||
- use InitFoldBlockFilter to make sure all fields are set to default
|
||||
- use (none virtual) wrapper methods
|
||||
*)
|
||||
TSynFoldBlockFilterFlag = (
|
||||
sfbIncludeDisabled // Foldable by config = off
|
||||
);
|
||||
TSynFoldBlockFilterFlags = set of TSynFoldBlockFilterFlag;
|
||||
TSynFoldBlockFilter = record
|
||||
FoldGroup: integer;
|
||||
Flags: TSynFoldBlockFilterFlags;
|
||||
end;
|
||||
|
||||
procedure InitFoldBlockFilter(out AFilter: TSynFoldBlockFilter;
|
||||
AFoldGroup: Integer = 0; AFlag: TSynFoldBlockFilterFlags = []);
|
||||
|
||||
type
|
||||
|
||||
TSynFoldNodeInfo = record
|
||||
LineIndex: Integer;
|
||||
NodeIndex: Integer; // Indicates the position within the list of info nodes (depends on search-Filter)
|
||||
@ -204,7 +256,7 @@ type
|
||||
|
||||
TSynCustomFoldHighlighter = class(TSynCustomHighlighter)
|
||||
protected
|
||||
// Config
|
||||
// Fold Config
|
||||
FFoldConfig: Array of TSynCustomFoldConfig;
|
||||
function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; virtual;
|
||||
procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); virtual;
|
||||
@ -220,36 +272,55 @@ type
|
||||
FRootCodeFoldBlock: TSynCustomCodeFoldBlock;
|
||||
FFoldNodeInfoList: TLazSynFoldNodeInfoList;
|
||||
protected
|
||||
function CreateFoldNodeInfoList: TLazSynFoldNodeInfoList; virtual;
|
||||
function GetFoldNodeInfo(Line: TLineIdx): TLazSynFoldNodeInfoList;
|
||||
procedure InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx); virtual;
|
||||
protected
|
||||
property CodeFoldRange: TSynCustomHighlighterRange read FCodeFoldRange;
|
||||
// "Range"
|
||||
function GetRangeClass: TSynCustomHighlighterRangeClass; virtual;
|
||||
procedure CreateRootCodeFoldBlock; virtual; // set RootCodeFoldBlock
|
||||
property CodeFoldRange: TSynCustomHighlighterRange read FCodeFoldRange;
|
||||
function TopCodeFoldBlockType(DownIndex: Integer = 0): Pointer;
|
||||
property RootCodeFoldBlock: TSynCustomCodeFoldBlock read FRootCodeFoldBlock
|
||||
write FRootCodeFoldBlock;
|
||||
|
||||
// Open/Close Folds
|
||||
function StartCodeFoldBlock(ABlockType: Pointer;
|
||||
IncreaseLevel: Boolean = true): TSynCustomCodeFoldBlock; virtual;
|
||||
procedure EndCodeFoldBlock(DecreaseLevel: Boolean = True); virtual;
|
||||
procedure CreateRootCodeFoldBlock; virtual;
|
||||
property RootCodeFoldBlock: TSynCustomCodeFoldBlock read FRootCodeFoldBlock
|
||||
write FRootCodeFoldBlock;
|
||||
|
||||
// Info about Folds
|
||||
function CreateFoldNodeInfoList: TLazSynFoldNodeInfoList; virtual;
|
||||
function GetFoldNodeInfo(Line: TLineIdx): TLazSynFoldNodeInfoList;
|
||||
procedure InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx); virtual;
|
||||
|
||||
// Info about Folds, on currently set line/range (simply forwarding to range
|
||||
function MinimumCodeFoldBlockLevel: integer; virtual;
|
||||
function CurrentCodeFoldBlockLevel: integer; virtual;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetRange: Pointer; override;
|
||||
|
||||
function MinimumCodeFoldBlockLevel: integer; virtual;
|
||||
function CurrentCodeFoldBlockLevel: integer; virtual;
|
||||
// Info about Folds
|
||||
function FoldBlockOpeningCount(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer; virtual; overload;
|
||||
function FoldBlockClosingCount(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer; virtual; overload;
|
||||
function FoldBlockEndLevel(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer; virtual; overload;
|
||||
function FoldBlockMinLevel(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer; virtual; overload;
|
||||
|
||||
// requires CurrentLines;
|
||||
function MinimumFoldLevel(Index: Integer): integer; virtual; abstract; // TODO: Move to Fold*
|
||||
function EndFoldLevel(Index: Integer): integer; virtual; abstract; // TODO: Replace with FoldNestCount
|
||||
function FoldBlockOpeningCount(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
|
||||
AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
|
||||
function FoldBlockClosingCount(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
|
||||
AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
|
||||
function FoldBlockEndLevel(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
|
||||
AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
|
||||
function FoldBlockMinLevel(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
|
||||
AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
|
||||
|
||||
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; deprecated;
|
||||
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; deprecated;
|
||||
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; deprecated;
|
||||
|
||||
// fold-nodes that can be collapsed
|
||||
// Highlighter can join several fold structures Or leave out some
|
||||
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; virtual;
|
||||
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; virtual;
|
||||
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; virtual;
|
||||
function FoldTypeCount: integer; virtual;
|
||||
function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer;
|
||||
UseCloseNodes: boolean = false): integer; virtual; // TODO: could be deprecated ./ only child-classes
|
||||
@ -296,6 +367,13 @@ function AllocateHighlighterRanges(
|
||||
|
||||
implementation
|
||||
|
||||
procedure InitFoldBlockFilter(out AFilter: TSynFoldBlockFilter; AFoldGroup: Integer;
|
||||
AFlag: TSynFoldBlockFilterFlags = []);
|
||||
begin
|
||||
AFilter.FoldGroup := AFoldGroup;
|
||||
AFilter.Flags := AFlag;
|
||||
end;
|
||||
|
||||
function CompareSynHighlighterRanges(Data1, Data2: Pointer): integer;
|
||||
var
|
||||
Range1: TSynCustomHighlighterRange;
|
||||
@ -597,6 +675,92 @@ begin
|
||||
Result:=fRanges.GetEqual(FCodeFoldRange);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldBlockOpeningCount(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer;
|
||||
begin
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
Result := FoldBlockEndLevel(ALineIndex, AFilter) - FoldBlockMinLevel(ALineIndex, AFilter);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldBlockClosingCount(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer;
|
||||
begin
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
Result := FoldBlockEndLevel(ALineIndex - 1, AFilter) - FoldBlockMinLevel(ALineIndex, AFilter);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldBlockEndLevel(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer;
|
||||
var
|
||||
r: Pointer;
|
||||
begin
|
||||
Assert(CurrentRanges <> nil, 'TSynCustomFoldHighlighter.FoldBlockEndLevel requires CurrentRanges');
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := CurrentRanges[ALineIndex];
|
||||
if (r <> nil) and (r <> NullRange) then
|
||||
Result := TSynCustomHighlighterRange(r).CodeFoldStackSize
|
||||
else
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldBlockMinLevel(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer;
|
||||
var
|
||||
r: Pointer;
|
||||
begin
|
||||
Assert(CurrentRanges <> nil, 'TSynCustomFoldHighlighter.FoldBlockMinLevelrequires CurrentRanges');
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := CurrentRanges[ALineIndex];
|
||||
if (r <> nil) and (r <> NullRange) then
|
||||
Result := TSynCustomHighlighterRange(r).MinimumCodeFoldBlockLevel
|
||||
else
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldBlockOpeningCount(ALineIndex: TLineIdx;
|
||||
AFoldGroup: integer; AFlags: TSynFoldBlockFilterFlags): integer;
|
||||
var
|
||||
Filter: TSynFoldBlockFilter;
|
||||
begin
|
||||
Filter.FoldGroup := AFoldGroup;
|
||||
Filter.Flags := AFlags;
|
||||
Result := FoldBlockOpeningCount(ALineIndex, Filter);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldBlockClosingCount(ALineIndex: TLineIdx;
|
||||
AFoldGroup: integer; AFlags: TSynFoldBlockFilterFlags): integer;
|
||||
var
|
||||
Filter: TSynFoldBlockFilter;
|
||||
begin
|
||||
Filter.FoldGroup := AFoldGroup;
|
||||
Filter.Flags := AFlags;
|
||||
Result := FoldBlockClosingCount(ALineIndex, Filter);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldBlockEndLevel(ALineIndex: TLineIdx;
|
||||
AFoldGroup: integer; AFlags: TSynFoldBlockFilterFlags): integer;
|
||||
var
|
||||
Filter: TSynFoldBlockFilter;
|
||||
begin
|
||||
Filter.FoldGroup := AFoldGroup;
|
||||
Filter.Flags := AFlags;
|
||||
Result := FoldBlockEndLevel(ALineIndex, Filter);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldBlockMinLevel(ALineIndex: TLineIdx;
|
||||
AFoldGroup: integer; AFlags: TSynFoldBlockFilterFlags): integer;
|
||||
var
|
||||
Filter: TSynFoldBlockFilter;
|
||||
begin
|
||||
Filter.FoldGroup := AFoldGroup;
|
||||
Filter.Flags := AFlags;
|
||||
Result := FoldBlockMinLevel(ALineIndex, Filter);
|
||||
end;
|
||||
|
||||
procedure TSynCustomFoldHighlighter.ResetRange;
|
||||
begin
|
||||
FCodeFoldRange.Clear;
|
||||
@ -605,6 +769,7 @@ end;
|
||||
|
||||
function TSynCustomFoldHighlighter.MinimumCodeFoldBlockLevel: integer;
|
||||
begin
|
||||
assert(FCodeFoldRange <> nil, 'MinimumCodeFoldBlockLevel requires FCodeFoldRange');
|
||||
Result := FCodeFoldRange.MinimumCodeFoldBlockLevel;
|
||||
end;
|
||||
|
||||
@ -625,25 +790,23 @@ end;
|
||||
|
||||
function TSynCustomFoldHighlighter.CurrentCodeFoldBlockLevel: integer;
|
||||
begin
|
||||
if CodeFoldRange<>nil then
|
||||
Result:=CodeFoldRange.CodeFoldStackSize
|
||||
else
|
||||
Result:=0;
|
||||
assert(FCodeFoldRange <> nil, 'MinimumCodeFoldBlockLevel requires FCodeFoldRange');
|
||||
Result := FCodeFoldRange.CodeFoldStackSize;
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer;
|
||||
begin
|
||||
result := 0;
|
||||
result := FoldBlockOpeningCount(ALineIndex, AType);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer;
|
||||
begin
|
||||
result := 0;
|
||||
result := FoldBlockClosingCount(ALineIndex, AType);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer;
|
||||
begin
|
||||
Result := 0;
|
||||
Result := FoldBlockEndLevel(ALineIndex, AType);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldTypeCount: integer;
|
||||
@ -661,7 +824,7 @@ function TSynCustomFoldHighlighter.FoldLineLength(ALineIndex, FoldIndex: Integer
|
||||
begin
|
||||
Result := FoldEndLine(ALineIndex, FoldIndex);
|
||||
// check if fold last line of block (not mixed "end begin")
|
||||
if (EndFoldLevel(Result) > MinimumFoldLevel(Result)) then
|
||||
if (FoldBlockEndLevel(Result) > FoldBlockMinLevel(Result)) then
|
||||
dec(Result);
|
||||
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
|
||||
Result := Result - ALineIndex;
|
||||
@ -672,13 +835,12 @@ var
|
||||
lvl, cnt: Integer;
|
||||
e, m: Integer;
|
||||
begin
|
||||
//atype := FoldTypeAtNodeIndex(ALineIndex, FoldIndex);
|
||||
cnt := CurrentLines.Count;
|
||||
e := EndFoldLevel(ALineIndex);
|
||||
m := MinimumFoldLevel(ALineIndex);
|
||||
e := FoldBlockEndLevel(ALineIndex);
|
||||
m := FoldBlockMinLevel(ALineIndex);
|
||||
lvl := Min(m+1+FoldIndex, e);
|
||||
Result := ALineIndex + 1;
|
||||
while (Result < cnt) and (MinimumFoldLevel(Result) >= lvl) do inc(Result);
|
||||
while (Result < cnt) and (FoldBlockMinLevel(Result) >= lvl) do inc(Result);
|
||||
if (Result = cnt) then
|
||||
dec(Result);
|
||||
end;
|
||||
|
||||
@ -75,13 +75,6 @@ type
|
||||
procedure EndXmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = '');
|
||||
public
|
||||
procedure SetLine({$IFDEF FPC}const {$ENDIF}NewValue: string; LineNumber:Integer); override;
|
||||
public
|
||||
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
// TODO: make private
|
||||
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
|
||||
function EndFoldLevel(ALineIndex: Integer): integer; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -122,50 +115,6 @@ begin
|
||||
FXmlRangeInfoClosePos := 0;
|
||||
end;
|
||||
|
||||
function TSynCustomXmlHighlighter.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynCustomXmlHighlighter.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynCustomXmlHighlighter.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := EndFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynCustomXmlHighlighter.MinimumFoldLevel(ALineIndex: Integer): integer;
|
||||
var
|
||||
r: TSynCustomHighlighterRange;
|
||||
begin
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.MinimumCodeFoldBlockLevel
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynCustomXmlHighlighter.EndFoldLevel(ALineIndex: Integer): integer;
|
||||
var
|
||||
r: TSynCustomHighlighterRange;
|
||||
begin
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.CodeFoldStackSize
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynCustomXmlHighlighter.StartXmlCodeFoldBlock(ABlockType: Integer): TSynCustomCodeFoldBlock;
|
||||
var
|
||||
FoldBlock: Boolean;
|
||||
@ -232,11 +181,11 @@ begin
|
||||
|
||||
if i = 0 then begin
|
||||
i := LineIndex - 1;
|
||||
lvl := EndFoldLevel(i);
|
||||
lvl := FoldBlockEndLevel(i);
|
||||
while i >= 0 do begin
|
||||
if MinimumFoldLevel(i) < lvl then begin
|
||||
if FoldBlockMinLevel(i) < lvl then begin
|
||||
LInfo := TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[i].ElementOpenList;
|
||||
k := length(LInfo) - Max(EndFoldLevel(i) - lvl, 0) - 1;
|
||||
k := length(LInfo) - Max(FoldBlockEndLevel(i) - lvl, 0) - 1;
|
||||
while (k >= 0) do begin
|
||||
if (LInfo[k] = AName) then
|
||||
break;
|
||||
|
||||
@ -140,7 +140,10 @@ var
|
||||
exit;
|
||||
|
||||
inc(YIndex);
|
||||
while (YIndex < LCnt) and (HL.MinimumFoldLevel(YIndex) > StartNode.NestLvlStart) do
|
||||
while (YIndex < LCnt) and
|
||||
(HL.FoldBlockMinLevel(YIndex, StartNode.FoldGroup, [sfbIncludeDisabled])
|
||||
> StartNode.NestLvlStart)
|
||||
do
|
||||
inc(YIndex);
|
||||
if YIndex = LCnt then
|
||||
exit;
|
||||
@ -172,7 +175,9 @@ var
|
||||
exit;
|
||||
|
||||
dec(YIndex);
|
||||
while (YIndex >= 0) and (HL.MinimumFoldLevel(YIndex) > EndNode.NestLvlEnd) do
|
||||
while (YIndex >= 0) and
|
||||
(HL.FoldBlockMinLevel(YIndex, EndNode.FoldGroup, [sfbIncludeDisabled]) > EndNode.NestLvlEnd)
|
||||
do
|
||||
dec(YIndex);
|
||||
if YIndex < 0 then
|
||||
exit;
|
||||
|
||||
@ -157,14 +157,6 @@ type
|
||||
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
|
||||
function GetFoldConfigCount: Integer; override;
|
||||
function GetFoldConfigInternalCount: Integer; override;
|
||||
public
|
||||
// folding
|
||||
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
// TODO: make private
|
||||
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
|
||||
function EndFoldLevel(ALineIndex: Integer): integer; override;
|
||||
published
|
||||
property UnknownAttri: TSynHighlighterAttributes read FUnknownAttri write FUnknownAttri;
|
||||
property SpaceAttri: TSynHighlighterAttributes read FSpaceAttri write FSpaceAttri;
|
||||
@ -747,56 +739,6 @@ begin
|
||||
Result := ord(high(TDiffCodeFoldBlockType)) - ord(low(TDiffCodeFoldBlockType)) + 1;
|
||||
end;
|
||||
|
||||
// EndLvl = MinLvl(+1)
|
||||
// MinLvl = Min(Min, Min(+1))
|
||||
|
||||
function TSynDiffSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := Max(0, MinimumFoldLevel(ALineIndex+1) - MinimumFoldLevel(ALineIndex));
|
||||
//Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynDiffSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := Max(0, MinimumFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex+1));
|
||||
//Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynDiffSyn.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := MinimumFoldLevel(ALineIndex+1);
|
||||
//Result := EndFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynDiffSyn.MinimumFoldLevel(ALineIndex: Integer): integer;
|
||||
var
|
||||
r: TSynCustomHighlighterRange;
|
||||
begin
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.MinimumCodeFoldBlockLevel
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynDiffSyn.EndFoldLevel(ALineIndex: Integer): integer;
|
||||
var
|
||||
r: TSynCustomHighlighterRange;
|
||||
begin
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.CodeFoldStackSize
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterPlaceableHighlighter(TSynDiffSyn);
|
||||
|
||||
|
||||
@ -65,6 +65,7 @@ type
|
||||
// internal type / no config
|
||||
cfbtLfmNone
|
||||
);
|
||||
TLfmCodeFoldBlockTypes = set of TLfmCodeFoldBlockType;
|
||||
|
||||
TProcTableProc = procedure of object;
|
||||
|
||||
@ -148,14 +149,6 @@ type
|
||||
procedure SetRange(Value: Pointer); override;
|
||||
procedure ResetRange; override;
|
||||
property IdentChars;
|
||||
public
|
||||
// folding
|
||||
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
// TODO: make private
|
||||
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
|
||||
function EndFoldLevel(ALineIndex: Integer): integer; override;
|
||||
published
|
||||
property CommentAttri: TSynHighlighterAttributes read fCommentAttri
|
||||
write fCommentAttri;
|
||||
@ -612,50 +605,6 @@ begin
|
||||
fRange := rsUnknown;
|
||||
end;
|
||||
|
||||
function TSynLFMSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynLFMSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynLFMSyn.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
|
||||
begin
|
||||
If AType <> 0 then exit(0);
|
||||
Result := EndFoldLevel(ALineIndex);
|
||||
end;
|
||||
|
||||
function TSynLFMSyn.MinimumFoldLevel(ALineIndex: Integer): integer;
|
||||
var
|
||||
r: TSynCustomHighlighterRange;
|
||||
begin
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.MinimumCodeFoldBlockLevel
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynLFMSyn.EndFoldLevel(ALineIndex: Integer): integer;
|
||||
var
|
||||
r: TSynCustomHighlighterRange;
|
||||
begin
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.CodeFoldStackSize
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
procedure TSynLFMSyn.SetRange(Value: Pointer);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
@ -174,6 +174,11 @@ const
|
||||
cfbtNone
|
||||
);
|
||||
|
||||
FOLDGROUP_PASCAL = 1;
|
||||
FOLDGROUP_REGION = 2;
|
||||
FOLDGROUP_IFDEF = 3;
|
||||
|
||||
|
||||
type
|
||||
|
||||
TPascalCompilerMode = (
|
||||
@ -319,7 +324,9 @@ type
|
||||
fD4syntax: boolean;
|
||||
FCatchNodeInfo: Boolean;
|
||||
FCatchNodeInfoList: TLazSynPasFoldNodeInfoList;
|
||||
// Divider
|
||||
FDividerDrawConfig: Array [TSynPasDividerDrawLocation] of TSynDividerDrawConfig;
|
||||
|
||||
function GetPasCodeFoldRange: TSynPasSynRange;
|
||||
procedure SetCompilerMode(const AValue: TPascalCompilerMode);
|
||||
procedure SetExtendedKeywordsMode(const AValue: Boolean);
|
||||
@ -449,9 +456,10 @@ type
|
||||
procedure SymbolProc;
|
||||
procedure UnknownProc;
|
||||
procedure SetD4syntax(const Value: boolean);
|
||||
procedure InitNode(var Node: TSynFoldNodeInfo; EndOffs: Integer;
|
||||
procedure InitNode(out Node: TSynFoldNodeInfo; EndOffs: Integer;
|
||||
ABlockType: TPascalCodeFoldBlockType; aActions: TSynFoldActions;
|
||||
AIsFold: Boolean);
|
||||
// Divider
|
||||
procedure CreateDividerDrawConfig;
|
||||
procedure DestroyDividerDrawConfig;
|
||||
protected
|
||||
@ -459,11 +467,17 @@ type
|
||||
function GetIdentChars: TSynIdentChars; override;
|
||||
function IsFilterStored: boolean; override; //mh 2000-10-08
|
||||
protected
|
||||
// "Range"
|
||||
function GetRangeClass: TSynCustomHighlighterRangeClass; override;
|
||||
procedure CreateRootCodeFoldBlock; override;
|
||||
function CreateRangeList(ALines: TSynEditStringsBase): TSynHighlighterRangeList; override;
|
||||
function UpdateRangeInfoAtLine(Index: Integer): Boolean; override; // Returns true if range changed
|
||||
|
||||
property PasCodeFoldRange: TSynPasSynRange read GetPasCodeFoldRange;
|
||||
function TopPascalCodeFoldBlockType
|
||||
(DownIndex: Integer = 0): TPascalCodeFoldBlockType;
|
||||
|
||||
// Open/Close Folds
|
||||
function StartPascalCodeFoldBlock
|
||||
(ABlockType: TPascalCodeFoldBlockType): TSynCustomCodeFoldBlock;
|
||||
procedure EndPascalCodeFoldBlock(NoMarkup: Boolean = False);
|
||||
@ -473,24 +487,19 @@ type
|
||||
procedure StartCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType);
|
||||
procedure EndCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType);
|
||||
|
||||
// Info about Folds
|
||||
function CreateFoldNodeInfoList: TLazSynFoldNodeInfoList; override;
|
||||
procedure InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx); override;
|
||||
protected
|
||||
property PasCodeFoldRange: TSynPasSynRange read GetPasCodeFoldRange;
|
||||
function TopPascalCodeFoldBlockType
|
||||
(DownIndex: Integer = 0): TPascalCodeFoldBlockType;
|
||||
|
||||
public
|
||||
function MinimumPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
|
||||
function EndPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
|
||||
protected
|
||||
function LastLinePasFoldLevelFix(Index: Integer; AType: Integer = 1): integer; // foldable nodes
|
||||
function LastLineFoldLevelFix(Index: Integer): integer; // all nodes
|
||||
function LastLinePasFoldLevelFix(Index: Integer; AType: Integer = 1): integer; // TODO deprecated; // foldable nodes
|
||||
|
||||
// Divider
|
||||
function GetDrawDivider(Index: integer): TSynDividerDrawConfigSetting; override;
|
||||
function GetDividerDrawConfig(Index: Integer): TSynDividerDrawConfig; override;
|
||||
function GetDividerDrawConfigCount: Integer; override;
|
||||
|
||||
// Fold Config
|
||||
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
|
||||
function GetFoldConfigCount: Integer; override;
|
||||
function GetFoldConfigInternalCount: Integer; override;
|
||||
@ -523,19 +532,18 @@ type
|
||||
function UseUserSettings(settingIndex: integer): boolean; override;
|
||||
procedure EnumUserSettings(settings: TStrings); override;
|
||||
|
||||
// fold-nodes that can be collapsed
|
||||
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
|
||||
// Info about Folds
|
||||
//function FoldBlockOpeningCount(ALineIndex: TLineIdx; const AFilter: TSynFoldBlockFilter): integer; override; overload;
|
||||
//function FoldBlockClosingCount(ALineIndex: TLineIdx; const AFilter: TSynFoldBlockFilter): integer; override; overload;
|
||||
function FoldBlockEndLevel(ALineIndex: TLineIdx; const AFilter: TSynFoldBlockFilter): integer; override; overload;
|
||||
function FoldBlockMinLevel(ALineIndex: TLineIdx; const AFilter: TSynFoldBlockFilter): integer; override; overload;
|
||||
|
||||
function FoldTypeCount: integer; override;
|
||||
function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer; // accesses FoldNodeInfo
|
||||
UseCloseNodes: boolean = false): integer; override;
|
||||
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; override; // accesses FoldNodeInfo
|
||||
function FoldEndLine(ALineIndex, FoldIndex: Integer): integer; override; // accesses FoldNodeInfo
|
||||
|
||||
// All fold nodes // TODO: make private
|
||||
function MinimumFoldLevel(Index: Integer): integer; override;
|
||||
function EndFoldLevel(Index: Integer): integer; override;
|
||||
published
|
||||
property AsmAttri: TSynHighlighterAttributes read fAsmAttri write fAsmAttri;
|
||||
property CommentAttri: TSynHighlighterAttributes read fCommentAttri
|
||||
@ -1091,7 +1099,6 @@ begin
|
||||
if TopPascalCodeFoldBlockType in [cfbtVarType, cfbtLocalVarType] then
|
||||
EndPascalCodeFoldBlockLastLine;
|
||||
StartPascalCodeFoldBlock(cfbtAsm);
|
||||
//debugln('TSynPasSyn.Func37 BEGIN ',dbgs(ord(TopPascalCodeFoldBlockType)),' LineNumber=',dbgs(fLineNumber),' ',dbgs(MinimumCodeFoldBlockLevel),' ',dbgs(CurrentCodeFoldBlockLevel));
|
||||
end
|
||||
else Result := tkIdentifier;
|
||||
end;
|
||||
@ -2361,7 +2368,7 @@ begin
|
||||
fLine:=PChar(Pointer(fLineStr));
|
||||
Run := 0;
|
||||
Inherited SetLine(NewValue,LineNumber);
|
||||
FStartCodeFoldBlockLevel := MinimumCodeFoldBlockLevel;
|
||||
FStartCodeFoldBlockLevel := PasCodeFoldRange.MinimumCodeFoldBlockLevel;
|
||||
PasCodeFoldRange.LastLineCodeFoldLevelFix := 0;
|
||||
PasCodeFoldRange.PasFoldFixLevel := 0;
|
||||
PasCodeFoldRange.PasFoldMinLevel := PasCodeFoldRange.PasFoldEndLevel;
|
||||
@ -3156,6 +3163,100 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.FoldBlockEndLevel(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer;
|
||||
var
|
||||
inf: TSynPasRangeInfo;
|
||||
r, r2: Pointer;
|
||||
begin
|
||||
Assert(CurrentRanges <> nil, 'TSynCustomFoldHighlighter.FoldBlockEndLevel requires CurrentRanges');
|
||||
|
||||
Result := 0;
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count - 1) then
|
||||
exit;
|
||||
|
||||
if AFilter.FoldGroup in [0, FOLDGROUP_REGION, FOLDGROUP_IFDEF] then
|
||||
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
|
||||
|
||||
if AFilter.FoldGroup in [0, FOLDGROUP_PASCAL] then begin
|
||||
// All or Pascal
|
||||
r := CurrentRanges[ALineIndex];
|
||||
if (r <> nil) and (r <> NullRange) then begin
|
||||
r2 := TSynPasSynRange(CurrentRanges[ALineIndex + 1]);
|
||||
if sfbIncludeDisabled in AFilter.Flags then begin
|
||||
Result := TSynPasSynRange(r).CodeFoldStackSize;
|
||||
if (r2 <> nil) and (r2 <> NullRange) then
|
||||
Result := Result + TSynPasSynRange(r2).LastLineCodeFoldLevelFix;
|
||||
end
|
||||
else begin
|
||||
Result := TSynPasSynRange(r).PasFoldEndLevel;
|
||||
if (r2 <> nil) and (r2 <> NullRange) then
|
||||
Result := Result + TSynPasSynRange(r2).PasFoldFixLevel;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if AFilter.FoldGroup in [0, FOLDGROUP_REGION] then begin
|
||||
// All or REGION
|
||||
Result := Result + inf.EndLevelRegion;
|
||||
end;
|
||||
|
||||
if AFilter.FoldGroup in [0, FOLDGROUP_IFDEF] then begin
|
||||
// All or IFDEF
|
||||
Result := Result + inf.EndLevelIfDef;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.FoldBlockMinLevel(ALineIndex: TLineIdx;
|
||||
const AFilter: TSynFoldBlockFilter): integer;
|
||||
var
|
||||
inf: TSynPasRangeInfo;
|
||||
r, r2: Pointer;
|
||||
begin
|
||||
Assert(CurrentRanges <> nil, 'TSynCustomFoldHighlighter.FoldBlockMinLevel requires CurrentRanges');
|
||||
|
||||
Result := 0;
|
||||
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count - 1) then
|
||||
exit;
|
||||
|
||||
if AFilter.FoldGroup in [0, FOLDGROUP_REGION, FOLDGROUP_IFDEF] then
|
||||
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
|
||||
|
||||
if AFilter.FoldGroup in [0, FOLDGROUP_PASCAL] then begin
|
||||
// All or Pascal
|
||||
(* Range.EndLevel can be smaller. because it Range.MinLevel does not know the LastLiineFix
|
||||
Using a copy of FoldBlockEndLevel *)
|
||||
r := CurrentRanges[ALineIndex];
|
||||
if (r <> nil) and (r <> NullRange) then begin
|
||||
r2 := TSynPasSynRange(CurrentRanges[ALineIndex + 1]);
|
||||
if sfbIncludeDisabled in AFilter.Flags then begin
|
||||
Result := TSynPasSynRange(r).CodeFoldStackSize;
|
||||
if (r2 <> nil) and (r2 <> NullRange) then
|
||||
Result := Result + TSynPasSynRange(r2).LastLineCodeFoldLevelFix;
|
||||
// now Result = FoldBlockEndLevel
|
||||
Result := Min(Result, TSynPasSynRange(r).MinimumCodeFoldBlockLevel);
|
||||
end
|
||||
else begin
|
||||
Result := TSynPasSynRange(r).PasFoldEndLevel;
|
||||
if (r2 <> nil) and (r2 <> NullRange) then
|
||||
Result := Result + TSynPasSynRange(r2).PasFoldFixLevel;
|
||||
// now Result = FoldBlockEndLevel
|
||||
Result := Min(Result, TSynPasSynRange(r).PasFoldMinLevel);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if AFilter.FoldGroup in [0, FOLDGROUP_REGION] then begin
|
||||
// All or REGION
|
||||
Result := Result + inf.MinLevelRegion;
|
||||
end;
|
||||
|
||||
if AFilter.FoldGroup in [0, FOLDGROUP_IFDEF] then begin
|
||||
// All or IFDEF
|
||||
Result := Result + inf.MinLevelIfDef;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.TopPascalCodeFoldBlockType(DownIndex: Integer = 0): TPascalCodeFoldBlockType;
|
||||
var
|
||||
p: Pointer;
|
||||
@ -3166,63 +3267,6 @@ begin
|
||||
Result := TPascalCodeFoldBlockType(PtrUInt(p));
|
||||
end;
|
||||
|
||||
function TSynPasSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer;
|
||||
var
|
||||
inf: TSynPasRangeInfo;
|
||||
begin
|
||||
Result := 0;
|
||||
if not(AType in [1, 4]) then
|
||||
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
|
||||
if (AType = 0) or (AType = 1) then
|
||||
Result := EndPasFoldLevel(ALineIndex) - MinimumPasFoldLevel(ALineIndex);
|
||||
if (AType = 0) or (AType = 2) then
|
||||
Result := Result + inf.EndLevelRegion - inf.MinLevelRegion;
|
||||
if (AType = 0) or (AType = 3) then
|
||||
Result := Result + inf.EndLevelIfDef - inf.MinLevelIfDef;
|
||||
if (AType = 4) then
|
||||
Result := EndPasFoldLevel(ALineIndex, 4) - MinimumPasFoldLevel(ALineIndex, 4);
|
||||
if Result < 0 then
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer;
|
||||
var
|
||||
inf, inf2: TSynPasRangeInfo;
|
||||
begin
|
||||
Result := 0;
|
||||
if not(AType in [1, 4]) then begin
|
||||
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
|
||||
inf2 := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex - 1];
|
||||
end;
|
||||
if (AType = 0) or (AType = 1) then
|
||||
Result := EndPasFoldLevel(ALineIndex - 1)
|
||||
- min(MinimumPasFoldLevel(ALineIndex), EndPasFoldLevel(ALineIndex));
|
||||
if (AType = 0) or (AType = 2) then
|
||||
Result := Result + inf2.EndLevelRegion - inf.MinLevelRegion;
|
||||
if (AType = 0) or (AType = 3) then
|
||||
Result := Result + inf2.EndLevelIfDef - inf.MinLevelIfDef;
|
||||
if (AType = 4) then
|
||||
Result := EndPasFoldLevel(ALineIndex - 1, 4)
|
||||
- min(MinimumPasFoldLevel(ALineIndex, 4), EndPasFoldLevel(ALineIndex, 4));
|
||||
end;
|
||||
|
||||
function TSynPasSyn.FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer;
|
||||
var
|
||||
inf: TSynPasRangeInfo;
|
||||
begin
|
||||
Result := 0;
|
||||
if not(AType in [1, 4]) then
|
||||
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
|
||||
if (AType = 0) or (AType = 1) then
|
||||
Result := EndPasFoldLevel(ALineIndex);
|
||||
if (AType = 0) or (AType = 2) then
|
||||
Result := Result + inf.EndLevelRegion;
|
||||
if (AType = 0) or (AType = 3) then
|
||||
Result := Result + inf.EndLevelIfDef;
|
||||
if (AType = 4) then
|
||||
Result := EndPasFoldLevel(ALineIndex, 4);
|
||||
end;
|
||||
|
||||
function TSynPasSyn.FoldTypeCount: integer;
|
||||
begin
|
||||
Result := 3;
|
||||
@ -3264,7 +3308,7 @@ begin
|
||||
|
||||
Result := FoldEndLine(ALineIndex, FoldIndex);
|
||||
// check if fold last line of block (not mixed "end begin")
|
||||
if (EndPasFoldLevel(Result, atype) > MinimumPasFoldLevel(Result, atype)) then
|
||||
if (FoldBlockEndLevel(Result, atype) > FoldBlockMinLevel(Result, atype)) then
|
||||
dec(Result);
|
||||
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
|
||||
Result := Result - ALineIndex;
|
||||
@ -3292,81 +3336,13 @@ begin
|
||||
lvl := node.FoldLvlEnd;
|
||||
|
||||
Result := ALineIndex + 1;
|
||||
while (Result < cnt) and (MinimumPasFoldLevel(Result, atype) >= lvl) do inc(Result);
|
||||
while (Result < cnt) and (FoldBlockMinLevel(Result, atype) >= lvl) do inc(Result);
|
||||
// check if fold last line of block (not mixed "end begin")
|
||||
// and not lastlinefix
|
||||
if (Result = cnt) then
|
||||
dec(Result);
|
||||
end;
|
||||
|
||||
function TSynPasSyn.MinimumPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
|
||||
var
|
||||
r: TSynPasSynRange;
|
||||
begin
|
||||
case AType of
|
||||
2:
|
||||
Result := TSynHighlighterPasRangeList(CurrentRanges).
|
||||
PasRangeInfo[Index].MinLevelRegion;
|
||||
3:
|
||||
Result := TSynHighlighterPasRangeList(CurrentRanges).
|
||||
PasRangeInfo[Index].MinLevelIfDef;
|
||||
4: // all pascal nodes (incl. not folded)
|
||||
begin
|
||||
if (Index < 0) or (Index >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynPasSynRange(CurrentRanges[Index]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then begin
|
||||
Result := Min(r.CodeFoldStackSize + LastLinePasFoldLevelFix(Index + 1, 4),
|
||||
r.MinimumCodeFoldBlockLevel);
|
||||
end else
|
||||
Result := 0;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
if (Index < 0) or (Index >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynPasSynRange(CurrentRanges[Index]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then begin
|
||||
Result := Min(r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1),
|
||||
r.PasFoldMinLevel)
|
||||
end else
|
||||
Result := 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.EndPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
|
||||
var
|
||||
r: TSynPasSynRange;
|
||||
begin
|
||||
if (Index < 0) or (Index >= CurrentLines.Count - 1) then
|
||||
exit(0);
|
||||
case AType of
|
||||
2:
|
||||
Result := TSynHighlighterPasRangeList(CurrentRanges).
|
||||
PasRangeInfo[Index].EndLevelRegion;
|
||||
3:
|
||||
Result := TSynHighlighterPasRangeList(CurrentRanges).
|
||||
PasRangeInfo[Index].EndLevelIfDef;
|
||||
4: // all pascal nodes (incl. not folded)
|
||||
begin
|
||||
r := TSynPasSynRange(CurrentRanges[Index]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.CodeFoldStackSize
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
r := TSynPasSynRange(CurrentRanges[Index]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1)
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.LastLinePasFoldLevelFix(Index: Integer; AType: Integer = 1): integer;
|
||||
var
|
||||
r: TSynPasSynRange;
|
||||
@ -3397,49 +3373,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function TSynPasSyn.MinimumFoldLevel(Index: Integer): integer;
|
||||
var
|
||||
r: TSynPasSynRange;
|
||||
begin
|
||||
if (Index < 0) or (Index >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynPasSynRange(CurrentRanges[Index]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := Min(r.CodeFoldStackSize + LastLineFoldLevelFix(Index + 1),
|
||||
r.MinimumCodeFoldBlockLevel)
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.EndFoldLevel(Index: Integer): integer;
|
||||
var
|
||||
r: TSynPasSynRange;
|
||||
begin
|
||||
if (Index < 0) or (Index >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynPasSynRange(CurrentRanges[Index]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.CodeFoldStackSize + LastLineFoldLevelFix(Index + 1)
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.LastLineFoldLevelFix(Index: Integer): integer;
|
||||
var
|
||||
r: TSynPasSynRange;
|
||||
begin
|
||||
if (Index < 0) or (Index >= CurrentLines.Count) then
|
||||
exit(0);
|
||||
r := TSynPasSynRange(CurrentRanges[Index]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.LastLineCodeFoldLevelFix
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
|
||||
procedure TSynPasSyn.InitNode(var Node: TSynFoldNodeInfo; EndOffs: Integer;
|
||||
procedure TSynPasSyn.InitNode(out Node: TSynFoldNodeInfo; EndOffs: Integer;
|
||||
ABlockType: TPascalCodeFoldBlockType; aActions: TSynFoldActions; AIsFold: Boolean);
|
||||
var
|
||||
OneLine: Boolean;
|
||||
@ -3455,30 +3389,29 @@ begin
|
||||
case ABlockType of
|
||||
cfbtRegion:
|
||||
begin
|
||||
node.FoldGroup := 2;
|
||||
node.FoldGroup := FOLDGROUP_REGION;
|
||||
Node.FoldLvlStart := FSynPasRangeInfo.EndLevelRegion;
|
||||
Node.NestLvlStart := FSynPasRangeInfo.EndLevelRegion;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > FSynPasRangeInfo.MinLevelRegion);
|
||||
end;
|
||||
cfbtIfDef:
|
||||
begin
|
||||
node.FoldGroup := 3;
|
||||
node.FoldGroup := FOLDGROUP_IFDEF;
|
||||
Node.FoldLvlStart := FSynPasRangeInfo.EndLevelIfDef;
|
||||
Node.NestLvlStart := FSynPasRangeInfo.EndLevelIfDef;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > FSynPasRangeInfo.MinLevelIfDef);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
node.FoldGroup := FOLDGROUP_PASCAL;
|
||||
if AIsFold then begin
|
||||
node.FoldGroup := 1;
|
||||
Node.FoldLvlStart := PasCodeFoldRange.PasFoldEndLevel;
|
||||
Node.NestLvlStart := CurrentCodeFoldBlockLevel;
|
||||
Node.NestLvlStart := PasCodeFoldRange.CodeFoldStackSize;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > PasCodeFoldRange.PasFoldMinLevel); // MinimumCodeFoldBlockLevel);
|
||||
end else begin
|
||||
node.FoldGroup := 4;
|
||||
Node.FoldLvlStart := PasCodeFoldRange.CodeFoldStackSize;
|
||||
Node.NestLvlStart := CurrentCodeFoldBlockLevel;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > PasCodeFoldRange.MinimumCodeFoldBlockLevel); // MinimumCodeFoldBlockLevel);
|
||||
Node.NestLvlStart := PasCodeFoldRange.CodeFoldStackSize;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > PasCodeFoldRange.MinimumCodeFoldBlockLevel);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -3584,7 +3517,7 @@ begin
|
||||
NextToEol;
|
||||
|
||||
fStringLen := 0;
|
||||
i := LastLineFoldLevelFix(Line+1);
|
||||
i := LastLinePasFoldLevelFix(Line+1, 4);
|
||||
while i < 0 do begin
|
||||
EndPascalCodeFoldBlock;
|
||||
inc(i);
|
||||
@ -3706,7 +3639,7 @@ begin
|
||||
EndPascalCodeFoldBlock;
|
||||
if FAtLineStart then begin
|
||||
// If we are not at linestart, new folds could have been opened => handle as normal close
|
||||
if (CurrentCodeFoldBlockLevel < FStartCodeFoldBlockLevel) and
|
||||
if (PasCodeFoldRange.CodeFoldStackSize < FStartCodeFoldBlockLevel) and
|
||||
(FStartCodeFoldBlockLevel > 0)
|
||||
then begin
|
||||
PasCodeFoldRange.DecLastLineCodeFoldLevelFix;
|
||||
@ -3738,7 +3671,7 @@ function TSynPasSyn.GetDrawDivider(Index: integer): TSynDividerDrawConfigSetting
|
||||
begin
|
||||
i := 0;
|
||||
j := StartLvl;
|
||||
m := CurrentCodeFoldBlockLevel;
|
||||
m := PasCodeFoldRange.CodeFoldStackSize;;
|
||||
t := TopPascalCodeFoldBlockType(j);
|
||||
while (i <= MaxDepth) and (j < m) and
|
||||
((t in CountTypes) or (t in SkipTypes)) do begin
|
||||
@ -3759,17 +3692,20 @@ var
|
||||
begin
|
||||
Result := inherited;
|
||||
if (index = 0) then exit;
|
||||
CloseCnt := EndFoldLevel(Index - 1) - MinimumFoldLevel(Index);
|
||||
if (CloseCnt = 0) or (MinimumFoldLevel(Index) <> EndFoldLevel(Index)) then // not a mixed line
|
||||
CloseCnt := FoldBlockClosingCount(Index, FOLDGROUP_PASCAL, [sfbIncludeDisabled]);
|
||||
if (CloseCnt = 0) or
|
||||
(FoldBlockMinLevel(Index, FOLDGROUP_PASCAL, [sfbIncludeDisabled])
|
||||
<> FoldBlockEndLevel(Index, FOLDGROUP_PASCAL, [sfbIncludeDisabled]))
|
||||
then // not a mixed line
|
||||
exit;
|
||||
|
||||
// SetRange[Index] has the folds at the start of this line
|
||||
// ClosedByNextLine: Folds closed by the next lines LastLineFix
|
||||
// must be taken from SetRange[Index+1] (end of this line)
|
||||
ClosedByNextLine := -LastLineFoldLevelFix(Index + 1);
|
||||
ClosedByNextLine := -LastLinePasFoldLevelFix(Index + 1, 4);
|
||||
// ClosedInLastLine: Folds Closed by this lines LastLineFix
|
||||
// must be ignored. (They are part of SetRange[Index] / this line)
|
||||
ClosedInLastLine := -LastLineFoldLevelFix(Index);
|
||||
ClosedInLastLine := -LastLinePasFoldLevelFix(Index, 4);
|
||||
|
||||
// Get the highest close-offset
|
||||
i := ClosedByNextLine - 1;
|
||||
|
||||
@ -56,7 +56,7 @@ interface
|
||||
{$I SynEdit.inc}
|
||||
|
||||
uses
|
||||
Classes, math, Graphics, SynEditTypes, SynEditHighlighter,
|
||||
Classes, Graphics, SynEditTypes, SynEditHighlighter,
|
||||
SynEditHighlighterFoldBase, SynEditHighlighterXMLBase;
|
||||
|
||||
type
|
||||
@ -98,22 +98,6 @@ type
|
||||
|
||||
type
|
||||
|
||||
{ TSynHighlighterXmlRangeList }
|
||||
|
||||
TSynHighlighterXmlRangeList = class(TSynHighlighterRangeList)
|
||||
private
|
||||
FItemOffset: Integer;
|
||||
function GetXmlRangeInfo(Index: Integer): TSynXmlRangeInfo;
|
||||
procedure SetXmlRangeInfo(Index: Integer; const AValue: TSynXmlRangeInfo);
|
||||
protected
|
||||
procedure SetCapacity(const AValue: Integer); override;
|
||||
public
|
||||
constructor Create;
|
||||
procedure Move(AFrom, ATo, ALen: Integer); override;
|
||||
property XmlRangeInfo[Index: Integer]: TSynXmlRangeInfo
|
||||
read GetXmlRangeInfo write SetXmlRangeInfo;
|
||||
end;
|
||||
|
||||
TProcTableProc = procedure of object;
|
||||
|
||||
{ TSynXMLSyn }
|
||||
@ -1010,65 +994,8 @@ begin
|
||||
Result := ord(high(TXmlCodeFoldBlockType)) - ord(low(TXmlCodeFoldBlockType)) + 1;
|
||||
end;
|
||||
|
||||
{ TSynHighlighterXmlRangeList }
|
||||
|
||||
function TSynHighlighterXmlRangeList.GetXmlRangeInfo(Index: Integer): TSynXmlRangeInfo;
|
||||
begin
|
||||
if (Index < 0) or (Index >= Count) then begin
|
||||
Result.ElementOpenList := nil;
|
||||
exit;
|
||||
end;
|
||||
Result := TSynXmlRangeInfo((ItemPointer[Index] + FItemOffset)^);
|
||||
end;
|
||||
|
||||
procedure TSynHighlighterXmlRangeList.SetXmlRangeInfo(Index: Integer;
|
||||
const AValue: TSynXmlRangeInfo);
|
||||
begin
|
||||
TSynXmlRangeInfo((ItemPointer[Index] + FItemOffset)^) := AValue;
|
||||
end;
|
||||
|
||||
procedure TSynHighlighterXmlRangeList.SetCapacity(const AValue: Integer);
|
||||
var
|
||||
i: LongInt;
|
||||
begin
|
||||
for i := AValue to Capacity-1 do
|
||||
with TSynXmlRangeInfo((ItemPointer[i] + FItemOffset)^) do begin
|
||||
ElementOpenList := nil;
|
||||
ElementCloseList := nil;
|
||||
end;
|
||||
inherited SetCapacity(AValue);
|
||||
end;
|
||||
|
||||
constructor TSynHighlighterXmlRangeList.Create;
|
||||
begin
|
||||
inherited;
|
||||
FItemOffset := ItemSize;
|
||||
ItemSize := FItemOffset + SizeOf(TSynXmlRangeInfo);
|
||||
end;
|
||||
|
||||
procedure TSynHighlighterXmlRangeList.Move(AFrom, ATo, ALen: Integer);
|
||||
var
|
||||
i: LongInt;
|
||||
begin
|
||||
if ATo > AFrom then
|
||||
for i:= Max(AFrom + ALen, ATo) to ATo + ALen - 1 do // move forward
|
||||
with TSynXmlRangeInfo((ItemPointer[i] + FItemOffset)^) do begin
|
||||
ElementOpenList := nil;
|
||||
ElementCloseList := nil;
|
||||
end
|
||||
else
|
||||
for i:= ATo to Min(ATo + ALen , AFrom) - 1 do // move backward
|
||||
with TSynXmlRangeInfo((ItemPointer[i] + FItemOffset)^) do begin
|
||||
ElementOpenList := nil;
|
||||
ElementCloseList := nil;
|
||||
end;
|
||||
inherited Move(AFrom, ATo, ALen);
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterPlaceableHighlighter(TSynXMLSyn);
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
||||
@ -39,13 +39,14 @@ type
|
||||
function TestText5: TStringArray;
|
||||
function TestText6: TStringArray;
|
||||
function TestText7: TStringArray;
|
||||
function TestText8: TStringArray;
|
||||
function TestTextHide(ALen: Integer): TStringArray;
|
||||
function TestTextHide2(ALen: Integer): TStringArray;
|
||||
function TestTextHide3: TStringArray;
|
||||
function TestTextHide4: TStringArray;
|
||||
function TestTextPlain: TStringArray;
|
||||
protected
|
||||
procedure TstSetText(AName: String; AText: TStringArray);
|
||||
procedure TstSetText(AName: String; AText: Array of String);
|
||||
procedure TstFold(AName: String; AFoldAtIndex: integer; AExpectedLines: Array of Integer);
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum: integer; AExpectedLines: Array of Integer);
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
@ -66,6 +67,7 @@ type
|
||||
procedure TestFoldEdit;
|
||||
procedure TestFoldStateFromText;
|
||||
procedure TestFoldStateDesc;
|
||||
procedure TestFoldProvider;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -73,7 +75,7 @@ implementation
|
||||
type
|
||||
TSynEditFoldedViewHack = class(TSynEditFoldedView) end;
|
||||
|
||||
procedure TTestFoldedView.TstSetText(AName: String; AText: TStringArray);
|
||||
procedure TTestFoldedView.TstSetText(AName: String; AText: array of String);
|
||||
begin
|
||||
PopBaseName;
|
||||
ReCreateEdit;
|
||||
@ -406,6 +408,32 @@ begin
|
||||
Result[26] := '';
|
||||
end;
|
||||
|
||||
function TTestFoldedView.TestText8: TStringArray;
|
||||
begin
|
||||
// end begin lines, with mixed type
|
||||
SetLength(Result, 20);
|
||||
Result[0] := 'program Foo;';
|
||||
Result[1] := 'procedure a;';
|
||||
Result[2] := 'begin';
|
||||
Result[3] := '{%region}';
|
||||
Result[4] := '{%endregion} {$ifdef x}';
|
||||
Result[5] := ' {$endif} if a then begin';
|
||||
Result[6] := ' end; {%region}';
|
||||
Result[7] := '{%endregion} {$ifdef x}';
|
||||
Result[8] := ' {$endif} if a then begin';
|
||||
Result[9] := ' writeln(1);';
|
||||
Result[10] := '{%region} end;';
|
||||
Result[11] := ' writeln(1);';
|
||||
Result[12] := '{%endregion} if a then begin';
|
||||
Result[13] := ' writeln(1);';
|
||||
Result[14] := '{$ifdef x} end;';
|
||||
Result[15] := ' writeln(1);';
|
||||
Result[16] := '{$endif}';
|
||||
Result[17] := ' writeln(1);';
|
||||
Result[18] := 'end';
|
||||
Result[19] := '';
|
||||
end;
|
||||
|
||||
function TTestFoldedView.TestTextHide(ALen: Integer): TStringArray;
|
||||
begin
|
||||
SetLength(Result, 3+ALen);
|
||||
@ -1457,6 +1485,161 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
procedure TTestFoldedView.TestFoldProvider;
|
||||
procedure DoTestOpenCounts(AName: string; AType: Integer; AExp: Array of Integer);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
AName := AName + ' (type=' + IntToStr(AType)+') ';
|
||||
for i := low(AExp) to high(AExp) do
|
||||
DebugLn([BaseTestName+AName+ ' line=' + IntToStr(i)+ ' exp=', AExp[i],' Got=', FoldedView.FoldProvider.FoldOpenCount(i, AType)]);
|
||||
for i := low(AExp) to high(AExp) do
|
||||
AssertEquals(BaseTestName+AName+ ' line=' + IntToStr(i),
|
||||
AExp[i], FoldedView.FoldProvider.FoldOpenCount(i, AType));
|
||||
end;
|
||||
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
// TSynEditFoldProvider.FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
|
||||
PushBaseName('');
|
||||
|
||||
TstSetText('TestText1', TestText);
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone]);
|
||||
// p P B ~ -
|
||||
DoTestOpenCounts('', 0, [1, 1, 1, 0, 0]); // all (fold conf)
|
||||
DoTestOpenCounts('', 1, [1, 1, 1, 0, 0]); // pas
|
||||
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0]); // pas (incl unfolded)
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0]); // $if
|
||||
|
||||
TstSetText('TestText1 (2)', TestText);
|
||||
EnableFolds([cfbtTopBeginEnd]);
|
||||
// p P B ~ -
|
||||
DoTestOpenCounts('', 0, [0, 0, 1, 0, 0]); // all (fold conf)
|
||||
DoTestOpenCounts('', 1, [0, 0, 1, 0, 0]); // pas
|
||||
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0]); // pas (incl unfolded)
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0]); // $if
|
||||
|
||||
TstSetText('TestText1 (3)', TestText);
|
||||
EnableFolds([cfbtProcedure, cfbtBeginEnd]);
|
||||
// p P B ~ -
|
||||
DoTestOpenCounts('', 0, [0, 1, 0, 0, 0]); // all (fold conf)
|
||||
DoTestOpenCounts('', 1, [0, 1, 0, 0, 0]); // pas
|
||||
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0]); // pas (incl unfolded)
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0]); // $if
|
||||
|
||||
|
||||
|
||||
TstSetText('TestText2', TestText2);
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone]);
|
||||
// if else
|
||||
// p PP B - B B ~ -B ~ - - ~
|
||||
DoTestOpenCounts('', 0, [1, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 1, [1, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
|
||||
//DoTestOpenCounts('', 4, [1, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
TstSetText('TestText2 (2)', TestText2);
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtProgram, cfbtRegion]);
|
||||
// p PP B - B B ~ -B ~ - - ~
|
||||
DoTestOpenCounts('', 0, [0, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 1, [0, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
|
||||
//DoTestOpenCounts('', 4, [1, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
|
||||
|
||||
TstSetText('TestText3', TestText3);
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone], [cfbtSlashComment]);
|
||||
// if else // one-line-comment
|
||||
// p $ P - B %B ~ --B~ - - /
|
||||
DoTestOpenCounts('', 0, [1, 1, 1, 0, 1, 2, 0, 1, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 1, [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
|
||||
//DoTestOpenCounts('', 4, [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // %if
|
||||
|
||||
TstSetText('TestText3 (2)', TestText3);
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtProgram, cfbtRegion], [cfbtSlashComment]);
|
||||
// p $ P - B %B ~ --B~ - - /
|
||||
DoTestOpenCounts('', 0, [0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 1, [0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
|
||||
//DoTestOpenCounts('', 4, [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // %if
|
||||
|
||||
TstSetText('TestText3 (3)', TestText3);
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtProgram, cfbtIfDef], []);
|
||||
// p $ P - B %B ~ --B~ - - /
|
||||
DoTestOpenCounts('', 0, [0, 0, 1, 0, 1, 2, 0, 1, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 1, [0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
|
||||
//DoTestOpenCounts('', 4, [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // %if
|
||||
|
||||
|
||||
|
||||
for i := 0 to 2 do begin // pos of $IFDEF does not matter
|
||||
TstSetText('TestTextPasHl-'+IntToStr(i)+'', TestTextPasHl(i));
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone], [cfbtSlashComment]);
|
||||
// if $E // one-line-comment
|
||||
// p P $bb- - - /
|
||||
DoTestOpenCounts('', 0, [1, 1, 3, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 1, [1, 1, 2, 0, 0, 0, 1]);
|
||||
//DoTestOpenCounts('', 4, [1, 1, 2, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 0, 1, 0, 0, 0, 0]); // %if
|
||||
|
||||
TstSetText('TestTextPasHl-'+IntToStr(i)+'', TestTextPasHl(i));
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtBeginEnd], [cfbtSlashComment]);
|
||||
// if $E // one-line-comment
|
||||
// p P $bb- - - /
|
||||
DoTestOpenCounts('', 0, [1, 1, 2, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 1, [1, 1, 1, 0, 0, 0, 1]);
|
||||
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 0, 1, 0, 0, 0, 0]); // %if
|
||||
|
||||
TstSetText('TestTextPasHl-'+IntToStr(i)+'', TestTextPasHl(i));
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtIfDef], [cfbtSlashComment]);
|
||||
// if $E // one-line-comment
|
||||
// p P $bb- - - /
|
||||
DoTestOpenCounts('', 0, [1, 1, 2, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 1, [1, 1, 2, 0, 0, 0, 1]);
|
||||
//DoTestOpenCounts('', 4, [1, 1, 2, 0, 0, 0, 1]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0]); // %region
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0, 0]); // %if
|
||||
end;
|
||||
|
||||
|
||||
|
||||
TstSetText('TestText4', TestText4);
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone], [cfbtSlashComment]);
|
||||
// pPBB - B - B -
|
||||
DoTestOpenCounts('', 0, [3, 1, 0, 1, 0, 1]);
|
||||
DoTestOpenCounts('', 1, [3, 1, 0, 1, 0, 1]);
|
||||
//DoTestOpenCounts('', 4, [3, 1, 0, 1, 0, 1]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0]);
|
||||
|
||||
|
||||
|
||||
TstSetText('TestText8', TestText8);
|
||||
EnableFolds([cfbtBeginEnd..cfbtNone], [cfbtSlashComment]);
|
||||
// p P B % $ B % $ B ~ % ~ B ~ $ ~ - ~ -
|
||||
DoTestOpenCounts('', 0, [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 1, [1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]);
|
||||
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 2, [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
DoTestOpenCounts('', 3, [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]);
|
||||
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
RegisterTest(TTestFoldedView);
|
||||
|
||||
136
components/synedit/test/testhighlighterlfm.pas
Normal file
136
components/synedit/test/testhighlighterlfm.pas
Normal file
@ -0,0 +1,136 @@
|
||||
unit TestHighlighterLfm;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc, TestHighlightFoldBase,
|
||||
SynEdit, SynEditTypes, SynHighlighterLFM, SynEditHighlighterFoldBase;
|
||||
|
||||
type
|
||||
|
||||
{ TTestBaseHighlighterLem }
|
||||
|
||||
TTestBaseHighlighterLem = class(TTestBaseHighlighterFoldBase)
|
||||
protected
|
||||
function LfmHighLighter: TSynLFMSyn;
|
||||
function CreateTheHighLighter: TSynCustomFoldHighlighter; override;
|
||||
procedure EnableFolds(AEnbledTypes: TLfmCodeFoldBlockTypes;
|
||||
AHideTypes: TLfmCodeFoldBlockTypes = [];
|
||||
ANoFoldTypes: TLfmCodeFoldBlockTypes = []
|
||||
);
|
||||
//procedure DebugFoldInfo(ALineIdx: Integer; AFilter: TSynFoldActions; Group: Integer=0);
|
||||
//procedure DebugFoldInfo(AFilter: TSynFoldActions; Group: Integer=0);
|
||||
//function FoldActionsToString(AFoldActions: TSynFoldActions): String;
|
||||
end;
|
||||
|
||||
{ TTestHighlighterLfm }
|
||||
|
||||
TTestHighlighterLfm = class(TTestBaseHighlighterLem)
|
||||
protected
|
||||
function TestTextFoldInfo1: TStringArray;
|
||||
|
||||
procedure CheckTokensForLine(Name: String; LineIdx: Integer; ExpTokens: Array of TtkTokenKind);
|
||||
published
|
||||
procedure TestFoldInfo;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TTestBaseHighlighterLem }
|
||||
|
||||
function TTestBaseHighlighterLem.LfmHighLighter: TSynLFMSyn;
|
||||
begin
|
||||
Result := TSynLFMSyn(FTheHighLighter);
|
||||
end;
|
||||
|
||||
function TTestBaseHighlighterLem.CreateTheHighLighter: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
Result := TSynLFMSyn.Create(nil);
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterLem.EnableFolds(AEnbledTypes: TLfmCodeFoldBlockTypes;
|
||||
AHideTypes: TLfmCodeFoldBlockTypes; ANoFoldTypes: TLfmCodeFoldBlockTypes);
|
||||
var
|
||||
i: TLfmCodeFoldBlockType;
|
||||
begin
|
||||
for i := low(TLfmCodeFoldBlockType) to high(TLfmCodeFoldBlockType) do begin
|
||||
LfmHighLighter.FoldConfig[ord(i)].Enabled := i in AEnbledTypes;
|
||||
if (i in ANoFoldTypes) then
|
||||
LfmHighLighter.FoldConfig[ord(i)].Modes := []
|
||||
else
|
||||
LfmHighLighter.FoldConfig[ord(i)].Modes := [fmFold];
|
||||
if i in AHideTypes then
|
||||
LfmHighLighter.FoldConfig[ord(i)].Modes := LfmHighLighter.FoldConfig[ord(i)].Modes + [fmHide]
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTestHighlighterLfm.TestTextFoldInfo1: TStringArray;
|
||||
begin
|
||||
SetLength(Result, 11);
|
||||
Result[0] := 'object BreakPointGroupDlg: TBreakPointGroupDlg';
|
||||
Result[1] := ' Left = 431';
|
||||
Result[2] := ' Height = 225';
|
||||
Result[3] := ' object ButtonPanel1: TButtonPanel';
|
||||
Result[4] := ' Left = 6';
|
||||
Result[5] := ' end';
|
||||
Result[6] := ' object Label1: TLabel';
|
||||
Result[7] := ' Left = 0';
|
||||
Result[8] := ' end';
|
||||
Result[9] := 'end';
|
||||
Result[10] := '';
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure TTestHighlighterLfm.CheckTokensForLine(Name: String; LineIdx: Integer;
|
||||
ExpTokens: array of TtkTokenKind);
|
||||
var
|
||||
c: Integer;
|
||||
begin
|
||||
LfmHighLighter.StartAtLineIndex(LineIdx);
|
||||
c := 0;
|
||||
while not LfmHighLighter.GetEol do begin
|
||||
//DebugLn([LfmHighLighter.GetToken,' (',PasHighLighter.GetTokenID ,') at ', PasHighLighter.GetTokenPos]);
|
||||
AssertEquals(Name + 'TokenId Line='+IntToStr(LineIdx)+' pos='+IntToStr(c), ord(ExpTokens[c]), ord(LfmHighLighter.GetTokenID));
|
||||
LfmHighLighter.Next;
|
||||
inc(c);
|
||||
if c >= length(ExpTokens) then
|
||||
break;
|
||||
end;
|
||||
AssertEquals(Name+ 'TokenId Line='+IntToStr(LineIdx)+' amount of tokens', length(ExpTokens), c );
|
||||
end;
|
||||
|
||||
procedure TTestHighlighterLfm.TestFoldInfo;
|
||||
begin
|
||||
ReCreateEdit;
|
||||
|
||||
// DebugFoldInfo([]);
|
||||
|
||||
{%region}
|
||||
SetLines(TestTextFoldInfo1);
|
||||
EnableFolds([cfbtLfmObject..cfbtLfmNone]);
|
||||
PushBaseName('Text 1 all folds');
|
||||
|
||||
EnableFolds([cfbtLfmObject..cfbtLfmNone], [cfbtLfmNone]);
|
||||
AssertEquals('Len 0', 9, LfmHighLighter.FoldLineLength(0,0));
|
||||
//AssertEquals('Len 1', 0, LfmHighLighter.FoldLineLength(1,0));
|
||||
AssertEquals('Len 3', 2, LfmHighLighter.FoldLineLength(3,0));
|
||||
//AssertEquals('Len 4', 0, LfmHighLighter.FoldLineLength(4,0));
|
||||
//AssertEquals('Len 5', 0, LfmHighLighter.FoldLineLength(5,0));
|
||||
AssertEquals('Len 6', 2, LfmHighLighter.FoldLineLength(6,0));
|
||||
|
||||
CheckFoldOpenCounts('', [1, 0, 0, 1, 0, 0, 1, 0, 0, 0]);
|
||||
|
||||
{%endregion}
|
||||
|
||||
end;
|
||||
|
||||
|
||||
|
||||
initialization
|
||||
|
||||
RegisterTest(TTestHighlighterLfm);
|
||||
end.
|
||||
|
||||
116
components/synedit/test/testhighlightfoldbase.pas
Normal file
116
components/synedit/test/testhighlightfoldbase.pas
Normal file
@ -0,0 +1,116 @@
|
||||
unit TestHighlightFoldBase;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc,
|
||||
SynEdit, SynEditTypes, SynEditHighlighterFoldBase;
|
||||
|
||||
type
|
||||
|
||||
// used by Fold / MarkupWord
|
||||
|
||||
{ TTestBaseHighlighterPas }
|
||||
|
||||
{ TTestBaseHighlighterFoldBase }
|
||||
|
||||
TTestBaseHighlighterFoldBase = class(TTestBase)
|
||||
protected
|
||||
FTheHighLighter: TSynCustomFoldHighlighter;
|
||||
function CreateTheHighLighter: TSynCustomFoldHighlighter; virtual; abstract;
|
||||
procedure SetUp; override;
|
||||
procedure TearDown; override;
|
||||
procedure ReCreateEdit; reintroduce;
|
||||
|
||||
procedure CheckFoldOpenCounts(Name: String; Expected: Array of Integer);
|
||||
procedure CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions; Expected: Array of Integer);
|
||||
procedure CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions; Group: Integer; Expected: Array of Integer);
|
||||
|
||||
function FoldActionsToString(AFoldActions: TSynFoldActions): String;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ TTestBaseHighlighterFoldBase }
|
||||
|
||||
procedure TTestBaseHighlighterFoldBase.SetUp;
|
||||
begin
|
||||
FTheHighLighter := nil;
|
||||
inherited SetUp;
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterFoldBase.TearDown;
|
||||
begin
|
||||
if Assigned(SynEdit) then
|
||||
SynEdit.Highlighter := nil;
|
||||
FreeAndNil(FTheHighLighter);
|
||||
inherited TearDown;
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterFoldBase.ReCreateEdit;
|
||||
begin
|
||||
if Assigned(SynEdit) then
|
||||
SynEdit.Highlighter := nil;
|
||||
FreeAndNil(FTheHighLighter);
|
||||
inherited ReCreateEdit;
|
||||
FTheHighLighter := CreateTheHighLighter;
|
||||
SynEdit.Highlighter := FTheHighLighter;
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterFoldBase.CheckFoldOpenCounts(Name: String;
|
||||
Expected: array of Integer);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to high(Expected) do
|
||||
AssertEquals(Name + 'OpenCount Line OLD='+IntToStr(i), Expected[i], FTheHighLighter.FoldOpenCount(i));
|
||||
|
||||
for i := 0 to high(Expected) do
|
||||
AssertEquals(Name + 'OpenCount Line='+IntToStr(i), Expected[i], FTheHighLighter.FoldBlockOpeningCount(i));
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterFoldBase.CheckFoldInfoCounts(Name: String;
|
||||
Filter: TSynFoldActions; Expected: array of Integer);
|
||||
begin
|
||||
CheckFoldInfoCounts(Name, Filter, 0, Expected);
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterFoldBase.CheckFoldInfoCounts(Name: String;
|
||||
Filter: TSynFoldActions; Group: Integer; Expected: array of Integer);
|
||||
var
|
||||
i: Integer;
|
||||
l: TLazSynFoldNodeInfoList;
|
||||
begin
|
||||
for i := 0 to high(Expected) do begin
|
||||
l := FTheHighLighter.FoldNodeInfo[i];
|
||||
AssertEquals(Name + 'InfoCount(Ex) Line='+IntToStr(i),
|
||||
Expected[i],
|
||||
l.CountEx(Filter, Group));
|
||||
l.ClearFilter;
|
||||
l.ActionFilter := Filter;
|
||||
l.GroupFilter := Group;
|
||||
AssertEquals(Name + 'InfoCount Line='+IntToStr(i),
|
||||
Expected[i],
|
||||
FTheHighLighter.FoldNodeInfo[i].Count);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTestBaseHighlighterFoldBase.FoldActionsToString(AFoldActions: TSynFoldActions): String;
|
||||
var
|
||||
s: string;
|
||||
i: TSynFoldAction;
|
||||
begin
|
||||
Result:='';
|
||||
for i := low(TSynFoldAction) to high(TSynFoldAction) do
|
||||
if i in AFoldActions then begin
|
||||
WriteStr(s, i);
|
||||
Result := Result + s + ',';
|
||||
end;
|
||||
if Result <> '' then SetLength(Result, Length(Result)-1);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -5,7 +5,7 @@ unit TestHighlightPas;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc,
|
||||
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc, TestHighlightFoldBase,
|
||||
SynEdit, SynEditTypes, SynHighlighterPas, SynEditHighlighterFoldBase;
|
||||
|
||||
type
|
||||
@ -14,12 +14,10 @@ type
|
||||
|
||||
{ TTestBaseHighlighterPas }
|
||||
|
||||
TTestBaseHighlighterPas = class(TTestBase)
|
||||
TTestBaseHighlighterPas = class(TTestBaseHighlighterFoldBase)
|
||||
protected
|
||||
PasHighLighter: TSynPasSyn;
|
||||
procedure SetUp; override;
|
||||
procedure TearDown; override;
|
||||
procedure ReCreateEdit; reintroduce;
|
||||
function PasHighLighter: TSynPasSyn;
|
||||
function CreateTheHighLighter: TSynCustomFoldHighlighter; override;
|
||||
procedure EnableFolds(AEnbledTypes: TPascalCodeFoldBlockTypes;
|
||||
AHideTypes: TPascalCodeFoldBlockTypes = [];
|
||||
ANoFoldTypes: TPascalCodeFoldBlockTypes = []
|
||||
@ -38,12 +36,8 @@ type
|
||||
function TestTextFoldInfo3: TStringArray;
|
||||
function TestTextFoldInfo4(AIfCol: Integer): TStringArray;
|
||||
|
||||
procedure CheckFoldOpenCounts(Name: String; Expected: Array of Integer);
|
||||
procedure CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions; Expected: Array of Integer);
|
||||
procedure CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions; Group: Integer; Expected: Array of Integer);
|
||||
procedure CheckTokensForLine(Name: String; LineIdx: Integer; ExpTokens: Array of TtkTokenKind);
|
||||
|
||||
function FoldActionsToString(AFoldActions: TSynFoldActions): String;
|
||||
published
|
||||
procedure TestFoldInfo;
|
||||
procedure TestExtendedKeywordsAndStrings;
|
||||
@ -60,28 +54,14 @@ implementation
|
||||
|
||||
{ TTestBaseHighlighterPas }
|
||||
|
||||
procedure TTestBaseHighlighterPas.SetUp;
|
||||
function TTestBaseHighlighterPas.PasHighLighter: TSynPasSyn;
|
||||
begin
|
||||
PasHighLighter := nil;
|
||||
inherited SetUp;
|
||||
Result := TSynPasSyn(FTheHighLighter);
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterPas.TearDown;
|
||||
function TTestBaseHighlighterPas.CreateTheHighLighter: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
if Assigned(SynEdit) then
|
||||
SynEdit.Highlighter := nil;
|
||||
FreeAndNil(PasHighLighter);
|
||||
inherited TearDown;
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterPas.ReCreateEdit;
|
||||
begin
|
||||
if Assigned(SynEdit) then
|
||||
SynEdit.Highlighter := nil;
|
||||
FreeAndNil(PasHighLighter);
|
||||
inherited ReCreateEdit;
|
||||
PasHighLighter := TSynPasSyn.Create(nil);
|
||||
SynEdit.Highlighter := PasHighLighter;
|
||||
Result := TSynPasSyn.Create(nil);
|
||||
end;
|
||||
|
||||
procedure TTestBaseHighlighterPas.EnableFolds(AEnbledTypes: TPascalCodeFoldBlockTypes;
|
||||
@ -114,8 +94,8 @@ begin
|
||||
l.GroupFilter := Group;
|
||||
debugln(['### Foldinfo Line: ', ALineIdx,
|
||||
' Cnt=', l.Count, ' CntEx=', c,
|
||||
' PasMinLvl=',PasHighLighter.MinimumPasFoldLevel(ALineIdx,1),
|
||||
' EndLvl=',PasHighLighter.EndPasFoldLevel(ALineIdx,1),
|
||||
' PasMinLvl=', PasHighLighter.FoldBlockMinLevel(ALineIdx,1),
|
||||
' EndLvl=',PasHighLighter.FoldBlockEndLevel(ALineIdx,1),
|
||||
//' Nestcnt=',PasHighLighter.FoldNestCount(ALineIdx,1),
|
||||
' : ', copy(SynEdit.Lines[ALineIdx],1,40)]);
|
||||
debugln('Idx: LogXStart End FldLvlStart End NestLvlStart End FldType FldTypeCompat FldGroup FldAction');
|
||||
@ -231,40 +211,6 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
procedure TTestHighlighterPas.CheckFoldOpenCounts(Name: String; Expected: array of Integer);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to high(Expected) do
|
||||
AssertEquals(Name + 'OpenCount Line='+IntToStr(i), Expected[i], PasHighLighter.FoldOpenCount(i));
|
||||
end;
|
||||
|
||||
procedure TTestHighlighterPas.CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions;
|
||||
Expected: array of Integer);
|
||||
begin
|
||||
CheckFoldInfoCounts(Name, Filter, 0, Expected);
|
||||
end;
|
||||
|
||||
procedure TTestHighlighterPas.CheckFoldInfoCounts(Name: String;
|
||||
Filter: TSynFoldActions; Group: Integer; Expected: array of Integer);
|
||||
var
|
||||
i: Integer;
|
||||
l: TLazSynFoldNodeInfoList;
|
||||
begin
|
||||
for i := 0 to high(Expected) do begin
|
||||
l := PasHighLighter.FoldNodeInfo[i];
|
||||
AssertEquals(Name + 'InfoCount(Ex) Line='+IntToStr(i),
|
||||
Expected[i],
|
||||
l.CountEx(Filter, Group));
|
||||
l.ClearFilter;
|
||||
l.ActionFilter := Filter;
|
||||
l.GroupFilter := Group;
|
||||
AssertEquals(Name + 'InfoCount Line='+IntToStr(i),
|
||||
Expected[i],
|
||||
PasHighLighter.FoldNodeInfo[i].Count);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestHighlighterPas.CheckTokensForLine(Name: String; LineIdx: Integer;
|
||||
ExpTokens: array of TtkTokenKind);
|
||||
var
|
||||
@ -283,21 +229,6 @@ begin
|
||||
AssertEquals(Name+ 'TokenId Line='+IntToStr(LineIdx)+' amount of tokens', length(ExpTokens), c );
|
||||
end;
|
||||
|
||||
function TTestHighlighterPas.FoldActionsToString(AFoldActions: TSynFoldActions
|
||||
): String;
|
||||
var
|
||||
s: string;
|
||||
i: TSynFoldAction;
|
||||
begin
|
||||
Result:='';
|
||||
for i := low(TSynFoldAction) to high(TSynFoldAction) do
|
||||
if i in AFoldActions then begin
|
||||
WriteStr(s, i);
|
||||
Result := Result + s + ',';
|
||||
end;
|
||||
if Result <> '' then SetLength(Result, Length(Result)-1);
|
||||
end;
|
||||
|
||||
procedure TTestHighlighterPas.TestFoldInfo;
|
||||
begin
|
||||
ReCreateEdit;
|
||||
@ -1013,12 +944,12 @@ begin
|
||||
CheckFoldInfoCounts('', [], 4, [1, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 2]);
|
||||
|
||||
//### Foldinfo Line: 0 PasMinLvl=0 EndLvl=0 : program Foo;
|
||||
CheckNode( 0, [], 4, 0, 0, 7, 0, 0, 0, 1, 10, 10, 4, [sfaOpen,sfaMarkup]); // program
|
||||
CheckNode( 0, [], 4, 0, 0, 7, 0, 0, 0, 1, 10, 10, 1, [sfaOpen,sfaMarkup]); // program
|
||||
//### Foldinfo Line: 1 PasMinLvl=0 EndLvl=0 : procedure a;
|
||||
CheckNode( 1, [], 4, 0, 0, 9, 1, 1, 1, 2, 3, 3, 4, [sfaOpen,sfaMarkup]); // procedure
|
||||
CheckNode( 1, [], 4, 0, 0, 9, 1, 1, 1, 2, 3, 3, 1, [sfaOpen,sfaMarkup]); // procedure
|
||||
//### Foldinfo Line: 2 PasMinLvl=0 EndLvl=0 : {$IFDEF A}
|
||||
//### Foldinfo Line: 3 PasMinLvl=0 EndLvl=0 : begin
|
||||
CheckNode( 3, [], 4, 0, 0, 5, 2, 2, 2, 3, 1, 0, 4, [sfaOpen,sfaMarkup]); // begin
|
||||
CheckNode( 3, [], 4, 0, 0, 5, 2, 2, 2, 3, 1, 0, 1, [sfaOpen,sfaMarkup]); // begin
|
||||
//### Foldinfo Line: 4 PasMinLvl=0 EndLvl=0 : {$ENDIF}
|
||||
//### Foldinfo Line: 5 PasMinLvl=0 EndLvl=1 : {$IFDEF B} if a then begin {$ENDIF}
|
||||
CheckNode( 5, [], 4, 0, 23, 28, 0, 1, 3, 4, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]); // begin
|
||||
@ -1026,16 +957,16 @@ begin
|
||||
//### Foldinfo Line: 7 PasMinLvl=0 EndLvl=0 : end;
|
||||
CheckNode( 7, [], 4, 0, 2, 5, 1, 0, 4, 3, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]); // end
|
||||
//### Foldinfo Line: 8 PasMinLvl=0 EndLvl=0 : end;
|
||||
CheckNode( 8, [], 4, 0, 0, 3, 3, 3, 3, 2, 1, 0, 4, [sfaClose,sfaMarkup]); // end;
|
||||
CheckNode( 8, [], 4, 1, 0, 3, 2, 2, 2, 1, 3, 3, 4, [sfaClose,sfaMarkup]); // end;
|
||||
CheckNode( 8, [], 4, 0, 0, 3, 3, 3, 3, 2, 1, 0, 1, [sfaClose,sfaMarkup]); // end;
|
||||
CheckNode( 8, [], 4, 1, 0, 3, 2, 2, 2, 1, 3, 3, 1, [sfaClose,sfaMarkup]); // end;
|
||||
//### Foldinfo Line: 9 PasMinLvl=0 EndLvl=1 : begin
|
||||
CheckNode( 9, [], 4, 0, 0, 5, 0, 1, 1, 2, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]); // begin
|
||||
//### Foldinfo Line: 10 PasMinLvl=0 EndLvl=0 : end.
|
||||
CheckNode(10, [], 4, 0, 0, 3, 1, 0, 2, 1, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]); // end.
|
||||
CheckNode(10, [], 4, 1, 0, 3, 1, 1, 1, 0, 10, 10, 4, [sfaClose,sfaMarkup]); // end.
|
||||
CheckNode(10, [], 4, 1, 0, 3, 1, 1, 1, 0, 10, 10, 1, [sfaClose,sfaMarkup]); // end.
|
||||
//### Foldinfo Line: 11 PasMinLvl=0 EndLvl=0 : //
|
||||
CheckNode(11, [], 4, 0, 0, 2, 0, 0, 0, 1, 22, 22, 4, [sfaOpen]); // //
|
||||
CheckNode(11, [], 4, 1, 2, 2, 1, 1, 1, 0, 22, 22, 4, [sfaClose,sfaLastLineClose]); // /
|
||||
CheckNode(11, [], 4, 0, 0, 2, 0, 0, 0, 1, 22, 22, 1, [sfaOpen]); // //
|
||||
CheckNode(11, [], 4, 1, 2, 2, 1, 1, 1, 0, 22, 22, 1, [sfaClose,sfaLastLineClose]); // /
|
||||
{%endregion TEXT 1 -- [cfbtBeginEnd..cfbtNone], [] grp=4}
|
||||
|
||||
{%region TEXT 1 -- [cfbtBeginEnd..cfbtNone], [sfaFold]}
|
||||
@ -1116,7 +1047,7 @@ begin
|
||||
//### Foldinfo Line: 0 PasMinLvl=0 EndLvl=1 : program Foo;
|
||||
CheckNode( 0, [], 0, 0, 0, 7, 0, 1, 0, 1, 10, 10, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]);
|
||||
//### Foldinfo Line: 1 PasMinLvl=1 EndLvl=1 : procedure a;
|
||||
CheckNode( 1, [], 0, 0, 0, 9, 1, 1, 1, 2, 3, 3, 4, [sfaOpen,sfaMarkup]);
|
||||
CheckNode( 1, [], 0, 0, 0, 9, 1, 1, 1, 2, 3, 3, 1, [sfaOpen,sfaMarkup]);
|
||||
//### Foldinfo Line: 2 PasMinLvl=1 EndLvl=1 : {$IFDEF A}
|
||||
CheckNode( 2, [], 0, 0, 2, 7, 0, 1, 0, 1, 18, 18, 3, [sfaOpen,sfaFold,sfaFoldFold]);
|
||||
//### Foldinfo Line: 3 PasMinLvl=1 EndLvl=2 : begin
|
||||
@ -1132,7 +1063,7 @@ begin
|
||||
CheckNode( 7, [], 0, 0, 2, 5, 3, 2, 4, 3, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]);
|
||||
//### Foldinfo Line: 8 PasMinLvl=1 EndLvl=1 : end;
|
||||
CheckNode( 8, [], 0, 0, 0, 3, 2, 1, 3, 2, 1, 0, 1, [sfaClose,sfaMarkup,sfaFold]);
|
||||
CheckNode( 8, [], 0, 1, 0, 3, 2, 2, 2, 1, 3, 3, 4, [sfaClose,sfaMarkup]);
|
||||
CheckNode( 8, [], 0, 1, 0, 3, 2, 2, 2, 1, 3, 3, 1, [sfaClose,sfaMarkup]);
|
||||
//### Foldinfo Line: 9 PasMinLvl=1 EndLvl=2 : begin
|
||||
CheckNode( 9, [], 0, 0, 0, 5, 1, 2, 1, 2, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]);
|
||||
//### Foldinfo Line: 10 PasMinLvl=0 EndLvl=0 : end.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user