• PCB 规则引擎之编辑器(语法着色,错误提示,代码格式化)


    对于一个规则引擎中的脚本代码编辑器是非常关键的,因为UI控件直接使用对象是规则维护者,关系到用户体验,在选用脚本编辑器的功能时除了满足代码的编辑的基本编辑要求外,功能还需要包含;语法着色,错误提示,代码格式化,代码折叠,自动代码提示,自动补全代码等功能.(目前技术无法做到JS加断点;边调试边运行)

    经过众多开源产品的代码编辑器对比与功能测试,ICSharpCode.TextEditor 是JS脚本编辑器最佳选择. 

     

    一.语法着色

        JS语法着色XML,对JS关键字进行着色,并可以扩展自指定义关键字着色,

        应用场影:规则引擎中新增加函数或变量等关键字时, 为用户体验更好,可增加自定义关键字着色;

                  例:BoardThick 是关键字,那么在JS代码中,以高亮着色加以区分

                       

    <?xml version="1.0"?>
    <!-- syntaxdefinition for JavaScript 2.0 by Svante Lidman -->
    
    <SyntaxDefinition name ="JavaScript" extensions = ".js">
        
        <Properties>
            <Property name="LineComment" value="//"/>
        </Properties>
    
        <Digits name ="Digits" bold ="false" italic ="false" color ="DarkBlue"/>
    
        <RuleSets>
            <RuleSet ignorecase = "false">
                <Delimiters>=!&gt;&lt;+-/*%&amp;|^~.}{,;][?:</Delimiters>
                
                <Span name ="LineComment" bold ="false" italic ="false" color ="DarkSlateGray" stopateol ="true">
                    <Begin>//</Begin>
                </Span>
                        
                <Span name ="BlockComment" bold ="false" italic ="false" color ="DarkSlateGray" stopateol ="false">
                    <Begin>/*</Begin>
                    <End>*/</End>
                </Span>
                
                <Span name ="String" bold ="false" italic ="false" color ="Sienna" stopateol ="false" escapecharacter="">
                    <Begin>&quot;</Begin>
                    <End>&quot;</End>
                </Span>
        
                <Span name = "Character" bold = "false" italic = "false" color = "Sienna" stopateol = "true" escapecharacter="">
                    <Begin>&apos;</Begin>
                    <End>&apos;</End>
                </Span>
        
                <KeyWords name ="JavaScriptKeyWords" bold="false" italic = "false" color = "Blue">
                    <Key word =  "break" />
                    <Key word =  "continue" />
                    <Key word =  "delete" />
                    <Key word =  "else" />
                    <Key word =  "for" />
                    <Key word =  "function" />
                    <Key word =  "if" />
                    <Key word =  "in" />
                    <Key word =  "new" />
                    <Key word =  "return" />
                    <Key word =  "this" />
                    <Key word =  "typeof" />
                    <Key word =  "var" />
                    <Key word =  "void" />
                    <Key word =  "while" />
                    <Key word =  "with" />
                    <!--ECMAScript keywords-->
                    <!-- Reserved for future use 
                        (some are already used in some Javascript Engines) 
                    -->
                    <Key word =  "abstract" />
                    <Key word =  "boolean" />
                    <Key word =  "byte" />
                    <Key word =  "case" />
                    <Key word =  "catch" />
                    <Key word =  "char" />
                    <Key word =  "class" />
                    <Key word =  "const" />
                    <Key word =  "debugger" />
                    <Key word =  "default" />
                    <Key word =  "do" />
                    <Key word =  "double" />
                    <Key word =  "enum" />
                    <Key word =  "export" />
                    <Key word =  "extends" />
                    <Key word =  "final" />
                    <Key word =  "finally" />
                    <Key word =  "float" />
                    <Key word =  "goto" />
                    <Key word =  "implements" />
                    <Key word =  "import" />
                    <Key word =  "instanceof" />
                    <Key word =  "int" />
                    <Key word =  "interface" />
                    <Key word =  "long" />
                    <Key word =  "native" />
                    <Key word =  "package" />
                    <Key word =  "private" />
                    <Key word =  "protected" />
                    <Key word =  "public" />
                    <Key word =  "short" />
                    <Key word =  "static" />
                    <Key word =  "super" />
                    <Key word =  "switch" />
                    <Key word =  "synchronized" />
                    <Key word =  "throw" />
                    <Key word =  "throws" />
                    <Key word =  "transient" />
                    <Key word =  "try" />
                    <Key word =  "volatile" />
                </KeyWords>
        
                <KeyWords name ="JavaScriptIntrinsics" bold="false" italic = "false" color = "Blue">
                    <Key word =  "Array" />
                    <Key word =  "Boolean" />
                    <Key word =  "Date" />
                    <Key word =  "Function" />
                    <Key word =  "Global" />
                    <Key word =  "Math" />
                    <Key word =  "Number" />
                    <Key word =  "Object" />
                    <Key word =  "RegExp" />
                    <Key word =  "String" />
                </KeyWords>
                
                <KeyWords name ="JavaScriptLiterals" bold="false" italic = "false" color = "Blue">
                    <Key word =  "false" />
                    <Key word =  "null" />
                    <Key word =  "true" />
                    <Key word =  "NaN" />
                    <Key word =  "Infinity" />
                </KeyWords>
        
                <KeyWords name ="JavaScriptLiterals" bold="false" italic = "false" color = "Blue">
                    <Key word =  "" />
                </KeyWords>
        
                <KeyWords name ="JavaScriptGlobalFunctions" bold="false" italic = "false" color = "Blue">
                    <Key word =  "eval" />
                    <Key word =  "parseInt" />
                    <Key word =  "parseFloat" />
                    <Key word =  "escape" />
                    <Key word =  "unescape" />
                    <Key word =  "isNaN" />
                    <Key word =  "isFinite" />
                </KeyWords>
    
          <KeyWords name ="JavaScriptUserFunctions" bold="false" italic = "false" color = "Blue">
            <Key word =  "console" />
            <Key word =  "JSON" />
            <Key word =  "console.log" />
            <Key word =  "console.alert" />
            <Key word =  "console.prompt" />
            <Key word =  "console.print" />
          </KeyWords>
          
          
        </RuleSet>
        </RuleSets>
        
    </SyntaxDefinition>
    View Code

      

       再来一个C#语法着色 XML供参考

    <?xml version="1.0"?>
    <!-- syntaxdefinition for C# 2000 by Mike Krueger -->
    
    <SyntaxDefinition name = "C#" extensions = ".cs">
        
        <Environment>
            <Custom name="TypeReference" bold="false" italic="false" color="#04ABAB" />
            <Custom name="UnknownEntity" bold="false" italic="false" color="#AB0404" />
        </Environment>
        
        <Properties>
            <Property name="LineComment" value="//"/>
        </Properties>
        
        <Digits name = "Digits" bold = "false" italic = "false" color = "DarkBlue"/>
        
        <RuleSets>
            <RuleSet ignorecase="false">
                <Delimiters>&amp;&lt;&gt;~!%^*()-+=|#/{}[]:;"' ,    .?</Delimiters>
                
                <Span name = "PreprocessorDirectives" rule = "PreprocessorSet" bold="false" italic="false" color="Green" stopateol = "true">
                    <Begin>#</Begin>
                </Span>
                
                <Span name = "DocLineComment" rule = "DocCommentSet" bold = "false" italic = "false" color = "Green" stopateol = "true" noescapesequences="true">
                    <Begin bold = "false" italic = "false" color = "Gray">///@!/@</Begin>
                </Span>
                
                <Span name = "LineComment" rule = "CommentMarkerSet" bold = "false" italic = "false" color = "Green" stopateol = "true">
                    <Begin>//@!/@</Begin>
                </Span>
                <Span name = "LineComment2" rule = "CommentMarkerSet" bold = "false" italic = "false" color = "Green" stopateol = "true">
                    <Begin>////</Begin>
                </Span>
                
                <Span name = "BlockComment" rule = "CommentMarkerSet" bold = "false" italic = "false" color = "Green" stopateol = "false">
                    <Begin>/*</Begin>
                    <End>*/</End>
                </Span>
                
                <Span name = "String" bold = "false" italic = "false" color = "Blue" stopateol = "true" escapecharacter="">
                    <Begin>"</Begin>
                    <End>"</End>
                </Span>
                
                <Span name = "MultiLineString" bold = "false" italic = "false" color = "Blue" stopateol = "false" escapecharacter='"'>
                    <Begin>@@"</Begin>
                    <End>"</End>
                </Span>
                
                <Span name = "Char" bold = "false" italic = "false" color = "Magenta" stopateol = "true" escapecharacter="">
                    <Begin>&apos;</Begin>
                    <End>&apos;</End>
                </Span>
                
                <MarkPrevious bold = "true" italic = "false" color = "MidnightBlue">(</MarkPrevious>
                
                <KeyWords name = "Punctuation" bold = "false" italic = "false" color = "DarkGreen">
                    <Key word = "?" />
                    <Key word = "," />
                    <Key word = "." />
                    <Key word = ";" />
                    <Key word = "(" />
                    <Key word = ")" />
                    <Key word = "[" />
                    <Key word = "]" />
                    <Key word = "{" />
                    <Key word = "}" />
                    <Key word = "+" />
                    <Key word = "-" />
                    <Key word = "/" />
                    <Key word = "%" />
                    <Key word = "*" />
                    <Key word = "&lt;" />
                    <Key word = "&gt;" />
                    <Key word = "^" />
                    <Key word = "=" />
                    <Key word = "~" />
                    <Key word = "!" />
                    <Key word = "|" />
                    <Key word = "&amp;" />
                </KeyWords>
                
                <KeyWords name = "AccessKeywords" bold="true" italic="false" color="Black">
                    <Key word = "this" />
                    <Key word = "base" />
                </KeyWords>
                
                <KeyWords name = "OperatorKeywords" bold="true" italic="false" color="DarkCyan">
                    <Key word = "as" />
                    <Key word = "is" />
                    <Key word = "new" />
                    <Key word = "sizeof" />
                    <Key word = "typeof" />
                    <Key word = "true" />
                    <Key word = "false" />
                    <Key word = "stackalloc" />
                </KeyWords>
                
                
                <KeyWords name = "SelectionStatements" bold="true" italic="false" color="Blue">
                    <Key word = "else" />
                    <Key word = "if" />
                    <Key word = "switch" />
                    <Key word = "case" />
                    <Key word = "default" />
                </KeyWords>
                
                <KeyWords name = "IterationStatements" bold="true" italic="false" color="Blue">
                    <Key word = "do" />
                    <Key word = "for" />
                    <Key word = "foreach" />
                    <Key word = "in" />
                    <Key word = "while" />
                </KeyWords>
                
                <KeyWords name = "JumpStatements" bold="false" italic="false" color="Navy">
                    <Key word = "break" />
                    <Key word = "continue" />
                    <Key word = "goto" />
                    <Key word = "return" />
                </KeyWords>
                
                <KeyWords name = "ContextKeywords" bold="false" italic="false" color="Navy">
                    <Key word = "yield" />
                    <Key word = "partial" />
                    <Key word = "global" />
                    <Key word = "where" />
                    <Key word = "select" />
                    <Key word = "group" />
                    <Key word = "by" />
                    <Key word = "into" />
                    <Key word = "from" />
                    <Key word = "ascending" />
                    <Key word = "descending" />
                    <Key word = "orderby" />
                    <Key word = "let" />
                    <Key word = "join" />
                    <Key word = "on" />
                    <Key word = "equals" />
                    <Key word = "var" />
                </KeyWords>
                
                <KeyWords name = "ExceptionHandlingStatements" bold="true" italic="false" color="Teal">
                    <Key word = "try" />
                    <Key word = "throw" />
                    <Key word = "catch" />
                    <Key word = "finally" />
                </KeyWords>
                
                <KeyWords name = "CheckedUncheckedStatements" bold="true" italic="false" color="DarkGray">
                    <Key word = "checked" />
                    <Key word = "unchecked" />
                </KeyWords>
                
                <KeyWords name = "UnsafeFixedStatements" bold="false" italic="false" color="Olive">
                    <Key word = "fixed" />
                    <Key word = "unsafe" />
                </KeyWords>
                
                <KeyWords name = "ValueTypes" bold="true" italic="false" color="Red">
                    <Key word = "bool" />
                    <Key word = "byte" />
                    <Key word = "char" />
                    <Key word = "decimal" />
                    <Key word = "double" />
                    <Key word = "enum" />
                    <Key word = "float" />
                    <Key word = "int" />
                    <Key word = "long" />
                    <Key word = "sbyte" />
                    <Key word = "short" />
                    <Key word = "struct" />
                    <Key word = "uint" />
                    <Key word = "ushort" />
                    <Key word = "ulong" />
                </KeyWords>
                
                <KeyWords name = "ReferenceTypes" bold="false" italic="false" color="Red">
                    <Key word = "class" />
                    <Key word = "interface" />
                    <Key word = "delegate" />
                    <Key word = "object" />
                    <Key word = "string" />
                </KeyWords>
                
                <KeyWords name = "Void" bold="false" italic="false" color="Red">
                    <Key word = "void" />
                </KeyWords>
                
                <KeyWords name = "ConversionKeyWords" bold="true" italic="false" color="Pink">
                    <Key word = "explicit" />
                    <Key word = "implicit" />
                    <Key word = "operator" />
                </KeyWords>
                
                <KeyWords name = "MethodParameters" bold="true" italic="false" color="DeepPink">
                    <Key word = "params" />
                    <Key word = "ref" />
                    <Key word = "out" />
                </KeyWords>
                
                <KeyWords name = "Modifiers" bold="false" italic="false" color="Brown">
                    <Key word = "abstract" />
                    <Key word = "const" />
                    <Key word = "event" />
                    <Key word = "extern" />
                    <Key word = "override" />
                    <Key word = "readonly" />
                    <Key word = "sealed" />
                    <Key word = "static" />
                    <Key word = "virtual" />
                    <Key word = "volatile" />
                </KeyWords>
                
                <KeyWords name = "AccessModifiers" bold="true" italic="false" color="Blue">
                    <Key word = "public" />
                    <Key word = "protected" />
                    <Key word = "private" />
                    <Key word = "internal" />
                </KeyWords>
                
                <KeyWords name = "NameSpaces" bold="true" italic="false" color="Green">
                    <Key word = "namespace" />
                    <Key word = "using" />
                </KeyWords>
                
                <KeyWords name = "LockKeyWord" bold="false" italic="false" color="DarkViolet">
                    <Key word = "lock" />
                </KeyWords>
                
                <KeyWords name = "GetSet" bold="false" italic="false" color="SaddleBrown">
                    <Key word = "get" />
                    <Key word = "set" />
                    <Key word = "add" />
                    <Key word = "remove" />
                </KeyWords>
                
                <KeyWords name = "Literals" bold="true" italic="false" color="Black">
                    <Key word = "null" />
                    <Key word = "value" />
                </KeyWords>
            </RuleSet>
            
            <RuleSet name = "CommentMarkerSet" ignorecase = "false">
                <Delimiters>&lt;&gt;~!@%^*()-+=|#/{}[]:;"' ,    .?</Delimiters>
                <KeyWords name = "ErrorWords" bold="true" italic="false" color="Red">
                    <Key word = "TODO" />
                    <Key word = "FIXME" />
                </KeyWords>
                <KeyWords name = "WarningWords" bold="true" italic="false" color="#EEE0E000">
                    <Key word = "HACK" />
                    <Key word = "UNDONE" />
                </KeyWords>
            </RuleSet>
            
            <RuleSet name = "DocCommentSet" ignorecase = "false">
                <Delimiters>&lt;&gt;~!@%^*()-+=|#/{}[]:;"' ,    .?</Delimiters>
                
                <Span name = "XmlTag" rule = "XmlDocSet" bold = "false" italic = "false" color = "Gray" stopateol = "true">
                    <Begin>&lt;</Begin>
                    <End>&gt;</End>
                </Span>
                
                <KeyWords name = "ErrorWords" bold="true" italic="false" color="Red">
                    <Key word = "TODO" />
                    <Key word = "FIXME" />
                </KeyWords>
                
                <KeyWords name = "WarningWords" bold="true" italic="false" color="#EEE0E000">
                    <Key word = "HACK" />
                    <Key word = "UNDONE" />
                </KeyWords>
            </RuleSet>
            
            <RuleSet name = "PreprocessorSet" ignorecase="false">
                <Delimiters>&amp;&lt;&gt;~!%^*()-+=|#/{}[]:;"' ,    .?</Delimiters>
                
                <KeyWords name = "PreprocessorDirectives" bold="true" italic="false" color="Green">
                    <Key word = "if" />
                    <Key word = "else" />
                    <Key word = "elif" />
                    <Key word = "endif" />
                    <Key word = "define" />
                    <Key word = "undef" />
                    <Key word = "warning" />
                    <Key word = "error" />
                    <Key word = "line" />
                    <Key word = "region" />
                    <Key word = "endregion" />
                    <Key word = "pragma" />
                </KeyWords>
            </RuleSet>
            
            <RuleSet name = "XmlDocSet" ignorecase = "false">
                <Delimiters>&lt;&gt;~!@%^*()-+=|#/{}[]:;"' ,    .?</Delimiters>
                
                <Span name = "String" bold = "true" italic = "false" color = "Silver" stopateol = "true">
                    <Begin>"</Begin>
                    <End>"</End>
                </Span>
                
                
                <KeyWords name = "Punctuation" bold = "true" italic = "false" color = "Gray">
                    <Key word = "/" />
                    <Key word = "|" />
                    <Key word = "=" />
                </KeyWords>
                
                <KeyWords name = "SpecialComment" bold="true" italic="false" color="Gray">
                    <Key word = "c" />
                    <Key word = "code" />
                    <Key word = "example" />
                    <Key word = "exception" />
                    <Key word = "list" />
                    <Key word = "para" />
                    <Key word = "param" />
                    <Key word = "paramref" />
                    <Key word = "permission" />
                    <Key word = "remarks" />
                    <Key word = "returns" />
                    <Key word = "see" />
                    <Key word = "seealso" />
                    <Key word = "summary" />
                    <Key word = "value" />
                    <Key word = "inheritdoc" />
                    
                    <Key word = "type" />
                    <Key word = "name" />
                    <Key word = "cref" />
                    <Key word = "item" />
                    <Key word = "term" />
                    <Key word = "description" />
                    <Key word = "listheader" />
                </KeyWords>
            </RuleSet>
        </RuleSets>
    </SyntaxDefinition>
    View Code

    二.错误提示

           在测试JS代码时,点击运行JS,当报错时直接定位执行JS代码的异常代码.

         

                string result = "";
                string resultType = "";
                try
                {
                    var resultJS = context.Run(jsCode);
                    if (resultJS == null)
                    {
                        result = "null";
                        resultType = "null";
                    }
                    else
                    {
                        resultType = resultJS.GetType().ToString();
                        result = Newtonsoft.Json.JsonConvert.SerializeObject(resultJS);
                    }
                }
                catch (Exception ex)
                {
                    string CodeLine = "";
                    if (ex.Data.Contains("V8SourceLine"))
                    {
                        var ErrCode = ex.Data["V8SourceLine"];
                        if (ErrCode != null)
                        {
                            CodeLine = CodeLine + "
    错误定位代码
    " + ErrCode.ToString().Trim(); ;
                        }
                    }
                    MessageBox.Show("报错内容:
    " + ex.Message + CodeLine, "JavaScript提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
    View Code

    三.代码格式化

        ICSharpCode.TextEditor 控件中没有现成的,这里跟据{}扩号,多层嵌套加首空格的方式进行代码格式化功能

        

           /// <summary>
            /// 格式化JS代码
            /// </summary>
            /// <param name="code"></param>
            /// <returns></returns>
            public static string FormatJSCode(string code)
            {
                //去除空白行
                code = RemoveEmptyLines(code);
                StringBuilder sb = new StringBuilder();
                int count = 2;
                int times = 0;
                string[] lines = code.Split('
    ');
                foreach (var line in lines)
                {
                    if (line.TrimStart().StartsWith("{") || line.TrimEnd().EndsWith("{"))
                    {
                        sb.Append(Indent(count * times) + line.TrimStart() + "
    ");
                        times++;
    
                    }
                    else if (line.TrimStart().StartsWith("}"))
                    {
                        times--;
                        if (times <= 0)
                        {
                            times = 0;
                        }
                        sb.Append(Indent(count * times) + line.TrimStart() + "
    ");
                    }
                    else
                    {
                        sb.Append(Indent(count * times) + line.TrimStart() + "
    ");
                    }
                }
                return sb.ToString();
            }
    View Code

    四.补全扩号{} ()[]

         当用户敲左扩号时,自动补充右扩号,并将光标点移到2个扩号中间. 

           private void txtContent_TextChanged(object sender, EventArgs e)
            {
                txtContent.Document.FoldingManager.UpdateFoldings(null, null);
                if (txtContent.Text.Length <= oldJScodeLength) return;
                var Line = this.txtContent.ActiveTextAreaControl.Caret.Line;
                var offset = this.txtContent.ActiveTextAreaControl.Caret.Offset;
                if (offset == 0) return;
                var LineSegment = txtContent.ActiveTextAreaControl.TextArea.Document.GetLineSegment(Line);
                if (offset == LineSegment.Length) return;
                try
                {
                    var charT = txtContent.ActiveTextAreaControl.TextArea.Document.GetText(offset, 1);
                    var charE = "";
                    switch (charT)
                    {
                        case "{" :
                            charE = "}";
                            break;
                        case "(":
                            charE = ")";
                            break;
                        case "[":
                            charE = "]";
                            break;
                    }
                    if (!string.IsNullOrEmpty(charE))
                    {
                        txtContent.ActiveTextAreaControl.SelectionManager.RemoveSelectedText();
                        txtContent.ActiveTextAreaControl.Caret.Column = txtContent.ActiveTextAreaControl.Caret.Column + 1;
                        txtContent.ActiveTextAreaControl.TextArea.InsertChar(charE[0]);
                        txtContent.ActiveTextAreaControl.Caret.Column = txtContent.ActiveTextAreaControl.Caret.Column - 2;
                        this.txtContent.ActiveTextAreaControl.TextArea.ScrollToCaret();
                    }
                }
                catch (Exception)
                {
    
    
                }
            }
    View Code

    五. 当前光标信息

          当前光标所在行,列,所选字符数,基本功能扩展,

        

            private void JSPositionChanged(object sender, EventArgs e)
            {
                ICSharpCode.TextEditor.Caret CaretPosition = (ICSharpCode.TextEditor.Caret)sender;
                toolStripStatusLabel1.Text = $@"行:{CaretPosition.Line + 1}  列:{CaretPosition.Column + 1} 偏移:{CaretPosition.Offset + 1}";
                toolStripStatusLabel3.Text = CaretPosition.CaretMode.ToString();
            }
    
            private void JSSelectionChanged(object sender, EventArgs e)
            {
                SelectionManager selContent = (SelectionManager)sender;
                toolStripStatusLabel2.Text = $@"选中字符数:{selContent.SelectedText.Length}";
                btnRunJSselect.Enabled = selContent.SelectedText.Length > 0;
            }
    View Code
  • 相关阅读:
    1074 食物链 (并查集)
    2832 6个朋友
    病毒 (拓扑)
    4735 烦人的幻灯片 (拓扑)
    JavaScript中变量的LHS引述和RHS引用
    td自动换行
    SQL Server 中的 NOLOCK 到底是什么意思?
    jQuery中遇到的坑
    jQuery中attr()函数 VS prop()函数
    Javascript刷新页面的几种方法
  • 原文地址:https://www.cnblogs.com/pcbren/p/9721528.html
Copyright © 2020-2023  润新知