texthistory: hoist single actions from group

In many cases across GtkTextBuffer, we end up with operations performed
inside of a begin/end user action. Those can be coalesced into a single
sub-action within the group, and hoisted out of the group. Doing so
increases the chances that we chain similar actions together for words.

Additionally, this fixes an issue introduced in
6179886b14 for #3977 where GNOME Text Editor
started to group all possible actions into a single group.

Fixes GNOME/gnome-text-editor#97
This commit is contained in:
Christian Hergert
2021-06-30 16:40:15 -07:00
parent e9d3d3e3cf
commit d8ab2e6d03

View File

@@ -213,6 +213,8 @@ action_chain (Action *action,
if (action->kind == ACTION_KIND_GROUP)
{
Action *tail = g_queue_peek_tail (&action->u.group.actions);
/* Always push new items onto a group, so that we can coalesce
* items when gtk_text_history_end_user_action() is called.
*
@@ -221,9 +223,23 @@ action_chain (Action *action,
*/
if (other->kind == ACTION_KIND_BARRIER)
action_free (other);
else
g_queue_push_tail_link (&action->u.group.actions, &other->link);
{
action_free (other);
return TRUE;
}
/* Try to chain onto the tail item in the group to increase
* the chances we have a single action within the group. That
* way we are more likely to hoist out of the group when the
* user action is ended.
*/
if (tail != NULL && tail->kind == other->kind)
{
if (action_chain (tail, other, in_user_action))
return TRUE;
}
g_queue_push_tail_link (&action->u.group.actions, &other->link);
return TRUE;
}
@@ -820,6 +836,26 @@ gtk_text_history_end_user_action (GtkTextHistory *self)
goto update_state;
}
/* If there is a single item within the group, we can hoist
* it up increasing the chances that we can join actions.
*/
if (peek->u.group.actions.length == 1)
{
GList *link_ = peek->u.group.actions.head;
Action *replaced = link_->data;
replaced->is_modified = peek->is_modified;
replaced->is_modified_set = peek->is_modified_set;
g_queue_unlink (&peek->u.group.actions, link_);
g_queue_unlink (&self->undo_queue, &peek->link);
action_free (peek);
gtk_text_history_push (self, replaced);
goto update_state;
}
/* Now insert a barrier action so we don't allow
* joining items to this node in the future.
*/