全文本代码着色(带源码和示例)

来源:互联网 发布:淘宝引擎推广怎么操作 编辑:程序博客网 时间:2024/06/11 18:59
写了一个全文本的C#代码着色器,不采用任何图片,因为事先没有参考任何已有着色器源码,可能有些地方实现的不是很优雅,如果谁手里有其他着色器的源码,望多交流!

完整源码下载地址:
http://teddy.51.net/products/HtmlCodeColor.rar

代码示例:
    using System; using System.Text.RegularExpressions; namespace CN.Teddy.Util.HtmlCodeColor {       /// <summary>       /// C#代码着色适配器       /// </summary>       public class CSharpAdapter : ICodeColorAdapter       { +             Constructors                          public CSharpAdapter()             {                   //null             }              -             #endregion              +             Private Members                          /// <summary>             /// 为//和/**/类型的注释着色             /// </summary>             /// <param name="src">输入源码</param>             /// <returns>格式化后的源码</returns>             private string ColorBasicComment(string src)             {                   string retCode = src;                                      Regex r1 = new Regex(@"(^|;)([ /t]*)(//.*$)", RegexOptions.Multiline);                   retCode = r1.Replace(retCode, "$1$2<span style=/"color: green/">$3</span>");                   Regex r2 = new Regex(@"(^|[ /t]+)(//*[^/*/]*/*/[ /t/r]*$)", RegexOptions.Multiline);                   retCode = r2.Replace(retCode, new MatchEvaluator(this.ColorBasicComment2Evaluator));                                      return retCode;             }                          /// <summary>             /// 为///类型的注释着色             /// </summary>             /// <param name="src">输入源码</param>             /// <returns>格式化后的源码</returns>             private string ColorXmlComment(string src)             {                   string retCode = src;                                      Regex r1 = new Regex(@"(/// *)&lt;(.*)&gt;", RegexOptions.Multiline);                   retCode = r1.Replace(retCode, new MatchEvaluator(this.ColorXmlCommentEvaluator));                   Regex r2 = new Regex(@"(/// *)(.*$)", RegexOptions.Multiline);                   retCode = r2.Replace(retCode, "<span style=/"color: gray/">$1</span>$2");                                      return retCode;             }                          /// <summary>             /// 为折叠显示代码构建HtmlTable框架             /// </summary>             /// <param name="src">输入源码</param>             /// <returns>格式化后的源码</returns>             private string DrawCollapseFrameTable(string src)             {                   System.Text.StringBuilder retCode = new System.Text.StringBuilder();                                      string frameHeader = "<table border=0 cellpadding=0 cellspacing=0 width=95% style='border: windowtext 0.5pt solid; background-color:#fefefe'><tr><td valign=top align=center style='border-right-color: #808080; border-right-style: solid; border-right-width: 1px'><table border=0 cellpadding=0 cellspacing=0><tr><td>&nbsp;</td><td>&nbsp;</td></tr></table></td><td><table border=0 cellpadding=1 cellspacing=0 width=100%>";                   string frameTailer = "</table></td></tr></table>";                                      retCode.Append(frameHeader);                                      string[] lines = src.Split('/n');                                      foreach (string line in lines)                   {                         string formatedLine = line.Trim();                                                  string lineHeader = "<tr><td style='width: 0px'><table style='width: 9px; height: 9px'><tr><td></td></tr></table></td><td style='width: 0px'></td><td style='width: 100%'><code style='font: 9pt Tahoma'>";                         string lineTailer = "</code></td></tr>";                                                  formatedLine = lineHeader + formatedLine + lineTailer;                                                  retCode.Append(formatedLine);                   }                                      retCode.Append(frameTailer);                                      return retCode.ToString();             }                          /// <summary>             /// 折叠Region             /// </summary>             /// <param name="src">输入源码</param>             /// <returns>格式化后的源码</returns>             private string CollapseRegion(string src)             {                   string retCode = src;                                      string lineHeader = "<tr><td style='width: 0px'><table style='width: 9px; height: 9px'><tr><td></td></tr></table></td><td style='width: 0px'></td><td style='width: 100%'><code style='font: 9pt Tahoma'>";                                      Regex r = new Regex(lineHeader + @"(&nbsp;)*<span style=/""color: blue/"">#region<.*$", RegexOptions.Multiline);                   while (r.Match(retCode).Success)                   {                         //add "+" tag                         retCode = r.Replace(retCode, new MatchEvaluator(this.CollapseRegionEvaluator));                   }                                      return retCode;             }             /// <summary>             /// 为一行源码中的关键字着色             /// </summary>             /// <param name="codeLine">某一行源码</param>             /// <param name="keywordList">关键字列表</param>             /// <returns>格式化后的源码</returns>             /// <summary>             private string ColorKeyword(string codeLine, string[] keywordList)             {                   string retCode = codeLine;                                      if (!retCode.StartsWith("//"))                   {                         foreach (string keyword in KEYWORD_LIST)                         {                               Regex r = new Regex(@"(^|/s+|,|/)|/(|/{|/}|/[|/]|/.|=|;)(" + keyword + @")(/s+|,|/)|/(|/{|/}|/[|/]|/.|=|;|$)");                                                              retCode = r.Replace(retCode, "$1<span style=/"color: blue/">$2</span>$3");                         }                   }                                      retCode = ClearColoredKeyworsInString(retCode);                                      return retCode.Trim();             }                          /// <summary>             /// 清除字符串中的被着色的关键字             /// </summary>             /// <param name="codeLine">某一行源码</param>             /// <returns>格式化后的源码</returns>             private string ClearColoredKeyworsInString(string codeLine)             {                   System.Text.StringBuilder retCode = new System.Text.StringBuilder();                                      string str = codeLine.Trim();                                      int indexOfQuot = str.IndexOf("&quot;");                   int lengthOfQuot = "&quot;".Length;                                      if (indexOfQuot >= 0)                   {                         while (indexOfQuot >= 0)                         {                               retCode.Append(str.Substring(0, indexOfQuot + lengthOfQuot));                               str = str.Substring(indexOfQuot + lengthOfQuot);                                                              indexOfQuot = str.IndexOf("&quot;");                                                              if (indexOfQuot >= 0)                               {                                     string inStr = str.Substring(0, indexOfQuot + lengthOfQuot);                                                                          inStr = inStr.Replace("/"color: blue/"", "/"/"");                                                                          retCode.Append(inStr);                                     str = str.Substring(indexOfQuot + lengthOfQuot);                               }                                                              indexOfQuot = str.IndexOf("&quot;");                         }                   }                                      retCode.Append(str);                                      return retCode.ToString();             }                                       public static string[] KEYWORD_LIST = {                   "abstract", "event", "new", "struct", "as", "explicit", "null", "switch",                   "base", "extern", "object", "this", "bool", "false", "operator", "throw",                   "break", "finally", "out", "true", "byte", "fixed", "override", "try",                   "case", "float", "params", "typeof", "catch", "for", "private", "uint",                   "char", "foreach", "protected", "ulong", "checked", "goto", "public",                   "unchecked", "class", "if", "readonly", "unsafe", "const", "implicit",                   "ref", "ushort", "continue", "in", "return", "using", "decimal", "int",                   "sbyte", "virtual", "default", "interface", "sealed", "volatile",                   "delegate", "internal", "short", "void", "do", "is", "sizeof", "while",                   "double", "lock", "stackalloc", "else", "long", "static", "enum",                   "namespace", "string", "get", "set", "#region", "#endregion", "true",                   "false"             };                          private string ColorXmlCommentEvaluator(Match m)             {                   Regex r = new Regex("(^.*&gt;)(.*)(&lt;/.*$)");                   if (r.Match(m.Value).Success)                   {                         return r.Replace(m.Value, "<span style=/"color: gray/">$1</span>$2<span style=/"color: gray/">$3</span>");                   }                   else                   {                         return "<span style=/"color: gray/">" + m.Value + "</span>";                   }             }                          private string ColorBasicComment2Evaluator(Match m)             {                   System.Text.StringBuilder retCode = new System.Text.StringBuilder();                                      string[] lines = m.Value.Split('/n');                                      foreach (string line in lines)                   {                         retCode.Append("<span style=/"color: green/">" + line + "</span>" + "/n");                   }                                      return retCode.ToString();             }                          private string CollapseRegionEvaluator(Match m)             {                   //get region code block                                      string retCode = m.Value;                                      string lineHeader = "<tr><td style='width: 0px'><table style='width: 9px; height: 9px'><tr><td></td></tr></table></td><td style='width: 0px'></td><td style='width: 100%'><code style='font: 9pt Tahoma'>";                   string lineTailer = "</code></td></tr>";                                      Regex r = new Regex("^" + lineHeader + @"(&nbsp;)*<span style=/""color: blue/"">#region</span>[^<]*" + lineTailer, RegexOptions.Multiline);                   retCode = r.Replace(retCode, new MatchEvaluator(this.CollapseRegionEvaluator2));                                      //find out #region - #endregion block & add collapse code                   string endRegionLinePattern = "<tr><td style='width: 0px'><table style='width: 9px; height: 9px'><tr><td></td></tr></table></td><td style='width: 0px'></td><td style='width: 100%'><code style='font: 9pt Tahoma'>(&nbsp;)*<span style=/"color: blue/">#endregion</span></code></td></tr>";                   Regex r2 = new Regex(endRegionLinePattern);                   string endRegionLine = r2.Match(retCode).Value;                   string formatedEndRegionLine = endRegionLine.Replace("<td style='width: 0px'></td><td style='width: 100%'>", "<td style='width: 0px'><span style='position: relative; left: -12px; font: 12px'><font color=#808080 face='Tahoma'>-</font></span></td><td style='width: 100%'>");                   string regionBlock = retCode.Substring(0, retCode.IndexOf(endRegionLine)) + formatedEndRegionLine;                                      string spaces = new Regex("(&nbsp;)+").Match(regionBlock).Value;                   string regionDescWidthTag = new Regex("#region</span> ([^<]*)</code>").Match(regionBlock).Value;                   string regionDesc = regionDescWidthTag.Substring(15, regionDescWidthTag.Length - ("#region</span> ").Length - ("</code>").Length);                                      regionBlock = regionBlock.Replace("</tr><tr><td style='width: 0px'>", "</tr><tr style='display: none'><td style='width: 0px'>");                   regionBlock = regionBlock.Substring(0, regionBlock.IndexOf("<code style='font: 9pt Tahoma'>") + "<code style='font: 9pt Tahoma'>".Length) +                   "<span>" + spaces + "</span>" + "<span style='border: 1px solid gray'><font color=gray>" + regionDesc + "</font></span>" +                   regionBlock.Substring(regionBlock.IndexOf("</code>"));                                      retCode = regionBlock + retCode.Substring(retCode.IndexOf(endRegionLine) + endRegionLine.Length);                                      return retCode;             }                                       private string CollapseRegionEvaluator2(Match m)             {                   string retCode = m.Value;                                      //add rectangle                   retCode = retCode.Replace("style='width: 9px; height: 9px'", "style='position: relative; left: -6px; top: 0px; border-color: #808080; border-style: solid; border-width: 1px; background: white; width: 9px; height: 9px'");                                      string spaces = new Regex("(&nbsp;)+").Match(m.Value).Value;                   string regionDescWidthTag = new Regex("#region</span> ([^<]*)</code>").Match(m.Value).Value;                   string regionDesc = regionDescWidthTag.Substring(15, regionDescWidthTag.Length - ("#region</span> ").Length - ("</code>").Length);                                      //add "+" tag                   retCode = retCode.Replace("<td style='width: 0px'></td>", "<td style='width: 0px'><span style='position: relative; left: -16px; top: -1px; font: 12px; cursor: hand' onclick='if (this.childNodes[0].innerHTML == /"_/") { this.childNodes[0].innerHTML = /"+/"; this.style.top = /"-1px/"; this.parentNode.nextSibling.childNodes[0].innerHTML = /"<span>" + spaces + "</span><span><font color=gray>" + regionDesc + "</font></span>/"; this.parentNode.nextSibling.childNodes[0].childNodes[1].style.border = /"1px solid gray/"; for (var i = 1 + this.parentNode.parentNode.rowIndex; i < this.parentNode.parentNode.parentNode.childNodes.length; i++) { this.parentNode.parentNode.parentNode.childNodes[i].style.display=/"none/"; if ( this.parentNode.parentNode.parentNode.childNodes[i].childNodes[1].innerText.length > 0 ) { break; } } } else { this.childNodes[0].innerHTML = /"_/"; this.style.top = /"-6px/"; var oldDesc = this.parentNode.nextSibling.childNodes[0].childNodes[1].childNodes[0].innerHTML; this.parentNode.nextSibling.childNodes[0].innerHTML = /"<span>" + spaces + "</span><span><font color=blue>#region </font></span><span></span>/"; this.parentNode.nextSibling.childNodes[0].childNodes[2].innerHTML = oldDesc; for (var i = 1 + this.parentNode.parentNode.rowIndex; i < this.parentNode.parentNode.parentNode.childNodes.length; i++) { this.parentNode.parentNode.parentNode.childNodes[i].style.display=/"block/"; if ( this.parentNode.parentNode.parentNode.childNodes[i].childNodes[1].innerText.length > 0 ) { break; } } }'><font color=#808080 face='Tahoma'>+</font></span></td>");                                      return retCode;             }              -             #endregion              +             ICodeColorAdapter 成员                          /// <summary>             /// 为注释着色,例如:对C#,包括///型、//型和/**/的注释             /// </summary>             /// <param name="src">输入源码</param>             /// <returns>格式化后的源码</returns>             public string ColorComment(string src)             {                   string retCode = src;                   retCode = ColorBasicComment(retCode);                   retCode = ColorXmlComment(retCode);                   return retCode;             }                          /// <summary>             /// 为关键字着色             /// </summary>             /// <param name="src">输入源码</param>             /// <returns>格式化后的源码</returns>             public string ColorKeyword(string src)             {                   System.Text.StringBuilder retCode = new System.Text.StringBuilder();                                      string[] lines = src.Split('/n');                                      if (lines != null && lines.Length > 0)                   {                         bool isInComment = false;                                                  foreach (string line in lines)                         {                               string formatedLine = line.Trim();                                                              if (new Regex(@"(^|[ /t]+)(//*)").Match(line).Success)                               {                                     isInComment = true;                               }                                                              if (!isInComment)                               {                                     formatedLine = ColorKeyword(line, KEYWORD_LIST);                               }                                                              if (new Regex(@"/*/[ /t/r]*$").Match(line).Success)                               {                                     isInComment = false;                               }                                                              retCode.Append(formatedLine + "/n");                         }                   }                                      return retCode.ToString();             }                          /// <summary>             /// 使代码支持折叠显示             /// </summary>             /// <param name="src">输入源码</param>             /// <returns>格式化后的源码</returns>             public string CollapseCode(string src)             {                   string retCode = src;                   retCode = DrawCollapseFrameTable(retCode);                   retCode = CollapseRegion(retCode);                   return retCode;             }                          /// <summary>             /// 代码缩进             /// </summary>             /// <param name="src">输入源码</param>             /// <returns>格式化后的源码</returns>             public string IndentCode(string src)             {                   System.Text.StringBuilder retCode = new System.Text.StringBuilder();                                      int indent = 0;                   string [] lines = src.Split('/n');                                      foreach (string line in lines)                   {                         string formatedLine = line.Trim();                                                  Regex r = new Regex(@"/}(/}|/s)*;?/s*$");                         if (r.Match(line).Success)                         {                               indent--;                         }                                                  for (int i = 0; i < indent; i++)                         {                               formatedLine = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + formatedLine;                         }                                                  retCode.Append(formatedLine + "/n");                                                  if (line.EndsWith("{"))                         {                               indent++;                         }                         else if (line.StartsWith("{"))                         {                               indent++;                         }                   }                                      return retCode.ToString();             } -             #endregion       } }