Monaco-editor: Update model uri without changing model

Created on 20 Jun 2018  路  6Comments  路  Source: microsoft/monaco-editor

Is there a way I can update the model's URI without creating a new one?

If not, is there a way to copy the undo stack into the new model?

api editor-core feature-request

Most helpful comment

This looks a little bit like playing with 馃敟 in internals. Is there any more 'official' API that could be introduced?

model.cloneWithNewURI(newUri) would be 馃挴.

All 6 comments

Currently, this is not possible. You could, however ... use some creative JS to get this to work.

// Assuming model1 is the previous model
var model2 = monaco.editor.createModel(model1.getValue(), undefined, newURI);

var cm2 = model2._commandManager;
var cm1 = model1._commandManager;
var temp;

// SWAP currentOpenStackElement
temp = cm2.currentOpenStackElement;
cm2.currentOpenStackElement = cm1.currentOpenStackElement;
cm1.currentOpenStackElement = tmp;

// SWAP past
temp = cm2.past;
cm2.past = cm1.past;
cm1.past = tmp;

// SWAP future
temp = cm2.future;
cm2.future = cm1.future;
cm1.future = tmp;

Thank you!

This looks a little bit like playing with 馃敟 in internals. Is there any more 'official' API that could be introduced?

model.cloneWithNewURI(newUri) would be 馃挴.

I can't run your code @alexandrudima , I always have the following error :

Error: ModelService: Cannot add model because it already exists!

So i tried something else like :
[TypeScript] const model = editor.getModel(); if (model) { const oldValue = model.getValue(); const oldLanguage = model.getModeId(); model.dispose(); editor.setModel( monaco.editor.createModel( oldValue, oldLanguage, uri ? monaco.Uri.parse(uri) : undefined, ), ); }
and got the same error message...

I can't figure out what I'm doing wrong

I could use a cloneWithNewURI type of method. Right now if I want to change the URI I just have to say tough luck, I'm dumping your undo/redo stack (unless I want to mess with internals).

To copy the undostack first get it:

   var history = {
            past: editor.getModel()["_commandManager"].past,
            future: editor.getModel()["_commandManager"].future,
          }

literally copy it to the new model:

      if(history.past && history.past.length) {
        editor.getModel()['_commandManager'].past.push(...history.past.map(data => new EditStackElement(data)));
      }
      if(history.future && history.future.length) {
        editor.getModel()['_commandManager'].future.push(...history.future.map(data => new EditStackElement(data)));
      }

note that EditStackElement is an internal class to monaco, not sure if you can easily export it but redefining it works fine because it doesn't have any external references

class EditStackElement {
  beforeVersionId;
  beforeCursorState;
  afterCursorState;
  afterVersionId = -1;
  editOperations = [];
  constructor(json){

    for (let key in json){

      this[key] = json[key];

    }

  }
  undo(model) {
    for (var i = this.editOperations.length - 1; i >= 0; i--) {
      this.editOperations[i] = {
        operations: model.applyEdits(this.editOperations[i].operations)
      };
    }
  }
  redo(model) {
    for (var i = 0; i < this.editOperations.length; i++) {
      this.editOperations[i] = {
        operations: model.applyEdits(this.editOperations[i].operations)
      };
    }
  }
}

important
I'm not claiming any of this is a good idea. it was just the fastest way to ship what I needed to. This is answers the 2nd question.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ststeiger picture ststeiger  路  3Comments

Panhaiwei picture Panhaiwei  路  3Comments

fabiospampinato picture fabiospampinato  路  3Comments

akosyakov picture akosyakov  路  3Comments

SoftTimur picture SoftTimur  路  3Comments