Listen for new history state?

Hi!
I would like to be notified when a new history state is generated.

For example, when I type “Hello world!” I would like to be notified just once; whereas, when I type “Hello” (wait a couple of second) “world!”, I would like to be notified two times, one after “Hello” and one at the end.

Is there a proper way to listen for that?

This feature could have multiple use case. For example, such an event it’s a great place to attach your “save a backup” logic, since the event is fired way less than the on-change event.

I need this feature to stay synced with the Visual Studio Code History API. I’m trying to publish a Visual Studio Code extension on a project based on Codemirror6, and it’s way easier to handle the history from Codemirror6 and just notify Visual Studio when a new state is available.

I briefly looked at the @codemirror/commands source code and could not find anything.
If there is not, could you please consider adding some sort of callback?
I would add it myself, but I have no idea on how to design such an API inside Codemirror6.

Since I need this feature asap, I would try to implement it myself by making my clone of the “history.ts” file. I’ll share it here when it’s ready.

Let me know if I missed something.
Best regards,
Luca Fabbian

This doesn’t exist, and would be difficult to provide in the form you describe, since whether new changes are included in the same event is determined only when the new change comes in, so an event is only really ‘closed’ when a new event is started.

I came to the same conclusion, however I managed to find a solution by relaxing the problem: I realized I do not need to know the history state content, but just when a new state is created.

I’ll post the code here for future references.
https://github.com/librogamesland/magebook/blob/main/src/javascript/history.ts

Currently, it’s nothing more than a dirty hard-coded hack, I hope I’ll refactor it soon.

First, in the history.ts I declare a way to listen for changes:

export const historyCallbacks : any = []

Then, I subscribe to this callback emitter from my main code (vscode.ts):

  let nextShouldBeAdded = true;
  historyCallbacks.push( (isDefinitive) => {
    if(isDefinitive) nextShouldBeAdded = true;
    if(nextShouldBeAdded){
        vscode.postMessage({ type: 'addUndo'}); // telling VSCode that a new state exists
        nextShouldBeAdded = false;
    }
  })


And finally, I edited the addChanges function in the history.ts to fire an event:

addChanges(event: HistEvent, time: number, userEvent: string | undefined, newGroupDelay: number, maxLen: number): HistoryState {
    let done = this.done, lastEvent = done[done.length - 1]
    if (lastEvent && lastEvent.changes && !lastEvent.changes.empty && event.changes &&
        (!userEvent || joinableUserEvent.test(userEvent)) &&
        ((!lastEvent.selectionsAfter.length &&
        time - this.prevTime < newGroupDelay &&
        isAdjacent(lastEvent.changes, event.changes)) ||
        // For compose (but not compose.start) events, always join with previous event
        userEvent == "input.type.compose")) {
    done = updateBranch(done, done.length - 1, maxLen,
                        new HistEvent(event.changes.compose(lastEvent.changes), conc(event.effects, lastEvent.effects),
                                        lastEvent.mapped, lastEvent.startSelection, none))
        historyCallbacks.forEach( callback => callback(false))
    } else {
        done = updateBranch(done, done.length, maxLen, event)
        historyCallbacks.forEach( callback => callback(true))
    }

    return new HistoryState(done, none, time, userEvent)
}

Done!