2016-06-01 9 views
2

標準テンプレートを使用して、文字列「Archive ????? Key」のすべての文字列を反転させるカスタムのハイライターを作成しました(ここで、????は任意の変数名)ピンク。しかし、私が本当に好きなのは、 "Archive"と "Key"部分がピンクになり、 "????"部分は栗色になります。限り、私はVSIXのハイライターを理解する(と私は実際にはない)これは2つのClassificationFormatDefinitionを定義することを意味しますが、私はちょうどプロジェクトを中断しようとするたびに。私は別のスタイルを割り当てたい場所複数のClassificationTypesを割り当てるVSIX IClassifier

public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span) 
{ 
    List<ClassificationSpan> spans = new List<ClassificationSpan>(); 

    string text = span.GetText(); 
    int idx0 = 0; 
    int idx1; 

    while (true) 
    { 
    idx0 = text.IndexOf(keyPrefix, idx0); 
    if (idx0 < 0) 
     break; 

    idx1 = text.IndexOf(keySuffix, idx0 + 6); 
    if (idx1 < 0) 
     break; 

    // TODO: make sure the prefix and suffix are part of the same object identifier. 
    string name = text.Substring(idx0 + lengthPrefix, idx1 - idx0 - lengthPrefix); 
    string full = text.Substring(idx0, idx1 - idx0 + keySuffix.Length); 

    SnapshotSpan span0 = new SnapshotSpan(span.Start + idx0, idx1 - idx0 + lengthSuffix); 
    SnapshotSpan span1 = new SnapshotSpan(span.Start + idx0 + lengthPrefix, idx1 - idx0 - lengthPrefix); 
    SnapshotSpan span2 = new SnapshotSpan(span.Start + idx1, lengthSuffix); 

    spans.Add(new ClassificationSpan(span0, classificationType)); 
    spans.Add(new ClassificationSpan(span1, classificationType)); // I'd like to assign a different IClassificationType to this span. 
    spans.Add(new ClassificationSpan(span2, classificationType)); 
    idx0 = idx1 + 5; 
    } 
    return spans; 
} 

そしてspan1がある:よう

マイGetClassificationSpans方法(標準テンプレートからの唯一の重大な逸脱である)に見えます。私は、Classifier、Format、Provider、Definitionクラスがどのようにしてこの(!)ものを行うのに必要なのか、そしてどのクラスが複数のスタイルを認識できるのか理解していません。 。

答えて

6

テンプレートを使い始めるためにOKですが、通常、それはあなたがに行くしているものの方向を知っていれば、より直接的に、すべてを再実装する簡単です

は、ここですべてのピースを組み合わせる方法は次のとおりです。

  • クラシファイア(実際にはIClassificationTagタグ)は、必要に応じてテキストバッファの特定のセクションの分類タグスパンを生成します。
  • 分類タグスパンは、タグが適用されるバッファ内のスパンと分類タグ自体で構成されます。分類タグは、単に適用する分類タイプを指定します。
  • 分類タイプは、その分類のタグを所定のフォーマットに関連付けるために使用されます。
  • 形式(具体的にはClassificationFormatDefinition)は、MEF(EditorFormatDefinition)としてエクスポートされるため、VSはそれらを検出し、関連付けられた分類タイプを持つカラースパンに使用できます。それらは、オプションで、フォント&の色オプションにも表示されます。
  • クラシファイアプロバイダは、VSがそれを検出するためにMEF経由でエクスポートされます。 VSは、開いているバッファごとに分類子をインスタンス化する手段を提供します(したがって、その中のタグを検出します)。

これは、それぞれ2つの分類タイプに関連付けられた2つの分類フォーマット定義を定義してエクスポートするコードです。それで、分類器は両方の型のタグをそれに応じて生成する必要があります。ここでの例では、(未テスト)です:

public static class Classifications 
{ 
    // These are the strings that will be used to form the classification types 
    // and bind those types to formats 
    public const string ArchiveKey = "MyProject/ArchiveKey"; 
    public const string ArchiveKeyVar = "MyProject/ArchiveKeyVar"; 

    // These MEF exports define the types themselves 
    [Export] 
    [Name(ArchiveKey)] 
    private static ClassificationTypeDefinition ArchiveKeyType = null; 

    [Export] 
    [Name(ArchiveKeyVar)] 
    private static ClassificationTypeDefinition ArchiveKeyVarType = null; 

    // These are the format definitions that specify how things will look 
    [Export(typeof(EditorFormatDefinition))] 
    [ClassificationType(ClassificationTypeNames = ArchiveKey)] 
    [UserVisible(true)] // Controls whether it appears in Fonts & Colors options for user configuration 
    [Name(ArchiveKey)] // This could be anything but I like to reuse the classification type name 
    [Order(After = Priority.Default, Before = Priority.High)] // Optionally include this attribute if your classification should 
                   // take precedence over some of the builtin ones like keywords 
    public sealed class ArchiveKeyFormatDefinition : ClassificationFormatDefinition 
    { 
     public ArchiveKeyFormatDefinition() 
     { 
      ForegroundColor = Color.FromRgb(0xFF, 0x69, 0xB4); // pink! 
      DisplayName = "This will display in Fonts & Colors"; 
     } 
    } 

    [Export(typeof(EditorFormatDefinition))] 
    [ClassificationType(ClassificationTypeNames = ArchiveKeyVar)] 
    [UserVisible(true)] 
    [Name(ArchiveKeyVar)] 
    [Order(After = Priority.Default, Before = Priority.High)] 
    public sealed class ArchiveKeyVarFormatDefinition : ClassificationFormatDefinition 
    { 
     public ArchiveKeyVarFormatDefinition() 
     { 
      ForegroundColor = Color.FromRgb(0xB0, 0x30, 0x60); // maroon 
      DisplayName = "This too will display in Fonts & Colors"; 
     } 
    } 
} 

