最近在做项目中用到使用到SharpDevelop的文本编辑器,AvalonEdit,要在项目中设置文本编辑器的前景色,背景色,字体,以及高亮等等,于是研究SharpDevelop的源码,
在ICSharpCode.AvalonEdit下的Highlighting下Resources文件夹下有许多.xshd文件,这些文件就是SharpDevelop中各种语言的资源文件,在这些资源文件中,如下图:
随便打开一个资源文件,比如打开CSharp-Mode.xshd这个文件,有很多节点,
<?xml version="1.0"?> <SyntaxDefinition name="C#" extensions=".cs" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"> <!-- The named colors 'Comment' and 'String' are used in SharpDevelop to detect if a line is inside a multiline string/comment --> <Color name="Comment" foreground="Green" exampleText="// comment" /> <Color name="String" foreground="Blue" exampleText="string text = "Hello, World!""/> <Color name="Char" foreground="Magenta" exampleText="char linefeed = '\n';"/> <Color name="Preprocessor" foreground="Green" exampleText="#region Title" /> <Color name="Punctuation" exampleText="a(b.c);" /> <Color name="ValueTypes" fontWeight="bold" foreground="Red" exampleText="bool b = true;" /> <Color name="ReferenceTypes" foreground="Red" exampleText="object o;" /> <Color name="MethodCall" foreground="MidnightBlue" fontWeight="bold" exampleText="o.ToString();"/> <Color name="NumberLiteral" foreground="DarkBlue" exampleText="3.1415f"/> <Color name="ThisOrBaseReference" fontWeight="bold" exampleText="this.Do(); base.Do();"/> <Color name="NullOrValueKeywords" fontWeight="bold" exampleText="if (value == null)"/> <Color name="Keywords" fontWeight="bold" foreground="Red" exampleText="if (a) {} else {}"/> <Color name="GotoKeywords" foreground="Navy" exampleText="continue; return null;"/> <Color name="ContextKeywords" foreground="Navy" exampleText="var a = from x in y select z;"/> <Color name="ExceptionKeywords" fontWeight="bold" foreground="Teal" exampleText="try {} catch {} finally {}"/> <Color name="CheckedKeyword" fontWeight="bold" foreground="DarkGray" exampleText="checked {}"/> <Color name="UnsafeKeywords" foreground="Olive" exampleText="unsafe { fixed (..) {} }"/> <Color name="OperatorKeywords" fontWeight="bold" foreground="Pink" exampleText="public static implicit operator..."/> <Color name="ParameterModifiers" fontWeight="bold" foreground="DeepPink" exampleText="(ref int a, params int[] b)"/> <Color name="Modifiers" foreground="Brown" exampleText="static readonly int a;"/> <Color name="Visibility" fontWeight="bold" foreground="Blue" exampleText="public override void ToString();"/> <Color name="NamespaceKeywords" fontWeight="bold" foreground="Green" exampleText="namespace A.B { using System; }"/> <Color name="GetSetAddRemove" foreground="SaddleBrown" exampleText="int Prop { get; set; }"/> <Color name="TrueFalse" fontWeight="bold" foreground="DarkCyan" exampleText="b = false; a = true;" /> <Color name="TypeKeywords" fontWeight="bold" foreground="DarkCyan" exampleText="if (x is int) { a = x as int; type = typeof(int); size = sizeof(int); c = new object(); }"/> <RuleSet name="CommentMarkerSet"> <Keywords fontWeight="bold" foreground="Red"> <Word>TODO</Word> <Word>FIXME</Word> </Keywords> <Keywords fontWeight="bold" foreground="#E0E000"> <Word>HACK</Word> <Word>UNDONE</Word> </Keywords> </RuleSet> <!-- This is the main ruleset. --> <RuleSet> <Span color="Preprocessor"> <Begin>\#</Begin> <RuleSet name="PreprocessorSet"> <Span> <!-- preprocessor directives that allow comments --> <Begin fontWeight="bold"> (define|undef|if|elif|else|endif|line)\b </Begin> <RuleSet> <Span color="Comment" ruleSet="CommentMarkerSet"> <Begin>//</Begin> </Span> </RuleSet> </Span> <Span> <!-- preprocessor directives that don't allow comments --> <Begin fontWeight="bold"> (region|endregion|error|warning|pragma)\b </Begin> </Span> </RuleSet> </Span> <Span color="Comment"> <Begin color="XmlDoc/DocComment">///</Begin> <RuleSet> <Import ruleSet="XmlDoc/DocCommentSet"/> <Import ruleSet="CommentMarkerSet"/> </RuleSet> </Span> <Span color="Comment" ruleSet="CommentMarkerSet"> <Begin>//</Begin> </Span> <Span color="Comment" ruleSet="CommentMarkerSet" multiline="true"> <Begin>/\*</Begin> <End>\*/</End> </Span> <Span color="String"> <Begin>"</Begin> <End>"</End> <RuleSet> <!-- span for escape sequences --> <Span begin="\\" end="."/> </RuleSet> </Span> <Span color="Char"> <Begin>'</Begin> <End>'</End> <RuleSet> <!-- span for escape sequences --> <Span begin="\\" end="."/> </RuleSet> </Span> <Span color="String" multiline="true"> <Begin color="String">@"</Begin> <End>"</End> <RuleSet> <!-- span for escape sequences --> <Span begin='""' end=""/> </RuleSet> </Span> <!-- don't highlight "@int" as keyword --> <Rule> @[\w\d_]+ </Rule> <Keywords color="ThisOrBaseReference"> <Word>this</Word> <Word>base</Word> </Keywords> <Keywords color="TypeKeywords"> <Word>as</Word> <Word>is</Word> <Word>new</Word> <Word>sizeof</Word> <Word>typeof</Word> <Word>stackalloc</Word> </Keywords> <Keywords color="TrueFalse"> <Word>true</Word> <Word>false</Word> </Keywords> <Keywords color="Keywords"> <Word>else</Word> <Word>if</Word> <Word>switch</Word> <Word>case</Word> <Word>default</Word> <Word>do</Word> <Word>for</Word> <Word>foreach</Word> <Word>in</Word> <Word>while</Word> <Word>lock</Word> <Word>fuck</Word> </Keywords> <Keywords color="GotoKeywords"> <Word>break</Word> <Word>continue</Word> <Word>goto</Word> <Word>return</Word> </Keywords> <Keywords color="ContextKeywords"> <Word>yield</Word> <Word>partial</Word> <Word>global</Word> <Word>where</Word> <Word>select</Word> <Word>group</Word> <Word>by</Word> <Word>into</Word> <Word>from</Word> <Word>ascending</Word> <Word>descending</Word> <Word>orderby</Word> <Word>let</Word> <Word>join</Word> <Word>on</Word> <Word>equals</Word> <Word>var</Word> <Word>dynamic</Word> </Keywords> <Keywords color="ExceptionKeywords"> <Word>try</Word> <Word>throw</Word> <Word>catch</Word> <Word>finally</Word> </Keywords> <Keywords color="CheckedKeyword"> <Word>checked</Word> <Word>unchecked</Word> </Keywords> <Keywords color="UnsafeKeywords"> <Word>fixed</Word> <Word>unsafe</Word> </Keywords> <Keywords color="ValueTypes"> <Word>bool</Word> <Word>byte</Word> <Word>char</Word> <Word>decimal</Word> <Word>double</Word> <Word>enum</Word> <Word>float</Word> <Word>int</Word> <Word>long</Word> <Word>sbyte</Word> <Word>short</Word> <Word>struct</Word> <Word>uint</Word> <Word>ushort</Word> <Word>ulong</Word> </Keywords> <Keywords color="ReferenceTypes"> <Word>class</Word> <Word>interface</Word> <Word>delegate</Word> <Word>object</Word> <Word>string</Word> <Word>void</Word> </Keywords> <Keywords color="OperatorKeywords"> <Word>explicit</Word> <Word>implicit</Word> <Word>operator</Word> </Keywords> <Keywords color="ParameterModifiers"> <Word>params</Word> <Word>ref</Word> <Word>out</Word> </Keywords> <Keywords color="Modifiers"> <Word>abstract</Word> <Word>const</Word> <Word>event</Word> <Word>extern</Word> <Word>override</Word> <Word>readonly</Word> <Word>sealed</Word> <Word>static</Word> <Word>virtual</Word> <Word>volatile</Word> </Keywords> <Keywords color="Visibility"> <Word>public</Word> <Word>protected</Word> <Word>private</Word> <Word>internal</Word> </Keywords> <Keywords color="NamespaceKeywords"> <Word>namespace</Word> <Word>using</Word> </Keywords> <Keywords color="GetSetAddRemove"> <Word>get</Word> <Word>set</Word> <Word>add</Word> <Word>remove</Word> </Keywords> <Keywords color="NullOrValueKeywords"> <Word>null</Word> <Word>value</Word> </Keywords> <!-- Mark previous rule--> <Rule color="MethodCall"> \b [\d\w_]+ # an identifier (?=\s*\() # followed by ( </Rule> <!-- Digits --> <Rule color="NumberLiteral"> \b0[xX][0-9a-fA-F]+ # hex number | ( \b\d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent </Rule> <Rule color="Punctuation"> [?,.;()\[\]{}+\-/%*<>^+~!|&]+ </Rule> </RuleSet> </SyntaxDefinition>
<SyntaxDefinition name="C#" extensions=".cs" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008">
其中SyntaxDefinition 这个节点中 name是语言的类型,有C#,Java,Html,ASP/XHTML,JavaScript,CSS等等一些类语言,extension的文件的后缀名,比如C#的文件是以.cs,Java是.java,JavaScript是.js等等,xmlns是命名空间
<Color name="Comment" foreground="Green" exampleText="// comment" />
<Color name="String" foreground="Blue" exampleText="string text = "Hello, World!""/>
<Color name="Char" foreground="Magenta" exampleText="char linefeed = '\n';"/>
<Color name="Keywords" fontWeight="bold" foreground="Red" exampleText="if (a) {} else {}"/>
..............
以上的那些xml节点是C#里的各种类型的关键字,
比如:<Color name="Comment" foreground="Green" exampleText="// comment" />这个是 C#中的 注释,然后所对应的 前景色foreground="Green"为绿色,
<Color name="Keywords" fontWeight="bold" foreground="Red" exampleText="if (a) {} else {}"/> C#中的关键字,字体是bold,前景色为红色,
还有其他类型 :字符,字符串,预处理器,标点符号,方法名,数字,复合关键字,操作,命名空间,修饰符,关键字类型,布尔型常熟,关键字,循环关键字,异常处理,控制流 等等。。
这对应的节点配置了这些类型的颜色,字体类型。
<Span color="Char">
<Begin>'</Begin>
<End>'</End>
<RuleSet>
<!-- span for escape sequences -->
<Span begin="\\" end="."/>
</RuleSet>
</Span>
在这里定义了各个类型的具体实现部分,比如C# 中Char 是以一对单引号 引起来的, 比如 char a = ’A‘;
<Keywords color="TrueFalse">
<Word>true</Word>
<Word>false</Word>
</Keywords>
<Keywords color="Keywords">
<Word>else</Word>
<Word>if</Word>
<Word>switch</Word>
<Word>case</Word>
<Word>default</Word>
<Word>do</Word>
<Word>for</Word>
<Word>foreach</Word>
<Word>in</Word>
<Word>while</Word>
<Word>lock</Word>
<Word>fuck</Word>
</Keywords>
<Keywords color="GotoKeywords">
<Word>break</Word>
<Word>continue</Word>
<Word>goto</Word>
<Word>return</Word>
</Keywords>
这些关键字对应最上面的节点,对应节点里配置好的字体或者颜色,在这些配置文件把颜色修改后重新编译后就可以得到想要的颜色。
在后台修改这些配置文件:
<?xml version="1.0"?> <SyntaxDefinition name="C++" extensions=".c;.h;.cc;.cpp;.hpp"> <FontStyle>微软雅黑</FontStyle> <FontSize>17</FontSize> <BackGround>#FFFFFFFF</BackGround> <Color name="Comment" foreground="#00FFFFFF" fontWeight="bold" displayName="注释" /> <Color name="Character" foreground="#FFFF00FF" displayName="字符" fontWeight="" /> <Color name="String" foreground="#FFFF00FF" displayName="字符串" fontWeight="" /> <Color name="Preprocessor" foreground="#FF0000FF" displayName="预处理器" fontWeight="" /> <Color name="Punctuation" foreground="#FF006400" displayName="标点符号" fontWeight="" /> <Color name="MethodName" foreground="#FF191970" displayName="方法名" fontWeight="" /> <Color name="Digits" foreground="#FF00008B" displayName="数字" fontWeight="" /> <Color name="CompoundKeywords" foreground="#FF000000" displayName="复合关键字" fontWeight="" /> <Color name="This" foreground="#FF000000" displayName="This" fontWeight="normal" /> <Color name="Operators" foreground="#FF008B8B" displayName="操作" fontWeight="" /> <Color name="Namespace" foreground="#FF008000" displayName="命名空间" fontWeight="" /> <Color name="Friend" foreground="#FFA52A2A" displayName="Friend" fontWeight="" /> <Color name="Modifiers" foreground="#FF0000FF" displayName="修饰" fontWeight="" /> <Color name="TypeKeywords" foreground="#FFFF0000" displayName="关键字类型" fontWeight="" /> <Color name="BooleanConstants" foreground="#FF000000" displayName="布尔型常数" fontWeight="" /> <Color name="Keywords" foreground="#00FFFFFF" displayName="关键字" fontWeight="normal" /> <Color name="LoopKeywords" foreground="#FF0000FF" displayName="循环关键字" fontWeight="" /> <Color name="ExceptionHandling" foreground="#FF008080" displayName="异常处理" fontWeight="" /> <Color name="ControlFlow" foreground="#FF0000FF" displayName="控制流" fontWeight="" /> </SyntaxDefinition>
自己新建一个配置文件,里面各个节点写上配置的颜色以及字体
在程序加载时加载这个配置文件,存放到一个List中去,以便在后面修改这里的值
然后在打开一个文本编辑器的时候,给文本编辑器对象的属性赋值:
在AvalonEditViewContent这个类中的public AvalonEditViewContent(OpenedFile file, Encoding fixedEncodingForLoading = null)
这个方法是打开 根据传入的文件的路径 用文本编辑器打开这个文件,并显示出来:
CodeEditor codeEditor = new CodeEditor(); codeEditor.PrimaryTextEditor.FontSize = DBconfigService.fontSize; System.Windows.Media.FontFamily fam = new System.Windows.Media.FontFamily(DBconfigService.fontStyle); codeEditor.PrimaryTextEditor.FontFamily = fam; codeEditor.ActiveTextEditor.FontFamily = fam; Color BGColor = DBconfigService.BGColor; SolidColorBrush br = new System.Windows.Media.SolidColorBrush(BGColor); codeEditor.PrimaryTextEditor.Background = br; System.Collections.Generic.IEnumerable<HighlightingColor> list = codeEditor.PrimaryTextEditor.SyntaxHighlighting.NamedHighlightingColors; System.Collections.Generic.List<HighlightingColor> listColor = list.ToList(); foreach (var item in listColor) { //item.FontSize = DBconfigService.fontSize; foreach (var model in DBconfigService.ListColorFant) { if (model.name == item.Name) { //前景色 Color color = model.foreground; HB b = new HB(new System.Windows.Media.SolidColorBrush(color)); item.Foreground = b; //加粗 FontWeightConverter fec = new FontWeightConverter(); if (string.IsNullOrEmpty(model.fontWeight)) { model.fontWeight = "normal"; } object obj = fec.ConvertFrom(model.fontWeight); FontWeight fontweight = (FontWeight)obj; item.FontWeight = fontweight; } } };
public class HB : HighlightingBrush { System.Windows.Media.SolidColorBrush brush; public HB(System.Windows.Media.SolidColorBrush brush) { brush.Freeze(); this.brush = brush; } public override System.Windows.Media.Brush GetBrush(DhcEc.AvalonEdit.Rendering.ITextRunConstructionContext context) { return brush; } public override string ToString() { return brush.ToString(); } }
在这里可以把配置文件中的值 全部更新到文本编辑器对象的各个属性去,这样就大功告成了!