Trying to add undo

This commit is contained in:
Krzosa Karol
2024-06-29 12:15:39 +02:00
parent c8ad9222fd
commit ceecb6cc81
4 changed files with 116 additions and 30 deletions

View File

@@ -225,7 +225,7 @@ void MergeSort(int64_t Count, Edit *First, Edit *Temp) {
}
}
void ApplyEdits(Buffer *buffer, Array<Edit> edits) {
void _ApplyEdits(Buffer *buffer, Array<Edit> edits) {
Scratch scratch((Arena *)buffer->allocator.object);
Assert(buffer->data[0]);
Assert(buffer->allocator.proc);

View File

@@ -101,7 +101,7 @@ void EventRecording_SimulateGetCharPressed(Window *focused_window) {
For(focused_window->cursors) {
AddEdit(&edits, it.range, string);
}
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
}
}

View File

@@ -14,6 +14,16 @@ struct Layout {
Vec2 buffer_world_pixel_size;
};
struct HistoryEntry {
Array<Cursor> cursors;
Array<Edit> edits;
};
struct History {
Array<HistoryEntry> entries;
int debug_edit_phase;
};
struct Window {
Font font;
float font_size;
@@ -25,6 +35,7 @@ struct Window {
Cursor main_cursor_begin_frame;
Array<Cursor> cursors;
Buffer buffer;
History history;
Arena layout_arena;
Layout layout;
@@ -246,7 +257,7 @@ Array<LayoutColumn> CalculateVisibleColumns(Arena *arena, Window &window) {
return r;
}
void BeforeEdit(Window *window) {
void MergeCursors(Window *window) {
Scratch scratch;
// Merge cursors that overlap, this needs to be handled before any edits to
// make sure overlapping edits won't happen.
@@ -280,7 +291,67 @@ void BeforeEdit(Window *window) {
window->cursors = new_cursors;
}
void UndoEdit(Window *window) {
if (window->history.entries.len <= 0) return;
HistoryEntry entry = window->history.entries.pop();
_ApplyEdits(&window->buffer, entry.edits);
window->cursors.dealloc();
window->cursors = entry.cursors;
Allocator sys_allocator = GetSystemAllocator();
For(entry.edits) Dealloc(sys_allocator, &it.string.data);
entry.edits.dealloc();
// Generate layout
Clear(&window->layout_arena);
window->layout = CalculateLayout(&window->layout_arena, window->buffer, window->font, window->font_size, window->font_spacing);
}
void BeforeEdit(Window *window) {
Assert(window->history.debug_edit_phase == 0);
window->history.debug_edit_phase += 1;
{
History &h = window->history;
HistoryEntry *entry = h.entries.alloc();
Allocator sys_allocator = GetSystemAllocator();
Assert(window->cursors.len);
entry->cursors = window->cursors.tight_copy(sys_allocator);
}
MergeCursors(window);
}
void ApplyEdits(Window *window, Array<Edit> edits) {
Assert(window->history.debug_edit_phase == 1);
window->history.debug_edit_phase += 1;
{
HistoryEntry *entry = window->history.entries.last();
Allocator sys_allocator = GetSystemAllocator();
entry->edits = edits.tight_copy(sys_allocator);
For(entry->edits) {
// Need to compile reverse edits
Range new_range = {it.range.min, it.range.min + it.string.len};
String string = GetString(window->buffer, it.range);
it.string = Copy(sys_allocator, string);
it.range = new_range;
}
}
_ApplyEdits(&window->buffer, edits);
}
void AfterEdit(Window *window, Array<Edit> edits) {
Assert(window->history.debug_edit_phase == 2);
window->history.debug_edit_phase -= 2;
HistoryEntry *entry = window->history.entries.last();
Assert(entry->cursors.len);
Assert(entry->edits.len);
// Offset all cursors by edits
ForItem(edit, edits) {
int64_t remove_size = GetRangeSize(edit.range);
@@ -308,6 +379,7 @@ void AfterEdit(Window *window, Array<Edit> edits) {
// Make sure all cursors are in range
For(window->cursors) it.range = Clamp(window->buffer, it.range);
// Generate layout
Clear(&window->layout_arena);
window->layout = CalculateLayout(&window->layout_arena, window->buffer, window->font, window->font_size, window->font_spacing);
}

View File

@@ -63,27 +63,26 @@ int main() {
window.font_size = font_size;
window.font_spacing;
InitArena(&window.layout_arena);
InitBuffer(GetSystemAllocator(), &window.buffer);
if (1) {
// Array<Edit> edits = {FrameArena};
// AddEdit(&edits, GetEnd(window.buffer), Format(FrameArena, "line number: 1"));
// ApplyEdits(&window.buffer, edits);
for (int i = 0; i < 50; i += 1) {
Array<Edit> edits = {FrameArena};
AddEdit(&edits, GetEnd(window.buffer), Format(FrameArena, "line number: %d\n", i));
ApplyEdits(&window.buffer, edits);
}
}
window.cursors.allocator = GetSystemAllocator();
window.cursors.add({});
AfterEdit(&window, {});
if (1) {
for (int i = 0; i < 50; i += 1) {
BeforeEdit(&window);
Array<Edit> edits = {FrameArena};
AddEdit(&edits, GetEnd(window.buffer), Format(FrameArena, "line number: %d\n", i));
ApplyEdits(&window, edits);
AfterEdit(&window, edits);
}
}
*window.cursors.last() = {};
windows.add(window);
}
// EnableEventWaiting();
int64_t frame = -1;
InitEventRecording();
while (!WindowShouldClose()) {
For(windows) {
@@ -91,6 +90,9 @@ int main() {
it.main_cursor_begin_frame = it.cursors[0];
}
frame += 1;
Dbg("%lld", (long long)frame);
UpdateEventRecording();
{
@@ -100,7 +102,7 @@ int main() {
focused_window->scroll.y -= mouse_wheel;
focused_window->scroll.y = ClampBottom(focused_window->scroll.y, 0.f);
BeforeEdit(focused_window); // Merge cursors
MergeCursors(focused_window);
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_A)) {
focused_window->cursors.clear();
focused_window->cursors.add(MakeCursor(0, focused_window->buffer.len));
@@ -167,7 +169,7 @@ int main() {
cursors_to_add.add({front, front});
}
For(cursors_to_add) focused_window->cursors.add(it);
BeforeEdit(focused_window); // Merge cursors
MergeCursors(focused_window);
} else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_LEFT_ALT)) { // Default in VSCode seems to be Shift + Alt + down
BeforeEdit(focused_window);
Array<Edit> edits = {FrameArena};
@@ -177,7 +179,7 @@ int main() {
String string = GetString(focused_window->buffer, line.range);
AddEdit(&edits, {line.range.max, line.range.max}, string);
}
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
For(focused_window->cursors) {
it.range.max = it.range.min = MoveDown(focused_window->buffer, it.range.min);
@@ -204,7 +206,7 @@ int main() {
cursors_to_add.add({front, front});
}
For(cursors_to_add) focused_window->cursors.add(it);
BeforeEdit(focused_window); // Merge cursors
MergeCursors(focused_window);
} else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_LEFT_ALT)) { // Default in VSCode seems to be Shift + Alt + up
BeforeEdit(focused_window);
Array<Edit> edits = {FrameArena};
@@ -214,7 +216,7 @@ int main() {
String string = GetString(focused_window->buffer, line.range);
AddEdit(&edits, {line.range.min, line.range.min}, string);
}
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
For(focused_window->cursors) {
it.range.max = it.range.min = MoveUp(focused_window->buffer, it.range.min);
@@ -240,7 +242,7 @@ int main() {
if (Seek(to_seek, needle, &found_index, SeekFlag_IgnoreCase)) {
found_index += cursor.range.max;
focused_window->cursors.add(MakeCursor(found_index + needle.len, found_index));
BeforeEdit(focused_window); // Merge cursors
MergeCursors(focused_window);
}
}
@@ -288,7 +290,7 @@ int main() {
For(focused_window->cursors) {
AddEdit(&edits, it.range, string);
}
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
}
if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_X) || IsKeyPressedRepeat(KEY_X))) {
@@ -310,10 +312,14 @@ int main() {
}
String to_save = Merge(FrameArena, strings, "\n");
SetClipboardText(to_save.data);
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
}
if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_Z) || IsKeyPressedRepeat(KEY_Z))) {
UndoEdit(focused_window);
}
if (IsKeyPressed(KEY_DELETE) || IsKeyPressedRepeat(KEY_DELETE)) {
// Select things to delete
For(focused_window->cursors) {
@@ -334,7 +340,7 @@ int main() {
Array<Edit> edits = {FrameArena};
String string = {};
For(focused_window->cursors) AddEdit(&edits, it.range, string);
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
}
@@ -358,7 +364,7 @@ int main() {
Array<Edit> edits = {FrameArena};
String string = {};
For(focused_window->cursors) AddEdit(&edits, it.range, string);
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
}
@@ -366,7 +372,7 @@ int main() {
BeforeEdit(focused_window);
Array<Edit> edits = {FrameArena};
For(focused_window->cursors) AddEdit(&edits, it.range, " ");
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
}
@@ -382,7 +388,7 @@ int main() {
BeforeEdit(focused_window);
Array<Edit> edits = {FrameArena};
For(focused_window->cursors) AddEdit(&edits, it.range, "\n");
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
}
@@ -402,7 +408,7 @@ int main() {
For(focused_window->cursors) {
AddEdit(&edits, it.range, string);
}
ApplyEdits(&focused_window->buffer, edits);
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
}
EventRecording_SimulateGetCharPressed(focused_window);
@@ -457,7 +463,7 @@ int main() {
window.cursors.clear();
}
window.cursors.add({col->pos, col->pos});
BeforeEdit(&window); // Merge cursors
MergeCursors(&window);
window.mouse_selecting = true;
}
@@ -572,6 +578,14 @@ int main() {
Dbg_Draw();
EventRecording_Draw();
Window *focused_window = &windows[0];
if (focused_window->mouse_selecting || EventPlaying) {
DisableEventWaiting();
} else {
EnableEventWaiting();
}
EndDrawing();
}
}