1.8 KiB
1.8 KiB
Towards an Undo System
date
2025-11-27 20:14
tags
ked, hacks, text-editors
I've been thinking about building an undo system for ke. The first pass is going to be a linear system. Let's start with the basic definitions for an undo system:
typedef enum undo_kind {
UNDO_INSERT = 1 << 0,
UNDO_UNKNOWN = 1 << 1,
/* more types to follow */
} undo_kind;
typedef struct undo_node {
undo_kind op;
size_t row, col;
abuf text;
struct undo_node *next;
struct undo_node *parent;
} undo_node;
typedef struct undo_tree {
/* the start of the undo sequence */
undo_node *root;
/* where we are currently at */
undo_node *current;
/* the current undo operations being built */
undo_node *pending;
} undo_tree;
The root is anchored at the last time the file was saved; when saving, the tree is freed. Current points to the end of the history, and pending is the sequence being built.
The lifecycle looks something like:
undo_tree_newandundo_tree_free--- called ininit_editoranddeathknell, respectively. The tree is initialized with all nodes set toNULL.- Once the user starts doing undoable things,
undo_begin(undo_kind)gets called, callingundo_node_new(undo_kind)if needed to set uptree->pending. It may need to callundo_commit(below) if needed. - Until an
undo_commitis called, some form ofundo_appendorundo_prependis called. - Finally, at some point
undo_commitis called. This needs to do a few things:- If
tree->current->nextis notNULL, it must be freed. - Set
tree->current->nextas pending, settree->currenttotree->current->next. - Set
tree->pendingtoNULL.
- If
Once the e
undo_node_new(undo_kind)andundo_node_free