Annotating tokens with extra data

TL;DR - I’d like to decorate CM tokens with some compiler-generated information after a parse has been completed.

Use-Case -
After compilation, I have tons of information at my disposal. I know, for example, if a variable has been defined at {line:1, ch:9) and used at {line:6, ch:28}, and I’d like to record the location of the definition inside the token representing the use. If I use markText to permanently change the color of the def/use tokens during annotation, this works perfectly.

However, I’d like this highlighting to happen only when the use token is moused over, meaning I need to store this location information somewhere so that it can be used later. Ideally, I would getTokenAt the current cursor location on mouseOver, and (if present) use the stored defLocation information to mark the use and def until mouseOut.

This information, unfortunately, is wiped (due to re-parse?). Is there is a different approach I could take?

Thanks so much,
Emmanuel

You could encode your information in a string and build a bogus class based on it. That or maintain a side table and somehow track changes to keep your side table locations in sync with the locations in the actual editor.

Ah, good call. I’ve been able to pass data between the compiler and the mouseover handler using your suggestion (I went with the ‘title’ attribute instead):

CodeMirror.defineInitHook(function (cm) {
CodeMirror.on(cm.getWrapperElement(), “mouseover”, function(evt){
var node = evt.target||evt.srcElement;
if(node && node.title){
var indices = node.title.split(","), start = indices[0], end = indices[1];
cm.markText(cm.posFromIndex(start), cm.posFromIndex(end),
{css: “background: lightred”});
}
});

Using some console output, I can confirm that the cm instance being passed in is the correct one, and that the posFromIndex calls are producing the right positions. However, I don’t see the result of the markText call in the editor, even though it shows up via cm.findMarks().

Nope, updates happen automatically. Your call to markText looks good. Maybe double-check that start and end aren’t the same (or are flipped).

Fantastic! Thanks for all your help. I wound up implementing something a little prettier than highlighting, using SVG arrows to point from a use to its definition. Demo available at http://arrows.wescheme.appspot.com/openEditor?publicId=89mvcdxYZ2

Click run, and then mouseover various identifiers in the code.

Relatedly: is there a way to store data besides stuffing it into title or className? I recall seeing some discussion about this in a thread long ago, where you recommended passing unrecognized names (such as ‘_data’) to markText, which could be retrieved later. Unfortunately, this post isn’t turning up for me in any of my searches…so perhaps I dreamed it? :smile:

EDIT: NVM - found it. It’s a pity that I need to do findMarksAt for every mousemove event, when 99% of the time there won’t be any markers. I don’t suppose there’s an optimization opportunity here, is there? Perhaps to allow a marker to respond to mouseovers, and do something clever internally in CM to quickly bail if no markers exist?

You are using markText, as opposed to a mode, to style those tokens? In that case, yes, you can just add any properties you want to the options you pass markText, as long as they don’t conflict with an existing property of a marker, and they’ll appear on the marker object.

Also, don’t worry about calling findMarksAt. Unless you’re doing it on a line with hundreds of markers, it is extremely cheap.

That’s good to know - I wasn’t sure how CM keeps track of markers. Again, I’m just blown away by how easy CM is to work with!