The SynEdit undo/redo system looks like incoherent patchwork:
The code in the SynEdit repo contains no fewer than 24 change reasons (TSynChangeReason enumeration) many of which are not used.
It is overly complex and understanding how it works even superficially requires persistence and a significant time investment
It is partially broken as the note in the SynEdit.pas header states.
The code is split between the huge SynEdit.pas unit and SynEditTextBuffer.pas
Implementing a new editor command that changes the editor buffer and is undoable, requires a good understanding of how the undo/redo command works, thus limiting the potential for contributors to implement new features
It makes the implementation of major features as as multi-cursor support very hard
However it should be said that the underlying implementation is quite clever and efficient. (ChangeReason to group undo actions, InitialChangeReason to monitor the modified status of the buffer, etc.)
The refactoring in commit 35eb4bc05617181d9db7d450ca9a64f40f870d8c and some of the earlier work done, gave the undo/redo system a facelift. Separated a large part of the implementation into its own unit SynEditUndo.pas, consolidated the change reasons down to 10 and simplified the implementation significantly. But the underlying issue still remains with SynEdit.pas littered with code related to undo/redo.
Proposal
Replace the undo/redo system with a new one that keeps some of the nice aspects of the current system but at the same time totally decouples the implementation from the basic editor functionality implemented in the main unit SynEdit.pas. The key idea is to record the changes to the buffer via the three events (LinePut, LinesInserted, LinesDeleted) and undo them as appropriate. This is robust and foolproof. There is no need for calls to AddChange in SynEdit.pas, so the implementation of new commands is very much simplified. Whenever you make changes to the editor buffer, these changes will be undoable automatically. It is also backwards compatible. The public interface to the undo/redo system will remain unchanged.
The SynEdit undo/redo system looks like incoherent patchwork:
However it should be said that the underlying implementation is quite clever and efficient. (ChangeReason to group undo actions, InitialChangeReason to monitor the modified status of the buffer, etc.)
The refactoring in commit 35eb4bc05617181d9db7d450ca9a64f40f870d8c and some of the earlier work done, gave the undo/redo system a facelift. Separated a large part of the implementation into its own unit SynEditUndo.pas, consolidated the change reasons down to 10 and simplified the implementation significantly. But the underlying issue still remains with SynEdit.pas littered with code related to undo/redo.
Proposal
Replace the undo/redo system with a new one that keeps some of the nice aspects of the current system but at the same time totally decouples the implementation from the basic editor functionality implemented in the main unit SynEdit.pas. The key idea is to record the changes to the buffer via the three events (LinePut, LinesInserted, LinesDeleted) and undo them as appropriate. This is robust and foolproof. There is no need for calls to AddChange in SynEdit.pas, so the implementation of new commands is very much simplified. Whenever you make changes to the editor buffer, these changes will be undoable automatically. It is also backwards compatible. The public interface to the undo/redo system will remain unchanged.