SixPairs

March 31, 2012

Highlight Classifier for Visual Studio Editor

Filed under: VS Editor — Tags: — Ceyhun Ciper @ 23:48

Sometimes you just want to see the data in a C# file:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.Utilities;
 
namespace Microsoft.VisualStudio.Text.Classification
{
	public static class Definitions
	{
		[Export(typeof(ClassificationTypeDefinition))]
		[Name("hilite-data")]
		internal static ClassificationTypeDefinition CTD;
 
		[Export(typeof(EditorFormatDefinition))]
		[ClassificationType(ClassificationTypeNames = "hilite-data")]
		[Name("hilite-data")]
		[DisplayName("Highlight Data")]
		[UserVisible(true)]
		[Order(Before = Priority.High)]
		internal sealed class CFD : ClassificationFormatDefinition
		{
			public CFD()
			{
				this.ForegroundColor = System.Windows.Media.Colors.LightGray;
			}
		}
 
		public static bool IsToBeHilited(this string classification)
		{
			var hilites = new[] { "string", "comment" };
			return hilites.Contains(classification.ToLower());
		}
	}
 
	[Export(typeof(IClassifierProvider))]
	[ContentType("CSharp")]
	internal sealed class HiliteDataClassifierProvider : IClassifierProvider
	{
		[Import]
		IClassificationTypeRegistryService ctrs = null;
		[Import]
		internal IClassifierAggregatorService AggregatorService = null;
 
		internal static bool ignoreRequest = false;
 
		public IClassifier GetClassifier(ITextBuffer textBuffer)
		{
			if (ignoreRequest)
				return null;
 
			try
			{
				ignoreRequest = true;
				return textBuffer.Properties.GetOrCreateSingletonProperty(
					() => new HiliteDataClassifier(AggregatorService.GetClassifier(textBuffer), ctrs));
			}
			finally
			{
				ignoreRequest = false;
			}
		}
	}
 
	internal sealed class HiliteDataClassifier : IClassifier
	{
		private IClassifier aggregator;
		private IClassificationTypeRegistryService ctrs;
 
		public HiliteDataClassifier(IClassifier aggregator, IClassificationTypeRegistryService ctrs)
		{
			this.aggregator = aggregator;
			this.ctrs = ctrs;
		}
 
		public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
		{
			var classifiedSpans =
				from cs in aggregator.GetClassificationSpans(span)
				let c = cs.ClassificationType.Classification
				where c.IsToBeHilited()
				select cs.Span;
 
			NormalizedSnapshotSpanCollection ignored = new NormalizedSnapshotSpanCollection(classifiedSpans);
			NormalizedSnapshotSpanCollection request = new NormalizedSnapshotSpanCollection(span);
 
			var spansToIgnore = NormalizedSnapshotSpanCollection.Difference(request, ignored);
 
			IClassificationType ct = ctrs.GetClassificationType("hilite-data");
 
			return spansToIgnore.Select(s => new ClassificationSpan(s, ct)).ToList();
		}
 
		public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
	}
}

 

This is for my own consumption (being a blog and what not); use it at your own peril.

Simple Colorizer for Visual Studio Editor

Filed under: VS Editor — Tags: — Ceyhun Ciper @ 16:48

Here is probably the simplest colorizer code:

namespace Ciper
{
	[Export(typeof(IClassifierProvider)), ContentType("text")]
	internal class CProvider : IClassifierProvider
	{
		[Import]
		IClassificationTypeRegistryService ctrs = null;
 
		[Export, Name("ciper.text"), BaseDefinition("text")]
		internal static ClassificationTypeDefinition CTD;
 
		[Export(typeof(EditorFormatDefinition)), Name("ciper.text.format"), ClassificationType(ClassificationTypeNames = "ciper.text")]
		internal class CFD : ClassificationFormatDefinition
		{
			public CFD()
			{
				ForegroundColor = System.Windows.Media.Colors.DarkMagenta;
			}
		}
 
		public IClassifier GetClassifier(ITextBuffer buffer)
		{
			return new C(ctrs.GetClassificationType("ciper.text"));
		}
	}
 
	class C : IClassifier
	{
		IClassificationType ct;
		public C(IClassificationType ct)
		{
			this.ct = ct;
		}
		public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
		{
			return new[] { new ClassificationSpan(span, ct) };
		}
 
