The undo history will store the current selection in the history. Since the selection was at the default position (start of doc) when you fed it the changes, that’s where it’ll put it when you undo. You can use setSelection during replaying to work around this.
given a transaction, how do I change it’s position to another ? I looked at the doc and other discussions here but could not find a clear answer, any help appreciated.
let state=EditorState.create({ schema, doc: doc, plugins: view.getState().plugins });
for (let i=0; i<steps.length; i++) {
let step=steps[i];
let tr=state.tr.step(step));
closeHistory(tr);
state = state.apply(tr);
let endPos=Selection.near(state.doc.resolve(step.getMap().map(step.to, 1)));
state = state.apply(state.tr.setSelection(endPos));
}
view.updateView(state);
but seems a bit convulted, is that correct ? is there a simpler way ?
You can’t rely on steps having from or to properties (even for replace steps, those properties aren’t part of the public API). One way to get information about the extent of a step is to use its position map (see its forEach method). I assume you’re trying to get the position in the old doc, before the step? But if so, I’m not sure why you are applying the step’s map – or are these inverted steps?
There is no single cursor position that can be derived from a step. As I said, you can use step.getMap.forEach to find out which parts of the document it touched.
Certainly not. The transform module doesn’t even know selections exist, and that’s how it should be.
Sure, and it does so when you apply the step programatically too, but it computes it from the old selection, so that doesn’t give you the selection you’re looking for (the cursor will probalby simply stay at the start of the document).
Your code is using a post-step position and applying it before the step, which is probably not what you mean and might produce an error if the position is out of range. You might get better results using oldEnd.
ok, so if that is so, given a start position and a step what is the correct way to calculate the cursor position after applying the step ? is that the maximum of all newEnd in all changed ranges ?
I ended up with code that works, though I’m not sure is correct: (I didn’t close the history properly above)
let state=EditorState.create({ schema, doc: doc, plugins: view.getState().plugins });
for (let i=0; i<steps.length; i++) {
let step=steps[i];
let tr=state.tr.step(step);
state = state.apply(tr);
let pos=-1;
step.getMap().forEach((oldStart, oldEnd, newStart, newEnd) => {
if (newEnd>pos) pos=newEnd;
});
tr=state.tr.setSelection(Selection.near(state.doc.resolve(pos)));
state = state.apply(tr);
state= state.apply(closeHistory(state));
}
view.updateView(state);
Again, there is no ‘cursor position after applying the step’. If you want to map a given previous selection through a step, you use the selection’s map method. But it sounds like that’s not what you are talking about.
You could put the .step and .setSelection in the same transaction to save some transactions, but otherwise that looks sane.