summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-05-21 22:11:23 -0400
committerpommicket <pommicket@gmail.com>2023-05-21 22:11:23 -0400
commit37eb65550f164857ed27d2e07c48c8b80c4d15fc (patch)
tree7d5c67838c80d1b64ccae05968d008aa8201c858
parent44413aca2385fceb7b6c74cb3e764271fdc077e7 (diff)
better undo chaining
-rw-r--r--buffer.c14
-rw-r--r--main.c1
2 files changed, 10 insertions, 5 deletions
diff --git a/buffer.c b/buffer.c
index 5ecdf4f..09b0efd 100644
--- a/buffer.c
+++ b/buffer.c
@@ -616,7 +616,9 @@ static bool buffer_edit_does_anything(TextBuffer *buffer, BufferEdit *edit) {
}
// has enough time passed since the last edit that we should create a new one?
-static bool buffer_edit_split(TextBuffer *buffer) {
+//
+// is_deletion should be set to true if the edit involves any deletion.
+static bool buffer_edit_split(TextBuffer *buffer, bool is_deletion) {
BufferEdit *last_edit = arr_lastp(buffer->undo_history);
if (!last_edit) return true;
if (buffer->will_chain_edits) return true;
@@ -624,7 +626,11 @@ static bool buffer_edit_split(TextBuffer *buffer) {
double curr_time = buffer->ted->frame_time;
double undo_time_cutoff = buffer_settings(buffer)->undo_save_time; // only keep around edits for this long (in seconds).
return last_edit->time <= buffer->last_write_time // last edit happened before buffer write (we need to split this so that undo_history_write_pos works)
- || curr_time - last_edit->time > undo_time_cutoff;
+ || curr_time - last_edit->time > undo_time_cutoff
+ || (curr_time != last_edit->time && (// if the last edit didn't take place on the same frame,
+ (last_edit->prev_len && !is_deletion) || // last edit deleted text but this edit inserts text
+ (last_edit->new_len && is_deletion) // last edit inserted text and this one deletes text
+ ));
}
// removes the last edit in the undo history if it doesn't do anything
@@ -1574,7 +1580,7 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32
i64 where_in_last_edit = last_edit ? buffer_pos_diff(buffer, last_edit->pos, pos) : -1;
// create a new edit, rather than adding to the old one if:
bool create_new_edit = where_in_last_edit < 0 || where_in_last_edit > last_edit->new_len // insertion is happening outside the previous edit,
- || buffer_edit_split(buffer); // or enough time has elapsed/etc to warrant a new one.
+ || buffer_edit_split(buffer, false); // or enough time has elapsed/etc to warrant a new one.
if (create_new_edit) {
// create a new edit for this insertion
@@ -2066,7 +2072,7 @@ void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars_)
!last_edit || // if there is no previous edit to combine it with
buffer_pos_cmp(del_end, edit_start) < 0 || // or if delete does not overlap last_edit
buffer_pos_cmp(del_start, edit_end) > 0 ||
- buffer_edit_split(buffer); // or if enough time has passed to warrant a new edit
+ buffer_edit_split(buffer, true); // or if enough time has passed to warrant a new edit
if (create_new_edit) {
// create a new edit
diff --git a/main.c b/main.c
index 64bf3ca..49d9663 100644
--- a/main.c
+++ b/main.c
@@ -2,7 +2,6 @@
FUTURE FEATURES:
- highlight TODO, FIXME, XXX, others(?) in comments
- autodetect indentation (tabs vs spaces)
-- better undo chaining (dechain on backspace?)
- font setting & support for multiple fonts to cover more characters
- support for variable-width fonts
- robust find (results shouldn't move around when you type things)