		public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
	}
}

 

This will paint everything that is not yet classified in magenta.

March 26, 2012

Simplest VS Editor Classifier

Filed under: VS Editor — Tags: — Ceyhun Ciper @ 20:59

Burada sadece daha once belirlenmis olan ClassificationType’larini kullaniyorum.

Here is a minimal VS Editor classifier that doesn’t do anything (not even classify):

namespace Ciper
{
  using EnvDTE;
  using EnvDTE80;
  using Microsoft.VisualStudio.Language.StandardClassification;
  using Microsoft.VisualStudio.Shell;
  using Microsoft.VisualStudio.Text;
  using Microsoft.VisualStudio.Text.Classification;
  using System;
  using System.ComponentModel.Composition;
 
  [Export(typeof(IClassifierProvider))]
  partial class DummyClassifier : IClassifierProviderIClassifier
  {
    [Import]
    IClassificationTypeRegistryService classificationTypeRegistry = null;
 
    [Import]
    IStandardClassificationService standardClassifications = null;
 
    [Import]
    SVsServiceProvider serviceProvider = null;
 
    DTE2 dte { get { return (DTE2)serviceProvider.GetService(typeof(DTE)); } }
    OutputWindowPane outputWindowPane { get { return dte.ToolWindows.OutputWindow.ActivePane; } }
 
    public IClassifier GetClassifier(ITextBuffer textBuffer)
    {
      return this;
    }
 
    public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
  }
}
 
namespace Ciper
{
  using Microsoft.VisualStudio.Text;
  using Microsoft.VisualStudio.Text.Classification;
  using Microsoft.VisualStudio.Utilities;
  using System.Collections.Generic;
 
  [ContentType("csharp")]
  partial class DummyClassifier
  {
    public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
    {
      return new List<ClassificationSpan>();
    }
  }
}

Go figure why you might find it useful…

