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

写了一个全文本的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
      }
}
posted @ 2005-01-10 14:45  Teddy's Knowledge Base  Views(2801)  Comments(10Edit  收藏  举报