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?
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.
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 馃挴.