Skip to content

Commit

Permalink
Merge branch 'folding-poc'. Todo: add GUI option.
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnlaan committed Jun 17, 2024
2 parents 359ac3f + 98349cd commit b3ea910
Show file tree
Hide file tree
Showing 6 changed files with 752 additions and 90 deletions.
44 changes: 44 additions & 0 deletions Components/ScintEdit.pas
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ TScintEdit = class(TWinControl)
procedure DeleteMarker(const Line: Integer; const Marker: TScintMarkerNumber);
procedure DPIChanged(const Message: TMessage);
procedure EndUndoAction;
procedure EnsureLineVisible(const Line: Integer);
function FindRawText(const StartPos, EndPos: Integer; const S: TScintRawString;
const Options: TScintFindOptions; out MatchRange: TScintRange): Boolean;
function FindText(const StartPos, EndPos: Integer; const S: String;
Expand Down Expand Up @@ -272,6 +273,7 @@ TScintEdit = class(TWinControl)
procedure ScrollCaretIntoView;
procedure SelectAll;
procedure SelectAllOccurrences(const Options: TScintFindOptions);
procedure SelectAndEnsureVisible(const Range: TScintRange);
procedure SelectNextOccurrence(const Options: TScintFindOptions);
function SelEmpty: Boolean;
function SelNotEmpty(out Sel: TScintRange): Boolean;
Expand Down Expand Up @@ -441,6 +443,8 @@ TScintCustomStyler = class(TComponent)
function ConsumeString(const Chars: TScintRawCharSet): TScintRawString;
function CurCharIn(const Chars: TScintRawCharSet): Boolean;
function CurCharIs(const C: AnsiChar): Boolean;
procedure GetFoldLevel(const LineState: TScintLineState; var Level: Integer;
var Header: Boolean); virtual; abstract;
procedure GetStyleAttributes(const Style: Integer;
var Attributes: TScintStyleAttributes); virtual; abstract;
function LineTextSpans(const S: TScintRawString): Boolean; virtual;
Expand Down Expand Up @@ -754,6 +758,12 @@ procedure TScintEdit.EndUndoAction;
Call(SCI_ENDUNDOACTION, 0, 0);
end;

procedure TScintEdit.EnsureLineVisible(const Line: Integer);
begin
FLines.CheckIndexRange(Line);
Call(SCI_ENSUREVISIBLE, Line, 0);
end;

class function TScintEdit.GetErrorException(const S: String): EScintEditError;
begin
Result := EScintEditError.Create('TScintEdit error: ' + S);
Expand Down Expand Up @@ -1307,13 +1317,31 @@ procedure TScintEdit.ScrollCaretIntoView;


procedure TScintEdit.SelectAllOccurrences(const Options: TScintFindOptions);
{ At the moment this does not automatically expand folds, unlike VSCode. Also
see SelectNextOccurrence. }
begin
Call(SCI_TARGETWHOLEDOCUMENT, 0, 0);
Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
Call(SCI_MULTIPLESELECTADDEACH, 0, 0);
end;

procedure TScintEdit.SelectAndEnsureVisible(const Range: TScintRange);
begin
CheckPosRange(Range.StartPos, Range.EndPos);

{ If the range is in a contracted section, expand it }
var StartLine := GetLineFromPosition(Range.StartPos);
var EndLine := GetLineFromPosition(Range.EndPos);
for var Line := StartLine to EndLine do
EnsureLineVisible(Line);

{ Select }
Selection := Range;
end;

procedure TScintEdit.SelectNextOccurrence(const Options: TScintFindOptions);
{ At the moment this does not automatically expand folds, unlike VSCode. Also
see SelectAllOccurrences. }
begin
Call(SCI_TARGETWHOLEDOCUMENT, 0, 0);
Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
Expand Down Expand Up @@ -1793,10 +1821,26 @@ procedure TScintEdit.StyleNeeded(const EndPos: Integer);
FStyler.FText := '';
end;

var FoldLevel: Integer;
var FoldHeader: Boolean;
FStyler.GetFoldLevel(FStyler.FLineState, FoldLevel, FoldHeader);
Inc(FoldLevel, SC_FOLDLEVELBASE);
if FoldHeader then
FoldLevel := FoldLevel or SC_FOLDLEVELHEADERFLAG;
{ Setting SC_FOLDLEVELWHITEFLAG on empty lines causes a problem: when
Scintilla auto expands a contracted section (for example after removing ']'
from a section header) all the empty lines stay invisible, even any which
are in the middle of the section. }

for var I := FirstLine to LastLine do begin
var OldState := FLines.GetState(I);
if FStyler.FLineState <> OldState then
Call(SCI_SETLINESTATE, I, FStyler.FLineState);
{ To display/debug fold levels use: Call(SCI_SETFOLDFLAGS, SC_FOLDFLAG_LEVELNUMBERS, 0);
And then also update UpdateLineNumbersWidth to make the margin wider. }
var OldLevel := Call(SCI_GETFOLDLEVEL, I, 0);
if FoldLevel <> OldLevel then
Call(SCI_SETFOLDLEVEL, I, FoldLevel);
end;

Result := LastLine;
Expand Down
33 changes: 32 additions & 1 deletion Components/ScintStylerInnoSetup.pas
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ interface

type
TInnoSetupStylerSection = (
scNone, { Not inside a section (start of file, or last section was closed) }
scNone, { Not inside a section (start of file, or previous section was closed )
Section tags themselves are not associated with any section! }
scUnknown, { Inside an unrecognized section }
scThirdParty, { Inside a '_' section (reserved for third-party tools) }
scCode,
Expand Down Expand Up @@ -104,6 +105,8 @@ TInnoSetupStyler = class(TScintCustomStyler)
procedure SetISPPInstalled(const Value: Boolean);
protected
procedure CommitStyle(const Style: TInnoSetupStylerStyle);
procedure GetFoldLevel(const LineState: TScintLineState; var Level: Integer;
var Header: Boolean); override;
procedure GetStyleAttributes(const Style: Integer;
var Attributes: TScintStyleAttributes); override;
function LineTextSpans(const S: TScintRawString): Boolean; override;
Expand Down Expand Up @@ -934,6 +937,34 @@ function TInnoSetupStyler.GetFlagsWordList(Section: TInnoSetupStylerSection): An
Result := FFlagsWordList[Section];
end;

procedure TInnoSetupStyler.GetFoldLevel(const LineState: TScintLineState;
var Level: Integer; var Header: Boolean);
begin
{ Set folding per section. To keep our code as simple as possible we simply
give all lines outside of a section (=lines at the start of the document and
section tags and section end tags and lines after section end tags) a header
flag. This avoids having to look at the previous line. Doesn't mean
Scintilla will display folding markers on all these header lines: it only
does that when there is something to fold, so when the header line is
followed a by non-header line which is only the case for a section tag line
followed by a section line.
Did notice an issue (Scintilla automatic folding bug?): Add a section with
some lines. Contract it. Break the section header for example by removing ']'.
Scintialla now auto expands the section and removes the fold mark.
Retype the ']'. Scintilla now displays the old fold mark to expand the
section but it's already expanded. }

var Section := TInnoSetupStyler.GetSectionFromLineState(LineState);
if Section <> scNone then begin
Level := 1;
Header := False;
end else begin
Level := 0;
Header := True;
end;
end;

function TInnoSetupStyler.GetKeywordsWordList(Section: TInnoSetupStylerSection): AnsiString;
begin
Result := FKeywordsWordList[Section];
Expand Down
Loading

0 comments on commit b3ea910

Please sign in to comment.