Fix BeforeEdit cursor removal, add multicursor deletion

This commit is contained in:
Krzosa Karol
2024-06-29 10:27:16 +02:00
parent e3150f8203
commit 7e68e09b22
3 changed files with 90 additions and 22 deletions

View File

@@ -183,16 +183,47 @@ for (int i = 0; i < array.len; i += 1) {
} }
} }
// Simple delete
IterRemove(arr) { IterRemove(arr) {
IterRemovePrepare(arr); IterRemovePrepare(arr);
remove_item = true; remove_item = true;
} }
//
// Deleting backwards
//
For(arr.reverse_iter()) { For(arr.reverse_iter()) {
defer{ arr.unordered_remove(it); }; defer{ arr.unordered_remove(it); };
} }
//
// When double looping and deleting
//
Array<Cursor *> deleted_cursors = {scratch};
ForItem(cursor, window->cursors) {
For(deleted_cursors) if (it == &cursor) goto end_of_cursor_loop;
For(window->cursors) {
if (&it == &cursor) break;
bool a = cursor.range.max >= it.range.min && cursor.range.max <= it.range.max;
bool b = cursor.range.min >= it.range.min && cursor.range.min <= it.range.max;
if (a || b) {
deleted_cursors.add(&it);
cursor.range.max = Max(cursor.range.max, it.range.max);
cursor.range.min = Min(cursor.range.min, it.range.min);
break;
}
}
end_of_cursor_loop:;
}
For(deleted_cursors) window->cursors.ordered_remove(*it);
*/ */
#define IterRemove(a) for (int i = 0; i < (a).len; i += 1) #define IterRemove(a) for (int i = 0; i < (a).len; i += 1)
#define IterRemovePrepare(a) \ #define IterRemovePrepare(a) \

View File

@@ -247,21 +247,29 @@ Array<LayoutColumn> CalculateVisibleColumns(Arena *arena, Window &window) {
} }
void BeforeEdit(Window *window) { void BeforeEdit(Window *window) {
Scratch scratch;
// Merge cursors that overlap, this needs to be handled before any edits to // Merge cursors that overlap, this needs to be handled before any edits to
// make sure overlapping edits won't happen. // make sure overlapping edits won't happen.
for (int64_t cursor_i = 0; cursor_i < window->cursors.len; cursor_i += 1) { // @optimize: could probably reverse the inner loop and simply unordered remove
Cursor &cursor = window->cursors[cursor_i]; Array<Cursor *> deleted_cursors = {scratch};
IterRemove(window->cursors) { ForItem(cursor, window->cursors) {
IterRemovePrepare(window->cursors); For(deleted_cursors) if (it == &cursor) goto end_of_cursor_loop;
if (&cursor == &it) continue;
if (cursor.range.max >= it.range.min && cursor.range.max <= it.range.max) { For(window->cursors) {
remove_item = true; if (&it == &cursor) break;
cursor.range.max = it.range.max; bool a = cursor.range.max >= it.range.min && cursor.range.max <= it.range.max;
bool b = cursor.range.min >= it.range.min && cursor.range.min <= it.range.max;
if (a || b) {
deleted_cursors.add(&it);
cursor.range.max = Max(cursor.range.max, it.range.max);
cursor.range.min = Min(cursor.range.min, it.range.min);
break; break;
} }
} }
end_of_cursor_loop:;
} }
For(deleted_cursors) window->cursors.ordered_remove(*it);
} }
void AfterEdit(Window *window, Array<Edit> edits) { void AfterEdit(Window *window, Array<Edit> edits) {

View File

@@ -312,22 +312,51 @@ int main() {
} }
if (IsKeyPressed(KEY_DELETE) || IsKeyPressedRepeat(KEY_DELETE)) { if (IsKeyPressed(KEY_DELETE) || IsKeyPressedRepeat(KEY_DELETE)) {
if (IsKeyDown(KEY_LEFT_SHIFT)) { // Select things to delete
} For(focused_window->cursors) {
} if (GetRangeSize(it.range)) continue;
if (IsKeyPressed(KEY_BACKSPACE) || IsKeyPressedRepeat(KEY_BACKSPACE)) { if (IsKeyDown(KEY_LEFT_CONTROL)) {
if (IsKeyDown(KEY_LEFT_SHIFT)) { int64_t pos = Seek(focused_window->buffer, it.range.min, ITERATE_FORWARD);
} else { it = MakeCursor(it.range.min, pos);
BeforeEdit(focused_window); } else {
Array<Edit> edits = {FrameArena}; int64_t pos = MoveRight(focused_window->buffer, it.range.min);
String string = {}; it = MakeCursor(it.range.min, pos);
For(focused_window->cursors) {
int64_t pos = MoveLeft(focused_window->buffer, it.range.min);
AddEdit(&edits, {pos, it.range.min}, string);
} }
ApplyEdits(&focused_window->buffer, edits);
AfterEdit(focused_window, edits);
} }
// Merge
BeforeEdit(focused_window);
// Modify
Array<Edit> edits = {FrameArena};
String string = {};
For(focused_window->cursors) AddEdit(&edits, it.range, string);
ApplyEdits(&focused_window->buffer, edits);
AfterEdit(focused_window, edits);
}
if (IsKeyPressed(KEY_BACKSPACE) || IsKeyPressedRepeat(KEY_BACKSPACE)) {
// Select things to delete
For(focused_window->cursors) {
if (GetRangeSize(it.range)) continue;
if (IsKeyDown(KEY_LEFT_CONTROL)) {
int64_t pos = Seek(focused_window->buffer, it.range.min, ITERATE_BACKWARD);
it = MakeCursor(pos, it.range.min);
} else {
int64_t pos = MoveLeft(focused_window->buffer, it.range.min);
it = MakeCursor(pos, it.range.min);
}
}
// Merge
BeforeEdit(focused_window);
// Modify
Array<Edit> edits = {FrameArena};
String string = {};
For(focused_window->cursors) AddEdit(&edits, it.range, string);
ApplyEdits(&focused_window->buffer, edits);
AfterEdit(focused_window, edits);
} }
if (IsKeyPressed(KEY_ENTER) || IsKeyPressedRepeat(KEY_ENTER)) { if (IsKeyPressed(KEY_ENTER) || IsKeyPressedRepeat(KEY_ENTER)) {