Some improvements to folding.

This commit is contained in:
Robert Di Pardo 2021-04-16 21:50:48 +10:00 committed by Neil Hodgson
parent ca54871b17
commit 22e19499b9
2 changed files with 85 additions and 46 deletions

View File

@ -546,6 +546,7 @@ void SCI_METHOD LexerFSharp::Lex(Sci_PositionU start, Sci_Position length, int i
}
bool LineContains(LexAccessor &styler, const char *word, const Sci_Position start, const Sci_Position end = 1);
bool MatchPPDirectiveBranch(LexAccessor &styler, const Sci_Position line);
void SCI_METHOD LexerFSharp::Fold(Sci_PositionU start, Sci_Position length, int initStyle, IDocument *pAccess) {
if (!options.fold) {
@ -584,17 +585,29 @@ void SCI_METHOD LexerFSharp::Fold(Sci_PositionU start, Sci_Position length, int
chNext = styler.SafeGetCharAt(currentPos + 1);
if (options.foldComment) {
if (options.foldCommentMultiLine && style == SCE_FSHARP_COMMENTLINE &&
stylePrev != SCE_FSHARP_COMMENTLINE) {
if (options.foldCommentMultiLine && inLineComment &&
(lineCurrent > 0 || styler.StyleAt(lineStartNext) == SCE_FSHARP_COMMENTLINE)) {
const bool haveCommentList = LineContains(styler, "//", lineStartNext, lineNext);
if (haveCommentList) {
commentLinesInFold++;
if (commentLinesInFold < 1) {
// begin fold region
if (commentLinesInFold == ZERO_LENGTH) {
levelNext++;
}
// start line count at 0
commentLinesInFold++;
} else {
const int8_t offset = commentLinesInFold > 0 ? commentLinesInFold : 1;
levelNext -= offset;
Sci_Position lineFold = lineCurrent;
while (lineFold > 0) {
commentLinesInFold--;
lineFold--;
if (!LineContains(styler, "//", lineFold)) {
break;
}
}
// line count should be reduced to 0, and no less
if (commentLinesInFold > ZERO_LENGTH) {
levelNext--;
}
commentLinesInFold = ZERO_LENGTH;
}
}
@ -613,19 +626,37 @@ void SCI_METHOD LexerFSharp::Fold(Sci_PositionU start, Sci_Position length, int
levelNext++;
} else if (styler.Match(currentPos, "#endif")) {
levelNext--;
// compensate for #else branches and import lists
Sci_Position lineFold = lineCurrent;
while (lineFold > 0) {
lineFold--;
if (MatchPPDirectiveBranch(styler, lineFold)) {
levelNext--;
break;
}
}
}
}
if (options.foldImports && style == SCE_FSHARP_KEYWORD && LineContains(styler, "open", lineCurrent)) {
const bool haveImportList = LineContains(styler, "open", lineStartNext, lineNext);
if (haveImportList) {
importsInFold++;
if (importsInFold < 1) {
if (importsInFold == ZERO_LENGTH) {
levelNext++;
}
importsInFold++;
} else {
const int8_t offset = importsInFold > 0 ? importsInFold : 1;
levelNext -= offset;
Sci_Position lineFold = lineCurrent;
while (lineFold > 0) {
importsInFold--;
lineFold--;
if (!LineContains(styler, "open", lineFold)) {
break;
}
}
if (importsInFold > ZERO_LENGTH) {
levelNext--;
}
importsInFold = ZERO_LENGTH;
}
}
@ -672,6 +703,14 @@ bool LineContains(LexAccessor &styler, const char *word, const Sci_Position star
}
return found;
}
bool MatchPPDirectiveBranch(LexAccessor &styler, const Sci_Position line) {
const Sci_Position linePrev = line - 1;
const Sci_Position lineStart = styler.LineStart(line);
const Sci_Position lineStartPrev = styler.LineStart(linePrev);
return (styler.StyleAt(lineStart) == SCE_FSHARP_PREPROCESSOR && !styler.Match(lineStart, "#if")) ||
(LineContains(styler, "open", lineStartPrev, linePrev) && LineContains(styler, "open", lineStart, line));
}
} // namespace
LexerModule lmFSharp(SCLEX_FSHARP, LexerFSharp::LexerFactoryFSharp, lexerName, fsharpWordLists);

View File

@ -8,39 +8,39 @@
2 400 401 + #if DEBUG
2 401 402 + open System
0 402 402 | open System.IO
0 402 3f8 | open System.Diagnostics
0 3f8 3f7 #endif
1 3f7 3f7
0 3f7 3f7 # 14 @"See: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/strings#remarks"
0 3f7 3f6 // verbatim string
0 3f6 3f3 let xmlFragment1 = @"<book author=""Milton, John"" title=""Paradise Lost"">"
1 3f3 3f3
0 3f3 3f2 // triple-quoted string
0 3f2 3ef let xmlFragment2 = """<book author="Milton, John" title="Paradise Lost">"""
1 3ef 3ef
2 3ef 3f0 + (* you need .NET 5.0 to compile this:
0 3f0 3f0 https://docs.microsoft.com/en-us/dotnet/fsharp/whats-new/fsharp-50#string-interpolation
0 3f0 3ef *)
0 3ef 3ec let interpolated = $"I think {3.0 + 0.14} is close to {System.Math.PI}!"
1 3ec 3ec
0 3ec 3e9 let ``a byte literal`` = '\209'B
1 3e9 3e9
0 3e9 3e8 // quoted expression
0 3e8 3e5 let expr =
0 3e5 3e5 <@@
0 3e5 3e5 let foo () = "bar"
0 3e5 3e5 foo ()
0 3e5 3e5 @@>
1 3e5 3e5
0 3e5 3e2 let bigNum (unused: 'a): float option =
0 3e2 3df Seq.init 10_000 (float >> (fun i -> i + 11.))
0 3df 3df |> (List.ofSeq
0 3df 3df >> List.take 5
0 3df 3df >> List.fold (*) 1.0)
0 3df 3df |> Some
1 3df 3df
0 3df 3d4 match bigNum () with
0 3d4 3d4 | Some num -> sprintf "%.2f > %u" num ``a byte literal``
0 3d4 3d4 | None -> sprintf "%A" "Have a byte string!"B
0 3d4 3d4 |> printfn "%s"
1 3d4 3d4
0 402 401 | open System.Diagnostics
0 401 3ff | #endif
1 3ff 3ff
0 3ff 3ff # 14 @"See: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/strings#remarks"
0 3ff 3ff // verbatim string
0 3ff 3ff let xmlFragment1 = @"<book author=""Milton, John"" title=""Paradise Lost"">"
1 3ff 3ff
0 3ff 3ff // triple-quoted string
0 3ff 3ff let xmlFragment2 = """<book author="Milton, John" title="Paradise Lost">"""
1 3ff 3ff
2 3ff 400 + (* you need .NET 5.0 to compile this:
0 400 400 https://docs.microsoft.com/en-us/dotnet/fsharp/whats-new/fsharp-50#string-interpolation
0 400 3ff *)
0 3ff 3ff let interpolated = $"I think {3.0 + 0.14} is close to {System.Math.PI}!"
1 3ff 3ff
0 3ff 3ff let ``a byte literal`` = '\209'B
1 3ff 3ff
0 3ff 3ff // quoted expression
0 3ff 3ff let expr =
0 3ff 3ff <@@
0 3ff 3ff let foo () = "bar"
0 3ff 3ff foo ()
0 3ff 3ff @@>
1 3ff 3ff
0 3ff 3ff let bigNum (unused: 'a): float option =
0 3ff 3ff Seq.init 10_000 (float >> (fun i -> i + 11.))
0 3ff 3ff |> (List.ofSeq
0 3ff 3ff >> List.take 5
0 3ff 3ff >> List.fold (*) 1.0)
0 3ff 3ff |> Some
1 3ff 3ff
0 3ff 3ff match bigNum () with
0 3ff 3ff | Some num -> sprintf "%.2f > %u" num ``a byte literal``
0 3ff 3ff | None -> sprintf "%A" "Have a byte string!"B
0 3ff 3ff |> printfn "%s"
1 3ff 3ff