Click here to Skip to main content
15,894,646 members
Articles / Programming Languages / C# 4.0

Writing a P2P Snippet sharing Extension for Visual Studio 2010 (VSX 2010)

Rate me:
Please Sign up or sign in to vote.
4.50/5 (6 votes)
31 Mar 2010GPL311 min read 36.5K   332   21  
CodeXchange is a simple Visual Studio extension which allows you to create, edit and share snippets with your peers without leaving the Visual Studio 2010 IDE.
using System;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace Sand.Services.CodeXchange.Client.Controls
{
    public class SourceCodeTextBox : TextBox
    {
        public SourceCodeTextBox()
        {
            Multiline = true;
            ScrollBars = ScrollBars.Vertical;
        }
    }
#if Code
    public class SourceCodeTextBox : RichTextBox
	{
		#region Constants
		#endregion

		#region Private fields
		// All c# keywords in alphabetic order :
		string[] keywords =
			{ "abstract"
			, "as"
			, "base"
			, "bool"
			, "break"
			, "byte"
			, "case"
			, "catch"
			, "char"
			, "checked"
			, "class"
			, "const"
			, "continue"
			, "decimal"
			, "default"
			, "delegate"
			, "do"
			, "double"
			, "else"
			, "enum"
			, "event"
			, "explicit"
			, "extern"
			, "false"
			, "finally"
			, "fixed"
			, "float"
			, "for"
			, "foreach"
			, "get"
			, "goto"
			, "if"
			, "implicit"
			, "in"
			, "int"
			, "interface"
			, "internal"
			, "is"
			, "lock"
			, "long"
			, "namespace"
			, "new"
			, "null"
			, "object"
			, "operator"
			, "out"
			, "override"
			, "params"
			, "private"
			, "protected"
			, "public"
			, "readonly"
			, "ref"
			, "return"
			, "sbyte"
			, "sealed"
			, "set"
			, "short"
			, "sizeof"
			, "stackalloc"
			, "static"
			, "string"
			, "struct"
			, "switch"
			, "this"
			, "throw"
			, "true" 
			, "try"
			, "typeof"
			, "uint"
			, "ulong"
			, "unchecked"
			, "unsafe"
			, "ushort"
			, "using"
			, "virtual"
			, "void"
			, "volatile"
			, "while"
			};

		private bool parseInProgress = false;
		#endregion
		
		#region Constructors
		public SourceCodeTextBox() : base()
		{
			this.Multiline      = true;
			this.WordWrap       = false;
			this.AcceptsTab     = true;
			this.ScrollBars     = RichTextBoxScrollBars.ForcedBoth;
			this.ForeColor      = SystemColors.WindowText;
			this.Font           = new Font("Courier New", 8, FontStyle.Regular );
		}
		#endregion

		#region Overriden methods
		protected override void OnTextChanged ( System.EventArgs e )
		{
			if( !parseInProgress )
			{
				base.OnTextChanged(e);

				ParseLines();
			}
		}

		protected override void OnVisibleChanged(EventArgs e)
		{
			if( !parseInProgress )
			{
				base.OnVisibleChanged (e);

				ParseLines();
			}
		}
		#endregion

		#region Public Methods
		public void RefreshText()
		{
			ParseLines();
		}
		#endregion

		#region Public Properties
		#endregion

		#region Private-Protected Methods
		private void ParseLines()
		{
			parseInProgress = true;

			int startPos = this.SelectionStart;
			string currentText = this.Text;
			this.Text = "";

			bool inMultiLineComment     = false;
			bool inComment              = false;
			bool inString               = false;
			bool inChar                 = false;
			bool isKeyWord              = false;

			bool stringBeganWithAtSign  = false;

			Regex regExSplitTokens = new Regex("([ \\\\\t\\n{}().:;\"'])");
			string [] tokens = regExSplitTokens.Split(currentText); 

			string prevToken = "";

			for( int iToken = 0 ; iToken < tokens.Length ; iToken++ )
			{
				string token = tokens[ iToken ];
				if( token.Length > 0 )	// Strangely enought there are empty strings in there.
				{
					isKeyWord = false;

					if( inMultiLineComment )
					{
						inMultiLineComment = ( token != @"*/" && !token.StartsWith( @"*/") && !token.EndsWith( @"*/") );
					}
					else if ( inComment )
					{
						// At end of line comment ends
						inComment = ( token != "\n" );
					}
					else if ( inString )
					{
						// String ends with another " char
						if( stringBeganWithAtSign || prevToken != @"\" ) inString = ( token != '"'.ToString() );
					}
					else if ( inChar )
					{
						// Char ends with another ' char
						inChar   = ( token != "'" );
					}
					else
					{
						inMultiLineComment = ( token == @"/*" || token.StartsWith( @"/*") );
						if( !inMultiLineComment ) inComment = ( token == @"//" || token.StartsWith( @"//") );
						if( !inMultiLineComment && !inComment )
						{
							inString  = ( token == '"'.ToString());
							if( inString )
							{
								stringBeganWithAtSign = ( prevToken == "@" );
							}
						}
						if( !inMultiLineComment && !inComment && !inString ) inChar = ( token == "'" );
					
						if (  ( !inMultiLineComment )
							&& ( !inComment          )
							&& ( !inString           )
							&& ( !inChar             )
							)
						{
							// Check keywords
							for (int iKeyword = 0; iKeyword < keywords.Length; iKeyword++) 
							{
								if ( token == keywords[iKeyword] ) 
								{
									isKeyWord = true;
									break;
								}
							}
						}
					}

					if( inMultiLineComment || inComment )
					{
						this.SelectionColor = Color.Green;
					}
					else if ( inString || inChar )
					{
						this.SelectionColor = Color.Purple;
					}
					else if( isKeyWord )
					{
						this.SelectionColor = Color.Blue;
					}
					else
					{
						this.SelectionColor = this.ForeColor;
					}

					// We need the previous token just for strings with \" in them,
					// which indicates that the " is part of the string.
					prevToken = token;

					this.SelectedText = token;
				}
			} 
			if( startPos != -1 ) this.SelectionStart = startPos;

			parseInProgress = false;
		}
		#endregion
	}
#endif
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
Spain Spain
Hi! I'm 22 years old. I live in a sunny mediterranian city called Barcelona.

I am a big fan of .NET and have been working with c# for a few years now.

Comments and Discussions