-- | Undo all updates that happened since last save,
-- perform a given action and redo all updates again.
-- Given action must not modify undo history.
retroactivelyAtSavePointB :: BufferM a -> BufferM a
retroactivelyAtSavePointB action = do
    (undoDepth, result) <- go 0
    replicateM_ undoDepth redoB
    return result
    where
        go step = do
            atSavedPoint <- gets isUnchangedBuffer
            if atSavedPoint
            then (step,) <$> action
            else undoB >> go (step + 1)


-- | Analogous to const, but returns a function that takes two parameters,
-- rather than one.
retroactivelyAtSavePointB :: BufferM a -> BufferM a
retroactivelyAtSavePointB action = do
    (undoDepth, result) <- go 0
    replicateM_ undoDepth redoB
    return result
    where
        go step = do
            atSavedPoint <- gets isUnchangedBuffer
            if atSavedPoint
            then (step,) <$> action
            else undoB >> go (step + 1)


-- | Analogous to const, but returns a function that takes two parameters,
-- rather than one.
retroactivelyAtSavePointB action = do
    (undoDepth, result) <- go 0
    replicateM_ undoDepth redoB
    return result
    where
        go step = do
            atSavedPoint <- gets isUnchangedBuffer
            if atSavedPoint
            then (step,) <$> action
            else undoB >> go (step + 1)


-- | Analogous to const, but returns a function that takes two parameters,
-- rather than one.