Greetings. In the last hour or so, I finally figured out how to partially restrict the user from altering lines of code I don’t want them to touch. My use-case is a JavaScript function’s source code, where the preamble and the return value should be constant. In addition, based on a nearby checkbox, one line of code in this preamble must change.
I’ve wanted functionality like this for years. (I’m currently using CodeMirror 5.25.2, but release notes up to 5.32 seem to indicate this hasn’t been added.)
Since I’m not sure if this would qualify as a “bug” or not per the guidelines, and I only have the raw code I used to do this, I figured I’d start here and see if there’s interest in folding something like this into CodeMirror itself.
Here’s the code:
/** * Mark CodeMirror lines "read-only", and get a function that can alter them. * * @param editor {CodeMirror} The editor. * @param startLine {Integer} The line index to start at. * @param endLine {Integer} The line index to end at. * * @returns {Function(String)} A callback for replacing read-only content. * * @note CodeMirror uses zero-based indexes for the API, and one-based indexes * for the rendering: the first line appears in gutters as line 1, but in the * API, it is line 0. */ getTextLock: function(editor, startLine, endLine) { const doc = editor.getDoc(); const options = Object.freeze({ readOnly: true, className: "readOnly" }); let mark = doc.markText( {line: startLine, ch: 0}, {line: endLine, ch: 0}, options ); return function(newText) { if (typeof newText !== "string") throw new Error("text lock only allows replacements with strings"); if (newText[newText.length - 1] !== "\n") newText += "\n"; const positioning = mark.find(); mark.clear(); doc.replaceRange(newText, positioning.from, positioning.to); startLine = positioning.from.line; endLine = startLine + newText.split("\n").length - 1; mark = doc.markText( {line: startLine, ch: 0}, {line: endLine, ch: 0}, options ); }; },
Unfortunately, I haven’t figured out how to prevent the user from appending to the very end of the CodeMirror instance, by simply using the Enter key at the end of the editor’s content.