23

I'm trying to configure the Monaco Editor in a way that certain regions of the textcontent are readonly. More precise, I want the first and last line to be readonly. Example below:

public something(someArgument) { // This is readonly
// This is where the user can put his code
// more user code...
} // readonly again

I already did something similar with the Ace Editor but I can't figure out a way to do this with Monaco. There is a ModelContentChangedEvent that you can register a listener on but it's fired after the change happened (so too late to prevent anything). Does someone with more experience with Monaco got a idea how to do this?

Thanks in advance!

custi
  • 553
  • 1
  • 4
  • 11

2 Answers2

4

Just change cursor position whenever it hits your readonly range:

// line 1 & 2 is readonly:
editor.onDidChangeCursorPosition(function (e) {
    if (e.position.lineNumber < 3) {
        this.editor.setPosition({
            lineNumber:3,
            column: 1
        });
    }
});
Rizky Ramadhan
  • 7,360
  • 4
  • 27
  • 31
3

I have created a plugin for adding range restrictions in the monaco editor. This plugin is created to solve this issue #953 of monaco editor.

Detailed Documentation and Playground for this plugin is available here

NPM Package

npm install constrained-editor-plugin@latest

Dependencies

<!-- Optional Dependency -->
<link rel="stylesheet" href="./node_modules/constrained-editor-plugin/constrained-editor-plugin.css">
<!-- Required Dependency -->
<script src="./node_modules/constrained-editor-plugin/constrainedEditorPlugin.js" ></script>

Sample Snippet

require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () {
  const container = document.getElementById('container')
  const editorInstance = monaco.editor.create(container, {
    value: [
      'const utils = {};',
      'function addKeysToUtils(){',
      '',
      '}',
      'addKeysToUtils();'
    ].join('\n'),
    language: 'javascript'
  });
  const model = editorInstance.getModel();

  // - Configuration for the Constrained Editor : Starts Here
  const constrainedInstance = constrainedEditor(monaco);
  constrainedInstance.initializeIn(editorInstance);
  constrainedInstance.addRestrictionsTo(model, [{
    // range : [ startLine, startColumn, endLine, endColumn ]
    range: [1, 7, 1, 12], // Range of Util Variable name
    label: 'utilName',
    validate: function (currentlyTypedValue, newRange, info) {
      const noSpaceAndSpecialChars = /^[a-z0-9A-Z]*$/;
      return noSpaceAndSpecialChars.test(currentlyTypedValue);
    }
  }, {
    range: [3, 1, 3, 1], // Range of Function definition
    allowMultiline: true,
    label: 'funcDefinition'
  }]);
  // - Configuration for the Constrained Editor : Ends Here
});
  • Need something like that. Just tried it in the playground, looks awesome! Thank you for your effort and sharing. – burkay Jan 13 '23 at 16:34
  • Do you want a typescript implementation pull request? Also, where do you get this type "Array" from? It's mentioned in the constrainedEditor.js file, but I can't find in the editor.api.d.ts file. – specifically_user3827668 Jul 26 '23 at 19:46
  • @specifically_user3827668 Thanks for your suggestion, I would be happy to have a typescript version of the package. Feel free to create a pull request. Also the documentation link for the datatype of RangeRestrictionObject you asked for is [here](https://constrained-editor-plugin.vercel.app/docs/TypeDefinitions/available-type-definitions#rangerestrictionobject) – Vignesh Prakash Jul 27 '23 at 23:22
  • Alright, sir you'll see a pr soon. I made some small changes to clean it up a little, but functionally it is the same. Ohhh, its your own type docs. Nice. – specifically_user3827668 Jul 28 '23 at 06:19