Exercises

  1. Tum span’lerin background’unu yellow yap
    namespace Ciper
    {
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System.Collections.Generic;
     
      [ContentType("text")]
      partial class DummyClassifier
      {
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          var l = new List<ClassificationSpan>();
          l.Add(new ClassificationSpan(span, classificationTypeRegistry.GetClassificationType("html server-side script")));
          return l;
        }
      }
    }
    
  2. Namespace’lerin background’unu yellow yap
    namespace Ciper
    {
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System.Collections.Generic;
      using System.Text.RegularExpressions;
     
      [ContentType("csharp")]
      partial class DummyClassifier
      {
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          var l = new List<ClassificationSpan>();
          var m = new Regex(@"^\s*namespace\s+(\S+)").Match(span.GetText());
          if (m.Success)
          {
            var s = new SnapshotSpan(span.Snapshot, span.Start + m.Groups[1].Index, m.Groups[1].Length);
            l.Add(new ClassificationSpan(s, classificationTypeRegistry.GetClassificationType("html server-side script")));
          }
          return l;
        }
      }
    }
    
  3. Namespace’leri string renginde goster
    namespace Ciper
    {
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System.Collections.Generic;
      using System.Text.RegularExpressions;
     
      [ContentType("csharp")]
      partial class DummyClassifier
      {
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          var l = new List<ClassificationSpan>();
          var m = new Regex(@"^\s*namespace\s+(\S+)").Match(span.GetText());
          if (m.Success)
          {
            var s = new SnapshotSpan(span.Snapshot, span.Start + m.Groups[1].Index, m.Groups[1].Length);
            l.Add(new ClassificationSpan(s, standardClassifications.StringLiteral));
          }
          return l;
        }
      }
    }
    
  4. Ceyhun ile baslayan comment’leri kirmizi olarak goster.
    namespace Ciper
    {
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System.Collections.Generic;
      using System.Text.RegularExpressions;
     
      [ContentType("csharp")]
      partial class DummyClassifier
      {
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          var l = new List<ClassificationSpan>();
          var m = new Regex(@"//\s*Ceyhun:?\s+(.+)"RegexOptions.IgnoreCase).Match(span.GetText());
          if (m.Success)
          {
            var s = new SnapshotSpan(span.Snapshot, span.Start + m.Groups[1].Index, m.Groups[1].Length);
            l.Add(new ClassificationSpan(s, standardClassifications.StringLiteral));
          }
          return l;
        }
      }
    }
    
  5. “// re 1.1.1.1 x@y.com data” gibi baslayan commentlerde ip’leri kirmizi, email’leri mavi, digerlerini disabled goster.
    namespace Ciper
    {
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System.Collections.Generic;
      using System.Text.RegularExpressions;
     
      [ContentType("csharp")]
      partial class DummyClassifier
      {
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          var l = new List<ClassificationSpan>();
          var m = new Regex(@"^\s*//\s*re:?\s+(.+)"RegexOptions.IgnoreCase).Match(span.GetText());
          if (m.Success)
          {
            var reGroup = m.Groups[1];
            int start = span.Start;
            var s = new SnapshotSpan(span.Snapshot, start + reGroup.Index, reGroup.Length);
            l.Add(new ClassificationSpan(s, standardClassifications.ExcludedCode));
     
            var ips = Regex.Matches(reGroup.Value, @"\d+\.\d+.\d+\.\d+");
            foreach (Match ip in ips)
            {
              s = new SnapshotSpan(span.Snapshot, start + ip.Index + reGroup.Index, ip.Length);
              l.Add(new ClassificationSpan(s, standardClassifications.StringLiteral));
            }
     
            var emails = Regex.Matches(reGroup.Value, @"\w+\@\w+\.\w+");
            foreach (Match email in emails)
            {
              s = new SnapshotSpan(span.Snapshot, start + email.Index + reGroup.Index, email.Length);
              l.Add(new ClassificationSpan(s, standardClassifications.Keyword));
            }
          }
          return l;
        }
      }
    }
    
  6. Output window’undaki tum span’leri comment renginde goster.
    namespace Ciper
    {
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System.Collections.Generic;
     
      [ContentType("output")]
      partial class DummyClassifier
      {
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          var l = new List<ClassificationSpan>();
          l.Add(new ClassificationSpan(span, standardClassifications.Comment));
          return l;
        }
      }
    }
    
  7. Output window’unu renklendir.
    namespace Ciper
    {
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System.Collections.Generic;
      using System.Text.RegularExpressions;
     
      [ContentType("output")]
      partial class DummyClassifier
      {
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          var l = new List<ClassificationSpan>();
          var text = span.GetText();
          Match m;
     
          m = Regex.Match(text, @"Project:\s([^,]+)");
          if (m.Success)
          {
            var projectSpan = new SnapshotSpan(span.Start + m.Groups[1].Index, m.Groups[1].Length);
            l.Add(new ClassificationSpan(projectSpan, standardClassifications.Keyword));
          }
     
          m = Regex.Match(text, @"error\s\w+:\s(.+)$");
          if (m.Success)
          {
            var projectSpan = new SnapshotSpan(span.Start + m.Groups[1].Index, m.Groups[1].Length);
            l.Add(new ClassificationSpan(projectSpan, standardClassifications.StringLiteral));
          }
     
          return l;
        }
      }
    }
    
  8. Show all standard classifications in the output window (with proper coloring).
    namespace Ciper
    {
      using Microsoft.VisualStudio.Language.StandardClassification;
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Reflection;
     
      [ContentType("output")]
      partial class DummyClassifier
      {
        bool initialized = false;
        IEnumerable<string> predefinedClassificationTypeNames
        {
          get
          {
            return
              typeof(PredefinedClassificationTypeNames)
              .GetFields(BindingFlags.Public | BindingFlags.Static)
              .Where(f => f.IsLiteral)
              .Select(f => f.GetValue(f).ToString());
          }
        }
     
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          if (!initialized)
          {
            outputWindowPane.OutputString(Environment.NewLine);
            outputWindowPane.OutputString("Predefined Classification Type Names:" + Environment.NewLine);
            outputWindowPane.OutputString("------------------------------------" + Environment.NewLine);
            foreach (var name in predefinedClassificationTypeNames)
            {
              outputWindowPane.OutputString(name + Environment.NewLine);
            }
            outputWindowPane.OutputString(Environment.NewLine);
            initialized = true;
          }
     
          var l = new List<ClassificationSpan>();
          var classificationTypeName = span.GetText().Trim();
          if (predefinedClassificationTypeNames.Any(n => n == classificationTypeName))
          {
            var classificationType = classificationTypeRegistry.GetClassificationType(classificationTypeName);
            if (classificationType != null)
              l.Add(new ClassificationSpan(span, classificationType));
          }
          return l;
        }
      }
    }
    
  9. Batch file’larinda REM ile baslayan satirlari comment olarak goster.
    namespace Ciper
    {
      using Microsoft.VisualStudio.Text;
      using Microsoft.VisualStudio.Text.Classification;
      using Microsoft.VisualStudio.Utilities;
      using System.Collections.Generic;
      using System.ComponentModel.Composition;
      using System.Text.RegularExpressions;
     
      [ContentType("bat")]
      partial class DummyClassifier
      {
        [ExportName("bat"), BaseDefinition("text")]
        ContentTypeDefinition batContentTypeDefinition;
     
        [ExportFileExtension(".bat"), ContentType("bat")]
        FileExtensionToContentTypeDefinition batFileExtensionDefinition;
     
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
          var l = new List<ClassificationSpan>();
          var text = span.GetText();
          if (Regex.IsMatch(text, @"^\s*rem\s+"RegexOptions.IgnoreCase))
          {
            l.Add(new ClassificationSpan(span, classificationTypeRegistry.GetClassificationType("comment")));
          }
          return l;
        }
      }
    }
    
  10. Bash .sh file’larinda sha-bang satirlarini gri goster.
  11. Regex file’learinda (.re) ip ve email’leri degisik renkte goster.
  12. Passwords.txt file’ini renklendir.

