SynEdit: Basic folding for LFM

git-svn-id: trunk@22552 -
This commit is contained in:
martin 2009-11-13 00:00:03 +00:00
parent 7b3bf8124d
commit ca94d30747
2 changed files with 142 additions and 6 deletions

View File

@ -6,7 +6,7 @@ interface
uses uses
SysUtils, Classes, Controls, Graphics, Menus, LCLIntf, SynGutterBase, SynEditMiscProcs, SysUtils, Classes, Controls, Graphics, Menus, LCLIntf, SynGutterBase, SynEditMiscProcs,
SynEditFoldedView, SynEditMouseCmds, LCLProc; SynEditFoldedView, SynEditMouseCmds, SynEditHighlighterFoldBase, LCLProc;
type type
@ -226,6 +226,8 @@ begin
SetLength(FMenuInf,c); SetLength(FMenuInf,c);
for i := c-1 downto 0 do begin for i := c-1 downto 0 do begin
inf := FFoldView.OpenFoldInfo(line-1, i); inf := FFoldView.OpenFoldInfo(line-1, i);
if sfaInvalid in inf.HNode.FoldAction then
continue;
FMenuInf[i] := inf; FMenuInf[i] := inf;
if (i < c-1) and (FMenuInf[i+1].LineNum = line) and (inf.LineNum <> line) if (i < c-1) and (FMenuInf[i+1].LineNum = line) and (inf.LineNum <> line)
then begin then begin

View File

