Skip to content

Instantly share code, notes, and snippets.

@KirillOsenkov
Created December 19, 2020 00:32
Show Gist options
  • Save KirillOsenkov/ea3bbb056bac464ec00d44942f0379f9 to your computer and use it in GitHub Desktop.
Save KirillOsenkov/ea3bbb056bac464ec00d44942f0379f9 to your computer and use it in GitHub Desktop.
/// <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