diff --git a/CSharpRepl.Services/CSharpRepl.Services.csproj b/CSharpRepl.Services/CSharpRepl.Services.csproj index b2b7594c..8bbcff13 100644 --- a/CSharpRepl.Services/CSharpRepl.Services.csproj +++ b/CSharpRepl.Services/CSharpRepl.Services.csproj @@ -38,9 +38,9 @@ --> - + - + diff --git a/CSharpRepl.Services/SyntaxHighlighting/HighlightedSpan.cs b/CSharpRepl.Services/SyntaxHighlighting/HighlightedSpan.cs index d1f7ad12..e5688e89 100644 --- a/CSharpRepl.Services/SyntaxHighlighting/HighlightedSpan.cs +++ b/CSharpRepl.Services/SyntaxHighlighting/HighlightedSpan.cs @@ -1,71 +1,71 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis.Text; -using PrettyPrompt.Highlighting; - -namespace CSharpRepl.Services.SyntaxHighlighting; - -public sealed record HighlightedSpan(TextSpan TextSpan, AnsiColor Color); - -public static class HighlightedSpanExtensions -{ - public static IReadOnlyCollection ToFormatSpans(this IReadOnlyCollection spans) => spans - .Select(span => new FormatSpan( - span.TextSpan.Start, - span.TextSpan.Length, - new ConsoleFormat(Foreground: span.Color) - )) - .ToArray(); - - /// - /// Converts possibly-overlapping format spans into the disjoint spans requires. - /// Roslyn's classifier nests spans (e.g. a string-escape-character span inside a string-literal span). The - /// later-starting span is the more specific classification, so it wins; the span it interrupts resumes after - /// it ends. The prompt's own renderer tolerates overlap, so this is only needed when building a FormattedString. - /// - public static IReadOnlyList FlattenOverlappingSpans(this IEnumerable spans) - { - // at equal starts, the longer (enclosing) span sorts first so the shorter, more specific span is - // pushed later and takes precedence over it. - var sorted = spans.OrderBy(s => s.Start).ThenByDescending(s => s.Length).ToArray(); - var result = new List(sorted.Length); - var enclosing = new Stack(); - int position = 0; - - foreach (var span in sorted) - { - // emit the tails of spans that end before this one starts - while (enclosing.TryPeek(out var top) && top.End <= span.Start) - { - Emit(top, top.End); - enclosing.Pop(); - } - // emit the segment of the still-open span leading up to this more specific span - if (enclosing.TryPeek(out var current)) - { - Emit(current, span.Start); - } - enclosing.Push(span); - } - while (enclosing.TryPop(out var top)) - { - Emit(top, top.End); - } - return result; - - void Emit(FormatSpan span, int end) - { - int start = Math.Max(position, span.Start); - if (end > start) - { - result.Add(new FormatSpan(start, end - start, span.Formatting)); - position = end; - } - } - } +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis.Text; +using PrettyPrompt.Highlighting; + +namespace CSharpRepl.Services.SyntaxHighlighting; + +public sealed record HighlightedSpan(TextSpan TextSpan, AnsiColor Color); + +public static class HighlightedSpanExtensions +{ + public static IReadOnlyCollection ToFormatSpans(this IReadOnlyCollection spans) => spans + .Select(span => new FormatSpan( + span.TextSpan.Start, + span.TextSpan.Length, + new ConsoleFormat(Foreground: span.Color) + )) + .ToArray(); + + /// + /// Converts possibly-overlapping format spans into the disjoint spans requires. + /// Roslyn's classifier nests spans (e.g. a string-escape-character span inside a string-literal span). The + /// later-starting span is the more specific classification, so it wins; the span it interrupts resumes after + /// it ends. The prompt's own renderer tolerates overlap, so this is only needed when building a FormattedString. + /// + public static IReadOnlyList FlattenOverlappingSpans(this IEnumerable spans) + { + // at equal starts, the longer (enclosing) span sorts first so the shorter, more specific span is + // pushed later and takes precedence over it. + var sorted = spans.OrderBy(s => s.Start).ThenByDescending(s => s.Length).ToArray(); + var result = new List(sorted.Length); + var enclosing = new Stack(); + int position = 0; + + foreach (var span in sorted) + { + // emit the tails of spans that end before this one starts + while (enclosing.TryPeek(out var top) && top.End <= span.Start) + { + Emit(top, top.End); + enclosing.Pop(); + } + // emit the segment of the still-open span leading up to this more specific span + if (enclosing.TryPeek(out var current)) + { + Emit(current, span.Start); + } + enclosing.Push(span); + } + while (enclosing.TryPop(out var top)) + { + Emit(top, top.End); + } + return result; + + void Emit(FormatSpan span, int end) + { + int start = Math.Max(position, span.Start); + if (end > start) + { + result.Add(new FormatSpan(start, end - start, span.Formatting)); + position = end; + } + } + } } \ No newline at end of file diff --git a/CSharpRepl/CSharpRepl.csproj b/CSharpRepl/CSharpRepl.csproj index fc0611ec..230dabe8 100644 --- a/CSharpRepl/CSharpRepl.csproj +++ b/CSharpRepl/CSharpRepl.csproj @@ -25,8 +25,8 @@ - - + +