Created
December 19, 2020 00:32
-
-
Save KirillOsenkov/ea3bbb056bac464ec00d44942f0379f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Export a <see cref="IClassifierProvider"/> | |
/// </summary> | |
[Export(typeof(IClassifierProvider))] | |
[ContentType("code")] | |
internal class VideoCommentClassifierProvider : IClassifierProvider | |
{ | |
[Export(typeof(ClassificationTypeDefinition))] | |
[Name("video comment")] | |
internal ClassificationTypeDefinition VideoCommentClassificationType = null; | |
[Import] | |
internal IClassificationTypeRegistryService ClassificationRegistry = null; | |
[Import] | |
internal IBufferTagAggregatorFactoryService _tagAggregatorFactory = null; | |
public IClassifier GetClassifier(ITextBuffer buffer) | |
{ | |
IClassificationType classificationType = ClassificationRegistry.GetClassificationType("video comment"); | |
var tagAggregator = _tagAggregatorFactory.CreateTagAggregator<VideoCommentTag>(buffer); | |
return new VideoCommentClassifier(tagAggregator, classificationType); | |
} | |
} | |
/// <summary> | |
/// Set the display values for the classification | |
/// </summary> | |
[Export(typeof(EditorFormatDefinition))] | |
[ClassificationType(ClassificationTypeNames = "video comment")] | |
[Name("VideoComment")] | |
[UserVisible(true)] | |
[Order(After = Priority.High)] | |
internal sealed class VideoCommentFormat : ClassificationFormatDefinition | |
{ | |
public VideoCommentFormat() | |
{ | |
DisplayName = "Video Comment"; //human readable version of the name | |
var color = Color.FromArgb(255, 20, 140, 226); | |
ForegroundColor = color; | |
//ForegroundBrush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 255)); | |
TextDecorations = new System.Windows.TextDecorationCollection() { | |
System.Windows.TextDecorations.Underline, | |
}; | |
} | |
} | |
class VideoCommentClassifier : IClassifier | |
{ | |
private readonly IClassificationType _classificationType; | |
private readonly ITagAggregator<VideoCommentTag> _tagger; | |
internal VideoCommentClassifier(ITagAggregator<VideoCommentTag> tagger, IClassificationType videoCommentType) | |
{ | |
_tagger = tagger; | |
_classificationType = videoCommentType; | |
} | |
public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span) | |
{ | |
IList<ClassificationSpan> classifiedSpans = new List<ClassificationSpan>(); | |
var tags = _tagger.GetTags(span); | |
foreach (IMappingTagSpan<VideoCommentTag> tagSpan in tags) | |
{ | |
SnapshotSpan videoCommentSpan = tagSpan.Span.GetSpans(span.Snapshot).First(); | |
classifiedSpans.Add(new ClassificationSpan(videoCommentSpan, _classificationType)); | |
} | |
return classifiedSpans; | |
} | |
public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged | |
{ | |
add { } | |
remove { } | |
} | |
} | |
internal class VideoCommentTag : ITag | |
{ | |
} | |
/// <summary> | |
/// This class implements ITagger for VideoCommentTag. It is responsible for creating | |
/// VideoCommentTag TagSpans, which our GlyphFactory will then create glyphs for. | |
/// </summary> | |
internal class VideoCommentTagger : ITagger<VideoCommentTag> | |
{ | |
public static readonly Regex VideoCommentRegex = new Regex( | |
@"(//|#)video:(.*?)$", | |
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase | |
); | |
/// <summary> | |
/// This method creates VideoCommentTag TagSpans over a set of SnapshotSpans. | |
/// </summary> | |
/// <param name="spans">A set of spans we want to get tags for.</param> | |
/// <returns>The list of VideoCommentTag TagSpans.</returns> | |
IEnumerable<ITagSpan<VideoCommentTag>> ITagger<VideoCommentTag>.GetTags(NormalizedSnapshotSpanCollection spans) | |
{ | |
foreach (SnapshotSpan curSpan in spans) | |
{ | |
var text = curSpan.GetText(); | |
var matches = VideoCommentRegex.Matches(text); | |
foreach (Match match in matches) | |
{ | |
SnapshotSpan todoSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curSpan.Start.Position + match.Index, match.Length)); | |
yield return new TagSpan<VideoCommentTag>(todoSpan, new VideoCommentTag()); | |
} | |
} | |
} | |
public event EventHandler<SnapshotSpanEventArgs> TagsChanged | |
{ | |
add { } | |
remove { } | |
} | |
} | |
[Export(typeof(ITaggerProvider))] | |
[ContentType("code")] | |
[TagType(typeof(VideoCommentTag))] | |
class VideoCommentTaggerProvider : ITaggerProvider | |
{ | |
public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag | |
{ | |
if (buffer == null) | |
{ | |
throw new ArgumentNullException("buffer"); | |
} | |
return buffer.Properties.GetOrCreateSingletonProperty(() => new VideoCommentTagger()) as ITagger<T>; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment