1. 程式人生 > >PCB 規則引擎之編輯器(語法著色,錯誤提示,程式碼格式化)

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;[email protected]%^*()-+=|\#/{}[]:;"' ,    .?</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;[email protected]%^*()-+=|\#/{}[]:;"' ,    .?</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;[email protected]%^*()-+=|\#/{}[]:;"' ,    .?</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 + "\r\n錯誤定位程式碼\r\n" + ErrCode.ToString().Trim(); ;
                    }
                }
                MessageBox.Show("報錯內容:\r\n" + 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('\n');
            foreach (var line in lines)
            {
                if (line.TrimStart().StartsWith("{") || line.TrimEnd().EndsWith("{"))
                {
                    sb.Append(Indent(count * times) + line.TrimStart() + "\r\n");
                    times++;

                }
                else if (line.TrimStart().StartsWith("}"))
                {
                    times--;
                    if (times <= 0)
                    {
                        times = 0;
                    }
                    sb.Append(Indent(count * times) + line.TrimStart() + "\r\n");
                }
                else
                {
                    sb.Append(Indent(count * times) + line.TrimStart() + "\r\n");
                }
            }
            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.ActiveText