@@ -83,6 +83,11 @@ public class CEUndoManager {
8383
8484 private weak var textView : TextView ?
8585 private( set) public var isGrouping : Bool = false
86+
87+ /// After ``endUndoGrouping`` is called, we'd expect the next mutation to be exclusive no matter what. This
88+ /// flag facilitates that, and is set by ``endUndoGrouping``
89+ private var shouldBreakNextGroup : Bool = false
90+
8691 /// True when the manager is ignoring mutations.
8792 private var isDisabled : Bool = false
8893
@@ -154,18 +159,19 @@ public class CEUndoManager {
154159 return
155160 }
156161 let newMutation = Mutation ( mutation: mutation, inverse: textStorage. inverseMutation ( for: mutation) )
157- if !undoStack. isEmpty, let lastMutation = undoStack. last? . mutations. last {
158- if isGrouping || shouldContinueGroup ( newMutation, lastMutation: lastMutation) {
159- undoStack [ undoStack. count - 1 ] . mutations. append ( newMutation)
160- } else {
161- undoStack. append ( UndoGroup ( mutations: [ newMutation] ) )
162- }
162+ // We can continue a group if:
163+ // - A group exists
164+ // - We're not direct to break the current group
165+ // - We're forced grouping OR we automagically detect we can group.
166+ if !undoStack. isEmpty,
167+ let lastMutation = undoStack. last? . mutations. last,
168+ !shouldBreakNextGroup,
169+ isGrouping || shouldContinueGroup ( newMutation, lastMutation: lastMutation) {
170+ undoStack [ undoStack. count - 1 ] . mutations. append ( newMutation)
163171 } else {
164- undoStack. append (
165- UndoGroup ( mutations: [ newMutation] )
166- )
172+ undoStack. append ( UndoGroup ( mutations: [ newMutation] ) )
173+ shouldBreakNextGroup = false
167174 }
168-
169175 redoStack. removeAll ( )
170176 }
171177
@@ -178,6 +184,8 @@ public class CEUndoManager {
178184 return
179185 }
180186 isGrouping = true
187+ // This is a new undo group, break for it.
188+ shouldBreakNextGroup = true
181189 }
182190
183191 /// Stops grouping all incoming mutations.
@@ -187,6 +195,8 @@ public class CEUndoManager {
187195 return
188196 }
189197 isGrouping = false
198+ // We just ended a group, do not allow the next mutation to be added to the group we just made.
199+ shouldBreakNextGroup = true
190200 }
191201
192202 /// Determines whether or not two mutations should be grouped.
0 commit comments