Click here to Skip to main content
15,886,812 members
Articles / Programming Languages / C#

Linkify Add-in for Visual Studio

Rate me:
Please Sign up or sign in to vote.
4.59/5 (23 votes)
2 Aug 2008CPOL9 min read 171K   433   99  
Link source code comments to your bug tracker, MSDN, development Wiki and more.
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Text.RegularExpressions;

namespace Linkify
{
  [Serializable]
  public class Protocol : ICloneable
  {
    public string prefix = "";

    [XmlElement(ElementName = "url")]
    public string url_deprecated = null;  // deprecated, use "exe" and/or "args"
    public string info = "";
    public bool urlEscape = true;
    public string exe = "";
    public string args = "";
    public bool confirmExecution = false;

    // introduced in 1.3
    public bool enabled = true;
    public string regEx = "";
    public RegexOptions regExOptions = RegexOptions.IgnoreCase;
    public string utilityUrl = "";
    public bool expandEnvVars = true;


    public enum Separator
    {
      SpecialChar = 0,    // default for old config files: everything up to space or : . ; , ) 
      Space = 1,          // first space (quotes still respected)
      LineRemainder = 2,  // remainder of the current line, trailing spaces are trimmed
      RegEx = 3,          // use RegEx on remainder of line, and extract first / default match (1.3)
    }

    public Separator separator;

    // call PostDeserialize after loading to adapt old data
    public void PostDeserialize()
    {
      // Adjust from version 1: only used "url"
      if (url_deprecated != null && url_deprecated.Length != 0)
      {
        exe = url_deprecated;
        args = "";
        url_deprecated = null;
      }
    }

    public object Clone()
    {
      Protocol p = this.MemberwiseClone() as Protocol;
      return p;
    }
  }

  [Serializable]
  public class ProtocolList : System.Collections.Generic.List<Protocol>, ICloneable
  {
    public Protocol MatchRequest(string request)
    {
      foreach(Protocol p in this)
      {
        if (p.enabled && request.StartsWith(p.prefix, StringComparison.OrdinalIgnoreCase))
          return p;
      }
      return null;
    }

    public Protocol MatchRequest(string request, int atIndex)
    {
      request = request.Substring(atIndex);
      return MatchRequest(request);
    }

    public Protocol Find(Protocol rhs)
    {
      return MatchRequest(rhs.prefix);
    }

    public void Merge(ProtocolList rhs, bool overrideExisting)
    {
      if (rhs == this)
        return;

      foreach (Protocol prhs in rhs)
      {
        Protocol existing = Find(prhs);
        if (existing != null)
        {
          if (overrideExisting)   // remove existing, and append new one
            Remove(existing);
          else
            continue;
        }
        Add(prhs.Clone() as Protocol);
      }
    }

    public object Clone()
    {
      ProtocolList copy = new ProtocolList();
      copy.Capacity = Count;
      foreach (Protocol p in this)
        copy.Add(p);
      return copy;
    }
  }

  [Serializable]
  public class Settings : ICloneable
  {
    public ProtocolList protocols = new ProtocolList();
    public bool TestMode = false;
    public bool ShiftForcesConfigMode = true;

    public PH.Utility.ControlPosition CPConfig = new PH.Utility.ControlPosition();
    public PH.Utility.ControlPosition CPConfirm = new PH.Utility.ControlPosition();

    public object Clone()
    {
      Settings copy = this.MemberwiseClone() as Settings;
      // deep copy reference members
      copy.protocols = copy.protocols.Clone() as ProtocolList;
      return copy;
    }

    /// call after deserialization, to adapt old serialization formats
    public void PostDeserialize()
    {
      foreach (Protocol p in protocols)
        if (p != null)
          p.PostDeserialize();
    }

    public void Merge(Settings rhs, bool overrideExisting)
    {
      if (rhs.protocols != null)
        protocols.Merge(rhs.protocols, overrideExisting);
    }

    public String SaveToString()
    {
      XmlSerializer ser = new XmlSerializer(typeof(Settings));
      MemoryStream writer = new MemoryStream();
      ser.Serialize(writer, this);
      return System.Convert.ToBase64String(writer.GetBuffer());
    }

    public static Settings LoadFromString(String s)
    {
      byte[] data = System.Convert.FromBase64String(s);
      XmlSerializer ser = new XmlSerializer(typeof(Settings));
      MemoryStream reader = new MemoryStream(data);
      Settings settings = ser.Deserialize(reader) as Settings;
      if (settings != null)
        settings.PostDeserialize();
      return settings;
    }

    public void Save(string file)
    {
      XmlSerializer ser = new XmlSerializer(typeof(Settings));
      StreamWriter writer = new StreamWriter(file);
      ser.Serialize(writer, this);
      writer.Close();
    }