@ -49,7 +49,7 @@ unit SynHighlighterLFM;
interface interface
uses uses
SysUtils, Classes, SysUtils, Classes, math,
{$IFDEF SYN_CLX} {$IFDEF SYN_CLX}
Qt, QControls, QGraphics, Qt, QControls, QGraphics,
{$ELSE} {$ELSE}
@ -60,7 +60,7 @@ uses
{$ENDIF} {$ENDIF}
Controls, Graphics, Controls, Graphics,
{$ENDIF} {$ENDIF}
SynEditTypes, SynEditHighlighter; SynEditTextBuffer, SynEditTypes, SynEditHighlighter, SynEditHighlighterFoldBase;
type type
TtkTokenKind = (tkComment, tkIdentifier, tkKey, tkNull, tkNumber, tkSpace, TtkTokenKind = (tkComment, tkIdentifier, tkKey, tkNull, tkNumber, tkSpace,
@ -68,10 +68,20 @@ type
TRangeState = (rsANil, rsComment, rsUnKnown); TRangeState = (rsANil, rsComment, rsUnKnown);
TLfmCodeFoldBlockType = (
cfbtLfmNone,
cfbtLfmObject, // object, inherited, inline
cfbtLfmList, // <>
cfbtLfmItem // Item
);
TProcTableProc = procedure of object; TProcTableProc = procedure of object;
type type
TSynLFMSyn = class(TSynCustomHighlighter)
{ TSynLFMSyn }
TSynLFMSyn = class(TSynCustomFoldHighlighter)
private private
fRange: TRangeState; fRange: TRangeState;
fLine: PChar; fLine: PChar;
@ -108,6 +118,14 @@ type
protected protected
function GetIdentChars: TSynIdentChars; override; function GetIdentChars: TSynIdentChars; override;
function GetSampleSource: string; override; function GetSampleSource: string; override;
protected
// folding
procedure CreateRootCodeFoldBlock; override;
function StartLfmCodeFoldBlock
(ABlockType: TLfmCodeFoldBlockType): TSynCustomCodeFoldBlock;
procedure EndLfmCodeFoldBlock;
function TopLfmCodeFoldBlockType(DownIndex: Integer = 0): TLfmCodeFoldBlockType;
public public
{$IFNDEF SYN_CPPB_1} class {$ENDIF} //mh 2000-07-14 {$IFNDEF SYN_CPPB_1} class {$ENDIF} //mh 2000-07-14
function GetLanguageName: string; override; function GetLanguageName: string; override;
@ -131,6 +149,15 @@ type
procedure SetRange(Value: Pointer); override; procedure SetRange(Value: Pointer); override;
procedure ResetRange; override; procedure ResetRange; override;
property IdentChars; 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;
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; override;
// TODO: make private
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
function EndFoldLevel(ALineIndex: Integer): integer; override;
published published
property CommentAttri: TSynHighlighterAttributes read fCommentAttri property CommentAttri: TSynHighlighterAttributes read fCommentAttri
write fCommentAttri; write fCommentAttri;
@ -279,6 +306,7 @@ end;
procedure TSynLFMSyn.SetLine({$IFDEF FPC}const {$ENDIF}NewValue: String; procedure TSynLFMSyn.SetLine({$IFDEF FPC}const {$ENDIF}NewValue: String;
LineNumber: Integer); LineNumber: Integer);
begin begin
inherited;
fLine := PChar(NewValue); fLine := PChar(NewValue);
Run := 0; Run := 0;
fLineNumber := LineNumber; fLineNumber := LineNumber;
@ -340,6 +368,8 @@ begin
(fLine[Run + 2] in ['d', 'D']) and (fLine[Run + 2] in ['d', 'D']) and
not (fLine[Run + 3] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']) not (fLine[Run + 3] in ['_', '0'..'9', 'a'..'z', 'A'..'Z'])
then begin then begin
if (TopLfmCodeFoldBlockType in [cfbtLfmObject, cfbtLfmItem]) then
EndLfmCodeFoldBlock;
fTokenID := tkKey; fTokenID := tkKey;
Inc(Run, 3); Inc(Run, 3);
end else end else
@ -387,6 +417,7 @@ begin
not (fLine[Run + 6] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']) not (fLine[Run + 6] in ['_', '0'..'9', 'a'..'z', 'A'..'Z'])
then then
begin begin
StartLfmCodeFoldBlock(cfbtLfmObject);
fTokenID := tkKey; fTokenID := tkKey;
Inc(Run, 6); Inc(Run, 6);
end end
@ -407,6 +438,7 @@ begin
not (fLine[Run + 9] in ['_', '0'..'9', 'a'..'z', 'A'..'Z'])) not (fLine[Run + 9] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']))
then then
begin begin
StartLfmCodeFoldBlock(cfbtLfmObject);
fTokenID := tkKey; fTokenID := tkKey;
Inc(Run, 9); Inc(Run, 9);
end end
@ -418,9 +450,20 @@ begin
not (fLine[Run + 6] in ['_', '0'..'9', 'a'..'z', 'A'..'Z'])) not (fLine[Run + 6] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']))
then then
begin begin
StartLfmCodeFoldBlock(cfbtLfmObject);
fTokenID := tkKey; fTokenID := tkKey;
Inc(Run, 6); Inc(Run, 6);
end end
else if ((fLine[Run + 1] in ['t', 'T']) and
(fLine[Run + 2] in ['e', 'E']) and
(fLine[Run + 3] in ['m', 'M']) and
not (fLine[Run + 4] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']))
then
begin
StartLfmCodeFoldBlock(cfbtLfmItem);
fTokenID := tkIdentifier;
Inc(Run, 4);
end
else else
AltProc; AltProc;
end; end;
@ -447,6 +490,11 @@ end;
procedure TSynLFMSyn.SymbolProc; procedure TSynLFMSyn.SymbolProc;
begin begin
if fLine[Run] = '<' then
StartLfmCodeFoldBlock(cfbtLfmList);
if (fLine[Run] = '>') and (TopLfmCodeFoldBlockType = cfbtLfmList) then
EndLfmCodeFoldBlock;
inc(Run); inc(Run);
fTokenID := tkSymbol; fTokenID := tkSymbol;
end; end;
@ -497,7 +545,8 @@ end;
function TSynLFMSyn.GetRange: Pointer; function TSynLFMSyn.GetRange: Pointer;
begin begin
Result := Pointer(PtrInt(fRange)); CodeFoldRange.RangeType:=Pointer(PtrUInt(Integer(fRange)));
Result := inherited;
end; end;
function TSynLFMSyn.GetTokenID: TtkTokenKind; function TSynLFMSyn.GetTokenID: TtkTokenKind;
@ -553,9 +602,73 @@ begin
fRange := rsUnknown; fRange := rsUnknown;
end; end;
function TSynLFMSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
begin
Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
end;
function TSynLFMSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
begin
Result := MinimumFoldLevel(ALineIndex) - EndFoldLevel(ALineIndex - 1);
end;
function TSynLFMSyn.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
Result := EndFoldLevel(ALineIndex);
end;
function TSynLFMSyn.FoldLineLength(ALineIndex, FoldIndex: Integer): integer;
var
i, lvl, cnt: Integer;
e, m: Integer;
begin
//atype := FoldTypeAtNodeIndex(ALineIndex, FoldIndex);
cnt := CurrentLines.Count;
e := EndFoldLevel(ALineIndex);
m := MinimumFoldLevel(ALineIndex);
lvl := Min(m+1+FoldIndex, e);
i := ALineIndex + 1;
while (i < cnt) and (MinimumFoldLevel(i) >= lvl) do inc(i);
// check if fold last line of block (not mixed "end begin")
// and not lastlinefix
if (i = cnt) or (EndFoldLevel(i) > MinimumFoldLevel(i)) then
dec(i);
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
Result := i - 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); procedure TSynLFMSyn.SetRange(Value: Pointer);
begin begin
fRange := TRangeState(PtrUInt(Value)); inherited;
fRange := TRangeState(Integer(PtrUInt(CodeFoldRange.RangeType)));
end; end;
function TSynLFMSyn.GetIdentChars: TSynIdentChars; function TSynLFMSyn.GetIdentChars: TSynIdentChars;
@ -579,6 +692,27 @@ begin
'end'; 'end';
end; { GetSampleSource } end; { GetSampleSource }
procedure TSynLFMSyn.CreateRootCodeFoldBlock;
begin
inherited CreateRootCodeFoldBlock;
RootCodeFoldBlock.InitRootBlockType(Pointer(PtrInt(cfbtLfmNone)));
end;
function TSynLFMSyn.StartLfmCodeFoldBlock(ABlockType: TLfmCodeFoldBlockType): TSynCustomCodeFoldBlock;
begin
StartCodeFoldBlock(Pointer(PtrInt(ABlockType)));
end;
procedure TSynLFMSyn.EndLfmCodeFoldBlock;
begin
EndCodeFoldBlock();
end;
function TSynLFMSyn.TopLfmCodeFoldBlockType(DownIndex: Integer): TLfmCodeFoldBlockType;
begin
Result := TLfmCodeFoldBlockType(PtrUInt(TopCodeFoldBlockType(DownIndex)));
end;
{$IFNDEF SYN_CPPB_1} //mh 2000-07-14 {$IFNDEF SYN_CPPB_1} //mh 2000-07-14
initialization initialization
RegisterPlaceableHighlighter(TSynLFMSyn); RegisterPlaceableHighlighter(TSynLFMSyn);