I'm trying to use CodeMirror (http://codemirror.net/) as a basic text editor with some extra functionalities. One of them is highlighting specific words or groups of words as specified by their positions in the original string. I have an external structure storing the list of substring positions I want to highlight. This structure is an Array where each element represents a text line and contains an array of objects with the positions of the substring to be highlighted. As an example, I have this text string:
The moon
is pale and round
as is
also the sun
The words to be highlighted are "moon", "pale", "round" and "sun". Thus, the highlighting structure is like this:
[
[ { iStart:4, iEnd:7 } ], // "moon"
[ { iStart:3, iEnd:6 }, { iStart:12, iEnd:16 } ], // "pale" and "round"
[],
[ { iStart:9, iEnd:11 } ] // "sun"
]
In order to achieve this, I first tried writing a custom language mode but was not successful (mainly because I didn't know how to manage the fact that CodeMirror seems to use tokens, not lines, and I obviously need to know the line where the current token is located so as to retrieve the right data from the highlight structure).
Then I tried writing an external function that applies the highlighting by just adding SPAN tags manually, like this:
function highlightText()
{
console.log( "highlightText()" );
// Get a reference to the text lines in the code editor
var codeLines = $("#editorContainer .CodeMirror-code pre>span" );
for( var i=0; i<colorSegments.length; i++ ){
// If there's text to be highlighted in this line...
if( colorSegments[i] && colorSegments[i].length > 0 ){
// Get the right element and do so
var lineElement = codeLines[i];
highlightWordsInLine( lineElement, colorSegments[i] );
}
}
}
function highlightWordsInLine(element, positions) {
// Get the raw text
var str = $( element ).text();
// Build a new string with highlighting tags.
// Start
var out = str.substr(0, positions[0].iStart);
for( var j=0; j<positions.length; j++ ){
var position = positions[j];
// Apply the highlighting tag
out += '<span class="cm-s-ambiance cm-relation">';
out += str.substr( position.iStart, position.iEnd - position.iStart + 1);
out += '</span>';
// Do not forget to incluide unhighlighted text in between
if( j < positions.length-1 ){
out += str.substr( position.iEnd - position.iStart + 1, positions[j+1].iStart );
}
}
// Wrap up to end of line
out += str.substr( position.iEnd + 1);
// Reset the html element value including applied highlight tags
element.innerHTML = out;
}
I understand this is a quite dirty approach, and it actually doesn't work 100% since some of the text in the code editor becomes unselectable and other bugs, but at least I got some success at controlling the highlighting.
So my question is, what's the right way to do this? If I should stick to the language-mode approach, how would I do it?
I've also been suggested to give a look to Ace (http://ace.c9.io/#nav=higlighter), but it doesn't look like it would support handling highlighting based on string positions instead of keyword lists or regexp rules.
Thanks in advance.