    public static Settings Load(string file)
    {
      StreamReader reader = new StreamReader(file);
      XmlSerializer ser = new XmlSerializer(typeof(Settings));
      Settings settings = ser.Deserialize(reader) as Settings;
      reader.Close();
      if (settings != null)
        settings.PostDeserialize();
      return settings;
    }

    public static Settings GenerateSample()
    {
      Settings defaultSettings = new Settings();
      Protocol p = new Protocol();
      p.prefix = "bugz:";
      p.info = "(link to your bug tracker here)";
      p.exe = "(set bugtracker url) http://myserver/bugs?id=*";
      p.urlEscape = true;
      p.separator = Protocol.Separator.SpecialChar;
      defaultSettings.protocols.Add(p);

      p = new Protocol();
      p.prefix = "msdn:";
      p.info = "Search MSDN (you might prefer google with site:msdn.microsoft.com)";
      p.exe = "http://search.microsoft.com/results.aspx?q=*&l=2";
      p.urlEscape = true;
      p.separator = Protocol.Separator.SpecialChar;
      defaultSettings.protocols.Add(p);

      p = new Protocol();
      p.prefix = "wiki:";
      p.info = "(link your documentation wiki here)";
      p.exe = "(set wiki url) http://localhost/wiki/?*";
      p.urlEscape = true;
      p.separator = Protocol.Separator.SpecialChar;
      defaultSettings.protocols.Add(p);

      p = new Protocol();
      p.prefix = "google:";
      p.info = "search term on google";
      p.exe = "http://www.google.com/search?q=*";
      p.urlEscape = true;
      p.separator = Protocol.Separator.SpecialChar;
      defaultSettings.protocols.Add(p);

      p = new Protocol();
      p.prefix = "ie:";
      p.info = "call Internet Explorer directly";
      p.exe = @"%PROGRAMFILES%\Internet Explorer\iexplore.exe";
      p.args = "*";
      p.urlEscape = true;
      p.separator = Protocol.Separator.SpecialChar;
      p.enabled = false;
      defaultSettings.protocols.Add(p);

      p = new Protocol();
      p.enabled = false;
      p.prefix = "cp:";
      p.info = "Search codeproject.com for articles";
      p.exe = "http://www.codeproject.com/info/search.asp?st=kw&target=*";
      p.urlEscape = true;
      p.separator = Protocol.Separator.SpecialChar;
      defaultSettings.protocols.Add(p);

      p = new Protocol();
      p.enabled = false;
      p.prefix = "cpian:";
      p.info = "Search codeproject.com for articles by the given author";
      p.exe = "http://www.codeproject.com/info/search.asp?st=au&target=*";
      p.urlEscape = true;
      p.separator = Protocol.Separator.SpecialChar;
      defaultSettings.protocols.Add(p);


      p = new Protocol();
      p.prefix = "$overload:";
      p.info = "Use DefaultOverloader to generate overloads for given functions";
      p.separator = Protocol.Separator.LineRemainder;
      p.exe = @"(set path to DefaultOverloader.exe)";
      p.args = "*";
      p.utilityUrl = "http://www.codeproject.com/KB/cs/DefaultOverloader.aspx";
      defaultSettings.protocols.Add(p);

      p = new Protocol();
      p.prefix = "Regex(@";
      p.info = "call Expresso (requires modification, works only for simple expressions)";
      p.separator = Protocol.Separator.SpecialChar;
      p.exe = @"%PROGRAMFILES%\Expresso\Expresso.exe";
      p.args = "/rxu=*";
      p.utilityUrl = "http://www.codeproject.com/KB/dotnet/expresso.aspx?msg=2374853#xx2374853xx";
      p.enabled = false;
      defaultSettings.protocols.Add(p);



      defaultSettings.PostDeserialize(); // Adapt old "url" format to new exe/args

      return defaultSettings;
    }
  }


}

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 Code Project Open License (CPOL)


Written By
Klippel
Germany Germany
Peter is tired of being called "Mr. Chen", even so certain individuals insist on it. No, he's not chinese.

Peter has seen lots of boxes you youngsters wouldn't even accept as calculators. He is proud of having visited the insides of a 16 Bit Machine.

In his spare time he ponders new ways of turning groceries into biohazards, or tries to coax South American officials to add some stamps to his passport.

Beyond these trivialities Peter works for Klippel[^], a small german company that wants to make mankind happier by selling them novel loudspeaker measurement equipment.


Where are you from?[^]



Please, if you are using one of my articles for anything, just leave me a comment. Seeing that this stuff is actually useful to someone is what keeps me posting and updating them.
Should you happen to not like it, tell me, too

Comments and Discussions