如何使用自定义模式在Ace Editor中集成语法检查?

时间:2015-06-22 07:45:26

标签: jshint ace-editor

我是ace-editor的新手,我已经包含自定义模式来验证我的代码,每行都应该以分号结束。如果我的查询中没有分号,那么编辑应该放弃警告,如“缺少分号“。

define('ace/mode/javascript-custom', [], function(require, exports, module) {

  var oop = require("ace/lib/oop");
  var TextMode = require("ace/mode/text").Mode;
  var Tokenizer = require("ace/tokenizer").Tokenizer;
  var ExampleHighlightRules = require("ace/mode/example_highlight_rules").ExampleHighlightRules;

  var Mode = function() {
    this.HighlightRules = ExampleHighlightRules;
  };
  oop.inherits(Mode, TextMode);

  (function() {
    this.lineCommentStart = "--";
    this.blockComment = {
      start: "->",
      end: "<-"
    };
  }).call(Mode.prototype);

  exports.Mode = Mode;
});

define('ace/mode/example_highlight_rules', [], function(require, exports, module) {
  var oop = require("ace/lib/oop");
  var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;

  var ExampleHighlightRules = function() {

    var keywordMapper = this.createKeywordMapper({
      "variable.language": "this",
      "keyword": "one|two",
      "constant.language": "true|false|null"
    }, "text", true);

    this.$rules = {
      "start": [{
        token: "comment",
        regex: "->",
        next: [{
          regex: "<-",
          token: "comment",
          next: "start"
        }, {
          defaultToken: "comment"
        }]
      }, {
        regex: "\\w+\\b",
        token: keywordMapper
      }, {
        token: "comment",
        regex: "--.*"
      }, {
        token: "string",
        regex: '"',
        next: [{
          regex: /\\./,
          token: "escape.character"
        }, {
          regex: '"',
          token: "string",
          next: "start"
        }, {
          defaultToken: "string"
        }]
      }, {
        token: "numbers",
        regex: /\d+(?:[.](\d)*)?|[.]\d+/
      }]
    };
    this.normalizeRules()
  };

  oop.inherits(ExampleHighlightRules, TextHighlightRules);

  exports.ExampleHighlightRules = ExampleHighlightRules;

});

var langTools = ace.require("ace/ext/language_tools");
var editor = ace.edit("editor");

editor.session.setMode("ace/mode/javascript-custom");
editor.setOptions({
  enableBasicAutocompletion: true,
  enableLiveAutocompletion: true
});
editor.setTheme("ace/theme/monokai");
var lines = editor.session.doc.getAllLines();
var errors = [];

for (var i = 0; i < lines.length; i++) {
  if (/[\w\d{(['"]/.test(lines[i])) {
    alert("hello");
    errors.push({
      row: i,
      column: lines[i].length,
      text: "Missing Semicolon",
      type: "error"
    });
  }
}
<script src="https://ajaxorg.github.io/ace-builds/src/ext-language_tools.js"></script>
<script src="https://ajaxorg.github.io/ace-builds/src/ace.js"></script>
<div id="editor" style="height: 200px; width: 400px"></div>
<div id="commandline" style="position: absolute; bottom: 10px; height: 20px; width: 800px;"></div>

更新

以下js文件是从ace生成并添加到我的rails应用程序中的,文件是在rails应用程序中加载的,但功能(分号检查)似乎不起作用。

worker-semicolonlineend - http://pastebin.com/2kZ2fYr9 mode-semicolonlineend - http://pastebin.com/eBY5VvNK

更新

  1. 在ace编辑器中,分别在第1行和第2行输入query1,query2
  2. 将第三行留空
  3. 现在在第四行,输入最后没有分号的查询,x标记出现在第三行 5当第五行也没有分号时,x标记显示在第四个查询
  4. enter image description here

1 个答案:

答案 0 :(得分:3)

Ace编辑器默认支持JavaScript的这种分析:

&#13;
&#13;
#editor {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
&#13;
<div id="editor">function foo() { ; // unnessesary semicolon
    var x = "bar" // missing semicolon 
    return x; // semicolon in place
}
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript"></script>
<script>
 var editor = ace.edit("editor");
 editor.setTheme("ace/theme/monokai");
 editor.getSession().setMode("ace/mode/javascript");
</script>
&#13;
&#13;
&#13;

只需确保您的代码可以使用工作文件worker-javascript.js。在上面的代码片段中,我使用CDN来获取Ace版本,因此worker始终可用。您可以配置JSHint via worker options

更新但如果确实需要更多内容,则需要按照我的理解进行以下操作:

  1. Create Worker and Mode为您提供分析
  2. 下载Ace source code并安装NodeJS
  3. 将您的新文件放在相应的Ace源代码文件夹
  4. Build Ace
  5. 将构建文件添加到项目中
  6. 使用新模式:editor.getSession().setMode("ace/mode/semicolonlineend");
  7. 执行行结束检查的工作人员将看起来像这样:

    define(function(require, exports, module) {
    "use strict";
    
    var oop = require("../lib/oop");
    var Mirror = require("../worker/mirror").Mirror;
    
    var SemicolonLineEndCheckWorker = exports.SemicolonLineEndCheckWorker = function (sender) {
        Mirror.call(this, sender);
        this.setTimeout(500);
        this.setOptions();
    };
    
    oop.inherits(SemicolonLineEndCheckWorker, Mirror);
    
    (function() {
    
        this.onUpdate = function () {
            var text = this.doc.getValue();
            var lines = text.replace(/^#!.*\n/, "\n").match(/[^\r\n]+/g);
    
            var errors = [];
    
            for (var i = 0; i < lines.length; i++) {
                var lastLineCharacter = lines[i].trim().slice(-1);
                if (lastLineCharacter === ';')
                    continue;
    
                errors.push({
                    row: i,
                    column: lines[i].length-1,
                    text: "Missing semicolon at the end of the line",
                    type: "warning",
                    raw: "Missing semicolon"
                });
    
            }
    
            this.sender.emit("annotate", errors);
        };
    
    }).call(SemicolonLineEndCheckWorker.prototype);
    
    });
    

    使用worker的新模式:

    define(function(require, exports, module) {
    "use strict";
    
    var oop = require("../lib/oop");
    var TextMode = require("./text").Mode;
    
    var Mode = function() { };
    oop.inherits(Mode, TextMode);
    
    (function() {
    
        this.createWorker = function(session) {
            var worker = new WorkerClient(["ace"], "ace/mode/semicolonlineend_worker", 
                "SemicolonLineEndCheckWorker");
            worker.attachToDocument(session.getDocument());
    
            worker.on("annotate", function(results) {
                session.setAnnotations(results.data);
            });
    
            worker.on("terminate", function() {
                session.clearAnnotations();
            });
    
            return worker;
        };
    
        this.$id = "ace/mode/semicolonlineend";
    }).call(Mode.prototype);
    
    exports.Mode = Mode;
    });