Basically, the editor is configured so there’s a prefix (readonly) an editable section in the middle, and a suffix (readonly).
I’m struggling quite a bit to re-implement this in CodeMirror 6, since the API is vastly different. I think I should be using something called atomicRanges? I’m going in circles trying to figure out how to get this working though… Any help would be greatly appreciated.
Sorry for posting again, but I thought my final solution here could be useful to someone in the future!
This was significantly more difficult than CodeMirror 5, but I got something that’s working enough. Here’s the result:
EditorState.transactionFilter.of((tr) => {
const from = prefix.length;
const to = tr.newDoc.length - suffix.length;
// check any changes are out of bounds
let oob = false;
tr.changes.iterChanges(
(fromA, toA, fromB, toB, inserted) => (oob = oob || fromB < from || toB > to + inserted.length)
);
if (oob) return [];
// check any selections are out of bounds
const selectionOkay = tr.newSelection.ranges.every((r) => r.from >= from && r.to <= to);
if (selectionOkay) return tr;
// create new selection which is in bounds
const selection = EditorSelection.create(
tr.newSelection.ranges.map((r) => EditorSelection.range(clamp(r.anchor, from, to), clamp(r.head, from, to))),
tr.newSelection.mainIndex
);
return [{ selection }];
})
There’s one edge-case (that I know of) that this doesn’t handle. Originally I wanted a character of whitespace after the prefix and before the suffix, but that can’t work right now.
Consider the following:
// "I" represents the cursor position
//
// prefix is "function foo( "
// suffix is " ) {\n return 1;\n}"
// which means editable range is 0 length right now
function foo( I ) {
return 1;
}
If a newline is inserted in this position, CodeMirror tries to trim the whitespace before the cursor before adding the newline, which is out of bounds and thus is cancelled. I didn’t find a way to fix this.
Also, when it’s setup like this, moving to the far end of the boundary and entering a newline will also cause the selection to go out of bounds… I’m not sure why.
Either way, I’ve spent way too long already just trying to make some sections readonly this is good enough for now.