本来这个功能应该算是编辑器的一个附属功能,本来有一个JS的代码着色器(syntaxhighlighter),现在版本是1.51,但是由于其功能始终是客户端的,有一些服务器操作比较麻烦,于是自己写了一个,当前只是实现了C#版本。
在这里,我讲述一下该代码实现模式,这里主要讲讲循环和分组的机制
主体:
![](https://www.cnblogs.com/images/cnblogs_com/keithdan/highlight1.jpg)
HighLightCode:为高亮代码的基类,并抽象,含有抽象方法
通过方法实现实例
public
static
HighLightCode CreateHighLightCode(CodeType regexcodetype)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
HighLightCode code = null;
if (regexcodetype == CodeType.CSharp)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
code = new RegexCSharp();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return code;
}
RegexCSharp:实现HighLightCode方法。
当前为C#实现了该方法,如果Java类实现该方法,则可以扩展出Java的着色代码.
思路:
如果我们直接使用正则表达式进行匹配,那么比较麻烦,会出现一些问题,如://string abc = "hello";那么"hello"会被分析为引号部分,而非注释部分。要解决该问题,我们先分析一下代码着色的原理和基础。
特殊的符号包括单引号,双引号,单行注释,多行注释的判断,由于这些情况都是成对的出现,我们需要找出这4个情况前后匹配的数据进行分组处理。
注意,单行注释由//开头,\r\n结尾
如:string abc= "hello!";
那么string abc=作为group1,"hello!"作为group2,;作为group3。那么在group1和group3我们需要的仅仅是对关键字进行匹配,在这里最简单的方法就是正则表达式进行匹配和着色。那么对于group2无非就是添加深红色而已。但是对于分组我们需要找到最先出现的符号位置,如:string abc = "hello // world!";此时的//应该作为字符串而非注释,所以它必须为group2中。
分组方法:
我们先讨论只有一个目标符号的情况。即:string abc= "hello!";
我们首先将4个符号的出现的初始位置找到,进行排序,得到位置最小的符号,那么该组就是以该符号为基准。在这里,我使用了List进行排序。得到位置最小的符号组,那么它就是我们要寻找的目标符号,于是寻找他的结尾符号,则可以得到它具体的字符串。
List
<
RegexItem
>
regexs
=
new
List
<
RegexItem
>
();
RegexItem regx
=
null
;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
int
count
=
0
;
int
pos1
=
code.IndexOf(
'
"
'
, start);
if
(pos1
>
-
1
)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
count++;
regx = new RegexItem();
regx.Postion = pos1;
regx.RegexMode = Mode.DoubleQuotedString;
regexs.Add(regx);
}
int
pos2
=
code.IndexOf(BeginSingleLineComments, start);
if
(pos2
>
-
1
)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
count++;
regx = new RegexItem();
regx.Postion = pos2;
regx.RegexMode = Mode.SingleLineComments;
regexs.Add(regx);
}
int
pos3
=
code.IndexOf(BeginMultiLineComments, start);
if
(pos3
>
-
1
)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
count++;
regx = new RegexItem();
regx.Postion = pos3;
regx.RegexMode = Mode.MultiLineComments;
regexs.Add(regx);
}
int
pos4
=
code.IndexOf(
"
'
"
, start);
if
(pos4
>
-
1
)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
count++;
regx = new RegexItem();
regx.Postion = pos4;
regx.RegexMode = Mode.SingleQuotedString;
regexs.Add(regx);
}
如上:pos1,pos2,pos3,pos4分别得到4个符号的最初位置,并放置于一个List<RegexItem>中,count表示查找到的符号的个数
if
(找到了特殊符号)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
则将List排序,得到最小的符号
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
则没有符号,所以都作为默认的数据处理
}
最后我们需要去匹配这些特殊符号,
if
(该符号为双引号)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
找到双引号以前的位置数据
//这个就是group1
找到后双引号位置
找到双引号位置内的数据
//这个就是group2
}
。。。。。。
通过这样的逻辑判断就简单地分出一个代码片段的组,group1和group2
循环流程:
由于程序不会只有一个目标符号,如:
string a1= "hello!";
string a2= "i love you!";
//string "a3";
上面实例则存在7个组
group1=string a1=
group2="hello!"
group3=;
group4=string a2=
group5="i love you!"
group6=;
group7=//string "a3";
这样的组会存在多个,于是我们从目标字符串的0位置开始到它的长度进行循环(for(int i=0;i<code.length;i++)),得到多个的目标组。
![](https://www.cnblogs.com/images/cnblogs_com/keithdan/highlight2.jpg)
该图展示了查找的判断逻辑,每找到一个组,则实例出RegexItem,放置到List<RegexItem>集合中。
List
<
RegexItem
>
items
=
new
List
<
RegexItem
>
();
private
int
CreateItem(
string
code,
int
start)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
List<RegexItem> regexs = new List<RegexItem>();
RegexItem regx = null;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
int count = 0;
int pos1 = code.IndexOf('"', start);
if (pos1 > -1)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
count++;
regx = new RegexItem();
regx.Postion = pos1;
regx.RegexMode = Mode.DoubleQuotedString;
regexs.Add(regx);
}
int pos2 = code.IndexOf(BeginSingleLineComments, start);
if (pos2 > -1)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
count++;
regx = new RegexItem();
regx.Postion = pos2;
regx.RegexMode = Mode.SingleLineComments;
regexs.Add(regx);
}
int pos3 = code.IndexOf(BeginMultiLineComments, start);
if (pos3 > -1)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
count++;
regx = new RegexItem();
regx.Postion = pos3;
regx.RegexMode = Mode.MultiLineComments;
regexs.Add(regx);
}
int pos4 = code.IndexOf("'", start);
if (pos4 > -1)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
count++;
regx = new RegexItem();
regx.Postion = pos4;
regx.RegexMode = Mode.SingleQuotedString;
regexs.Add(regx);
}
RegexItem minItem = null;
if (count > 0)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (regexs.Count > 1)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Comparison<RegexItem> comp = new Comparison<RegexItem>(SortItmes);
regexs.Sort(comp);
minItem = regexs[0];
}
else if (regexs.Count == 1)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
minItem = regexs[0];
}
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
minItem = new RegexItem();
minItem.Postion = start;
minItem.RegexMode = Mode.Default;
}
int end = 0;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
RegexItem itemFirst = new RegexItem();
itemFirst.RegexMode = Mode.Default;
itemFirst.Postion = start;
if (minItem.RegexMode == Mode.DoubleQuotedString)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
end = code.IndexOf('"', minItem.Postion + 1);
itemFirst.Text = code.Substring(start, minItem.Postion - start);
items.Add(itemFirst);
minItem.Text = code.Substring(minItem.Postion, end - minItem.Postion + 1);
items.Add(minItem);
}
else if (minItem.RegexMode == Mode.SingleLineComments)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
end = code.IndexOf(EndSingleLineComments, minItem.Postion + 1);
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (end == -1)
{ end = code.Length - 1; }//为最后一行
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
else
{ end++; }//因为\r\n占两个字节
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
itemFirst.Text = code.Substring(start, minItem.Postion - start);
items.Add(itemFirst);
minItem.Text = code.Substring(minItem.Postion, end - minItem.Postion + 1);
items.Add(minItem);
}
else if (minItem.RegexMode == Mode.MultiLineComments)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
end = code.IndexOf(EndMultiLineComments, minItem.Postion + 1);
itemFirst.Text = code.Substring(start, minItem.Postion - start);
items.Add(itemFirst);
minItem.Text = code.Substring(minItem.Postion, end - minItem.Postion + 1);
items.Add(minItem);
}
else if (minItem.RegexMode == Mode.SingleQuotedString)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
end = code.IndexOf("'", minItem.Postion + 1);
itemFirst.Text = code.Substring(start, minItem.Postion - start);
items.Add(itemFirst);
minItem.Text = code.Substring(minItem.Postion, end - minItem.Postion + 1);
items.Add(minItem);
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// end = code.IndexOf(start, minItem.Postion - start + 1);
end = code.Length - 1;
minItem.Text = code.Substring(start, code.Length - start);
items.Add(minItem);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return end;
}
public
string
GetHighLightCode(
string
code)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
int i = 0;
//循环判断逻辑
for (; i < code.Length; i++)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
int start = CreateItem(code, i);
i = start;
}
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
}
当然,如果没有源码的朋友可以到http://www.cnblogs.com/KeithDan/archive/2008/04/23/1168279.html 去下载