问题
Using Code Mirror, I need to map change event data to a list of tuples containing:
(Text before change, Change text, Text after change)
I am currently listening on the change
event and can handle input changes, but have to code specific solutions for deletions, selection movements, and undos.
Is there a more reliable approach that works with the standard events?
Edit
Adding current work.
Thinking a bit more, I only care about the first (in terms of position) change in a document. Here is what I currently do:
var docStart = {'line': 0, 'ch': 0},
docEnd = {'line': Infinity, 'ch': Infinity};
// Just assume that we always have a single change and it is first
// for this example.
cm.on('change', function(cm, change) {
var start, end, text; switch (change.origin) {
case '+delete':
start = change.from;
end = change.from;
text = '';
break;
case 'undo':
start = change.from;
end = change.from;
text = change.text.join('\n');
break;
case 'redo':
start = change.from;
end = {'line': change.to.line, 'ch': change.to.ch + 1};
text = '';
break;
default:
start = change.from;
end = {'line': change.to.line, 'ch': change.to.ch + 1};
text = change.text.join('\n');
break;
}
var pre = cm.doc.getRange(docStart, start);
var post = cm.doc.getRange(end, docEnd);
[pre, text, post]; // output
};
This is not correct. Not all event types are handled and many cases like line terminators also are not handled correctly or constantly. An alternative would be greatly appreciated.
回答1:
To get text's before edit, you could use beforeChange event.
Than the text fetching is pretty straightforward.
beforeChange
also has nice property, as it's fired for each change (no chaining as with change
).
cm.on("beforeChange", function (cm, change) {
var before = cm.getRange({ line: 0, ch: 0 }, change.from);
var text = cm.getRange(change.from, change.to);
var after = cm.getRange(change.to, { line: cm.lineCount() + 1, ch: 0 });
console.log("before change", before, text, after);
});
If you need the text after change, than you have to calculate to
in post-change coordinate system. Luckily it's quite easy still:
cm.on("change", function (cm, change) {
var from = change.from;
var text = change.text.join("\n");
var removed = change.removed.join("\n");
var to = cm.posFromIndex(cm.indexFromPos(from) + text.length);
var before = cm.getRange({ line: 0, ch: 0 }, from);
var after = cm.getRange(to, { line: cm.lineCount() + 1, ch: 0 });
console.log("after change", before, removed, text, after);
});
Hopes this works, I hadn't time to test it properly.
来源:https://stackoverflow.com/questions/19744118/code-mirror-get-text-around-changes