Standard VS Editor Classification Types

Filed under: VS Editor — Tags: — Ceyhun Ciper @ 15:07

Here are some of the standard classification types:

ClassificationTypes1

Or, if you prefer Courier:

ClassificationTypes2

Here is how to use them:

[Import]
IClassificationTypeRegistryService registry = null;

IClassificationType classificationType = registry.GetClassificationType(“Symbol Reference”);

Here is a list of all the standard classification types:

string[] classificationTypes = new string[] {
“BIDINEUTRAL”,
“TEXT”,
“QUICKINFO-BOLD”,
“MARKERPLACEHOLDER”,
“WORD WRAP GLYPH”,
“SIGHELP-DOCUMENTATION”,
“CURRENTPARAM”,
“NATURAL LANGUAGE”,
“FORMAL LANGUAGE”,
“COMMENT”,
“IDENTIFIER”,
“KEYWORD”,
“WHITESPACE”,
“OPERATOR”,
“LITERAL”,
“STRING”,
“CHARACTER”,
“NUMBER”,
“OTHER”,
“EXCLUDED CODE”,
“PREPROCESSOR KEYWORD”,
“SYMBOL DEFINITION”,
“SYMBOL REFERENCE”,
“URL”,
“LINE NUMBER”,
“VB XML DOC TAG”,
“VB XML DOC ATTRIBUTE”,
“VB XML DOC COMMENT”,
“VB XML DELIMITER”,
“VB XML COMMENT”,
“VB XML NAME”,
“VB XML ATTRIBUTE NAME”,
“VB XML CDATA SECTION”,
“VB XML PROCESSING INSTRUCTION”,
“VB XML ATTRIBUTE VALUE”,
“VB XML ATTRIBUTE QUOTES”,
“VB XML TEXT”,
“VB XML EMBEDDED EXPRESSION”,
“VB USER TYPES”,
“VB EXCLUDED CODE”,
“CSS KEYWORD”,
“CSS COMMENT”,
“CSS SELECTOR”,
“CSS PROPERTY NAME”,
“CSS PROPERTY VALUE”,
“CSS STRING VALUE”,
“HTML ATTRIBUTE NAME”,
“HTML ATTRIBUTE VALUE”,
“HTML COMMENT”,
“HTML ELEMENT NAME”,
“HTML ENTITY”,
“HTML OPERATOR”,
“HTML SERVER-SIDE SCRIPT”,
“HTML TAG DELIMITER”,
“HTML PRIORITY WORKAROUND”,
“SCRIPT KEYWORD”,
“SCRIPT COMMENT”,
“SCRIPT OPERATOR”,
“SCRIPT NUMBER”,
“SCRIPT STRING”,
“SCRIPT IDENTIFIER”,
“SCRIPT FUNCTION BLOCK START”
};

Create a free website or blog at WordPress.com.