プロバイダ:

[Export(typeof(ITaggerProvider))] 
[ContentType("text")] // or whatever content type your tagger applies to 
[TagType(typeof(ClassificationTag))] 
public class ArchiveKeyClassifierProvider : ITaggerProvider 
{ 
    [Import] 
    public IClassificationTypeRegistryService ClassificationTypeRegistry { get; set; } 

    public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag 
    { 
     return buffer.Properties.GetOrCreateSingletonProperty(() => 
      new ArchiveKeyClassifier(buffer, ClassificationTypeRegistry)) as ITagger<T>; 
    } 
} 

は最後に、鬼自体:

public class ArchiveKeyClassifier : ITagger<ClassificationTag> 
{ 
    public event EventHandler<SnapshotSpanEventArgs> TagsChanged; 

    private Dictionary<string, ClassificationTag> _tags; 

    public ArchiveKeyClassifier(ITextBuffer subjectBuffer, IClassificationTypeRegistryService classificationRegistry) 
    { 
     // Build the tags that correspond to each of the possible classifications 
     _tags = new Dictionary<string, ClassificationTag> { 
      { Classifications.ArchiveKey, BuildTag(classificationRegistry, Classifications.ArchiveKey) }, 
      { Classifications.ArchiveKeyVar, BuildTag(classificationRegistry, Classifications.ArchiveKeyVar) } 
     }; 
    } 

    public IEnumerable<ITagSpan<ClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans) 
    { 
     if (spans.Count == 0) 
      yield break; 

     foreach (var span in spans) { 
      if (span.IsEmpty) 
       continue; 

      foreach (var identSpan in LexIdentifiers(span)) { 
       var ident = identSpan.GetText(); 
       if (!ident.StartsWith("Archive") || !ident.EndsWith("Key")) 
        continue; 

       var varSpan = new SnapshotSpan(
        identSpan.Start + "Archive".Length, 
        identSpan.End - "Key".Length); 

       yield return new TagSpan<ClassificationTag>(new SnapshotSpan(identSpan.Start, varSpan.Start), _tags[Classifications.ArchiveKey]); 
       yield return new TagSpan<ClassificationTag>(varSpan, _tags[Classifications.ArchiveKeyVar]); 
       yield return new TagSpan<ClassificationTag>(new SnapshotSpan(varSpan.End, identSpan.End), _tags[Classifications.ArchiveKey]); 
      } 
     } 
    } 

    private static IEnumerable<SnapshotSpan> LexIdentifiers(SnapshotSpan span) 
    { 
     // Tokenize the string into identifiers and numbers, returning only the identifiers 
     var s = span.GetText(); 
     for (int i = 0; i < s.Length;) { 
      if (char.IsLetter(s[i])) { 
       var start = i; 
       for (++i; i < s.Length && IsTokenChar(s[i]); ++i); 
       yield return new SnapshotSpan(span.Start + start, i - start); 
       continue; 
      } 
      if (char.IsDigit(s[i])) { 
       for (++i; i < s.Length && IsTokenChar(s[i]); ++i); 
       continue; 
      } 
      ++i; 
     } 
    } 

    private static bool IsTokenChar(char c) 
    { 
     return char.IsLetterOrDigit(c) || c == '_'; 
    } 

    private static ClassificationTag BuildTag(IClassificationTypeRegistryService classificationRegistry, string typeName) 
    { 
     return new ClassificationTag(classificationRegistry.GetClassificationType(typeName)); 
    } 
} 

もう一つ注意:スタートアップを加速するために、VSはA続けますMEFエクスポートのキャッシュ。ただし、このキャッシュは、必要なときに無効化されないことがよくあります。さらに、既存の分類フォーマット定義のデフォルトの色を変更した場合、VSは以前の値をレジストリに保存するため、変更が取得されない可能性があります。これを軽減するには、MEFや書式関連の変更があった場合に、コンパイル時にバッチスクリプトを実行してオブジェクトをクリアするのが最善です。ここでVS2013と(VSIXesをテストする際にデフォルトで使用)経験ルートサフィックスのための例です。同じ[名前(ArchiveKey)]は、これは素晴らしい作品属性を使用して、両方のClassificationFormatDefinitionタイプから離れて

@echo off 

del "%LOCALAPPDATA%\Microsoft\VisualStudio\12.0Exp\ComponentModelCache\Microsoft.VisualStudio.Default.cache" 2> nul 
rmdir /S /Q "%LOCALAPPDATA%\Microsoft\VisualStudio\12.0Exp\ComponentModelCache" 2> nul 

reg delete HKCU\Software\Microsoft\VisualStudio\12.0Exp\FontAndColors\Cache\{75A05685-00A8-4DED-BAE5-E7A50BFA929A} /f 
+0

。私は間違いなくこの上に構築することができます。 –

+0

おっと、良いキャッチ。編集。あなたがそれが役に立つとうれしい! – Cameron

+0

@Cameron:VSはレジストリに以前の値が保存されているため、変更が反映されない可能性があります。これを軽減するには、コンパイル時にバッチスクリプトを実行することをお勧めします。物事をクリアするためのフォーマット関連の変更が含まれています。これらのキャッシュされた値を拡張機能から無効にする方法を知っていますか? – HJLebbink

関連する問題