Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an asynchronous warning source for CodeMirror's lint feature

The examples only show how to implement the JSON and Javascript lint addons with CodeMirror (syntax-highlighting Javascript-based editor), which are synchronous.

Unfortunately, there aren't Javascript-based parsers/lint'ers readily available for most languages. I'd like to implement my own linter for Python. Unfortunately, it seems as if the existing lint addon depends on the linter (which the lint plugin invokes) being synchronous.

angelozerr says that there is a "CodeMirror.remotingValidator" plugin located in remoting-lint.js, but Github show that this file was removed. marijnh says that it was removed because it was "not generally useful", but doesn't clarify any alternatives.

Is there a strategy for, somehow, calling the linter asynchronously, so that I can do an Ajax call in order to parse the code remotely?

like image 407
Dustin Oprea Avatar asked Apr 16 '13 07:04

Dustin Oprea


1 Answers

Sure there is. A quick look through the contents of the last version of remoting-lint.js (https://github.com/marijnh/CodeMirror/commit/27f097ed75561e846bdb955f13f8dd2bcf0b589e) shows that it was little more than a jQuery AJAX request, which invokes a callback provided to the function as a parameter. This callback will only be passed if the "async" option is given to the lint plugin. Note that I have some options being passed-into CodeMirror that may not be relevant to you. The lint-related options are "gutters" and "lintWith".

Note that Python only presents one error at a time, but that the lint addon accepts a list of errors. Because of the former, the latter will only ever have one item, at most.

function python_validator(cm, updateLinting, options) {
    var text = cm.getValue() + "\n";

    if(text.trim() == "")
    {
        updateLinting(cm, []);
        return;
    }

    function result_cb(error)
    {
        var found = [];

        if(error != null) {
            var start_line = error.line_no;
            var start_char = error.column_no;
            var end_line = error.line_no;
            var end_char = error.column_no;
            var message = error.message;

            found.push({
                from: CodeMirror.Pos(start_line - 1, start_char),
                to: CodeMirror.Pos(end_line - 1, end_char),
                message: message
            });
        }

        updateLinting(cm, found);
    }

    check_python_syntax(text, result_cb)
};  

var text_obj = $discriminator_text.get()[0];
var editor = CodeMirror.fromTextArea(text_obj, {
    mode: { name: "python",
            version: 2,
            singleLineStringErrors: false },
    lineNumbers: true,
    indentUnit: 4,
    tabMode: "shift",
    matchBrackets: true,
    styleActiveLine: true,
    lineWrapping: false,
    gutters: ["CodeMirror-lint-markers"],
    lintWith: {
        "getAnnotations": python_validator,
        "async" : true,
    },
});

I've posted a very simple project to make this a little more straightforward: https://github.com/dsoprea/CodeMirrorRemoteValidator

like image 187
Dustin Oprea Avatar answered Oct 22 '22 02:10

Dustin Oprea