Reputation: 4401
I am trying to develop a simple mode for codemirror. This mode will colour paragraphs alternatively in blue and green. A separation between paragraph is an empty line or a line containing only spaces.
Here is a version of the code that works, but with the big issue that empty lines are not detected:
CodeMirror.defineMode("rt", function() {
return {
startState: function() {return {state1: true};},
token: function(stream, state) {
if (stream.match(/\s\s*/)!=null){ # this fails to detect empty lines
state.state1 = !state.state1;
}
stream.skipToEnd();
if (state.state1) { return "status1"; }
return "status2";
}
};
});
if I apply it to the following text:
line 1
line 2 # the next line is just a backspace and is not detected
line 3
line 4 # the next line is a few spaces followed by a backspace, it is detected
line 5
line 6
it colors from line 1 to line 4 in one color and line 5 to line 6 in another, which is expected.
I am trying to find a way to update my code so that it detects the empty line between line 2 and line 3. Any way to do this ?
Upvotes: 0
Views: 1489
Reputation: 4401
The documentation of codemirror says:
By default, blank lines are simply skipped when tokenizing a document. For languages that have significant blank lines, you can define a blankLine(state) method on your mode that will get called whenever a blank line is passed over, so that it can update the parser state.
(http://codemirror.net/doc/manual.html#modeapi)
The following code works (blankLine function added):
CodeMirror.defineMode("rt", function() {
return {
startState: function() {return {state1: true};},
blankLine: function (state){ state.state1 = !state.state1; },
token: function(stream, state) {
console.log(stream)
if (stream.match(/^\s*$/)!=null){
state.state1 = !state.state1;
}
stream.skipToEnd();
if (state.state1) { return "status1"; }
return "status2";
}
};
});
Upvotes: 2
Reputation: 17381
You can detect backspace with [\b]
in javascript regexp: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
BTW /\s\s*/
can be simplified to /\s+/
however if you want to detect "an empty line or a line containing only spaces", you can use /\s*/
.
Also if you don't care about the actual result array of the regular expression, you can use test()
instead: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
You can use ^
to indicate the beginning of the line and $
for the line end.
So the code will be roughly like this:
CodeMirror.defineMode("rt", function() {
return {
startState: function() {
return {
state1: true
};
},
token: function(stream, state) {
if ( /^\s*$/m.test(stream) ) {
state.state1 = !state.state1;
}
stream.skipToEnd();
return state.state1 ? "status1" : "status2";
}
};
});
The m flag is used to specify that a multiline input string should be treated as multiple lines. If the m flag is used, ^ and $ match at the start or end of any line within the input string instead of the start or end of the entire string. Example: http://www.w3schools.com/jsref/jsref_regexp_m.asp
Upvotes: 2