diff --git a/src/text_editor/buffer_history.cpp b/src/text_editor/buffer_history.cpp index e1273dc..a76f20d 100644 --- a/src/text_editor/buffer_history.cpp +++ b/src/text_editor/buffer_history.cpp @@ -98,7 +98,7 @@ void ClearRedoStack(Buffer *buffer) { // We can invoke this before caret altering commands to save caret history // and then call some editing command to edit which is not going to save carets // @todo: this needs to be actually tested though!!! -void BeforeEdit(Buffer *buffer, Array &carets) { +Array BeginEdit(Allocator allocator, Buffer *buffer, Array &carets) { Assert(buffer->edit_phase == 0 || buffer->edit_phase == 1); if (buffer->edit_phase == 0) { buffer->edit_phase += 1; @@ -106,11 +106,19 @@ void BeforeEdit(Buffer *buffer, Array &carets) { SaveHistoryBeforeMergeCursor(buffer, &buffer->undo_stack, carets); ClearRedoStack(buffer); } + Array result = {allocator}; + return result; +} + +void PreBeginEdit_SaveCaretHistory(Buffer *buffer, Array &carets) { + BeginEdit({}, buffer, carets); } bool KILL_SELECTION = true; -void AfterEdit(Buffer *buffer, Array *edits, Array *carets, bool kill_selection = true) { +void EndEdit(Buffer *buffer, Array *edits, Array *carets, bool kill_selection = true) { ProfileFunction(); + ApplyEdits(buffer, *edits); + Assert(buffer->edit_phase == 2); buffer->edit_phase -= 2; diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index b6a5320..7cf667b 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -463,6 +463,7 @@ void AppendToConsole(String16 string) { // @todo: ? View *view = FindView(buffer->id); + Assert(view); bool scroll_to_end = false; if (view) { diff --git a/src/text_editor/commands_clipboard.cpp b/src/text_editor/commands_clipboard.cpp index 5d9413a..3db91d1 100644 --- a/src/text_editor/commands_clipboard.cpp +++ b/src/text_editor/commands_clipboard.cpp @@ -47,24 +47,20 @@ void Command_Paste(View *view) { // Regular paste if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) { - BeforeEdit(buffer, view->carets); + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); - Array edits = {scratch}; For(view->carets) AddEdit(&edits, it.range, string); - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets); + EndEdit(buffer, &edits, &view->carets); return; } // Multicursor paste - BeforeEdit(buffer, view->carets); + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); - Array edits = {scratch}; for (int64_t i = 0; i < view->carets.len; i += 1) { String16 string = SavedClipboardCursors[i]; Caret &it = view->carets[i]; AddEdit(&edits, it.range, string); } - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets); + EndEdit(buffer, &edits, &view->carets); } \ No newline at end of file diff --git a/src/text_editor/commands_window.cpp b/src/text_editor/commands_window.cpp index 2043d14..be095c5 100644 --- a/src/text_editor/commands_window.cpp +++ b/src/text_editor/commands_window.cpp @@ -162,11 +162,10 @@ void Command_MoveLine(View *view, int direction) { XY back; }; - Buffer *buffer = GetBuffer(view->active_buffer); - BeforeEdit(buffer, view->carets); + Buffer *buffer = GetBuffer(view->active_buffer); + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); Array saved_xy = {scratch}; - Array edits = {scratch}; For(view->carets) { Add(&saved_xy, {PosToXY(*buffer, GetFront(it)), PosToXY(*buffer, GetBack(it))}); Range lines_to_move_range = {GetFullLineStart(buffer, it.range.min), GetFullLineEnd(buffer, it.range.max)}; @@ -187,8 +186,7 @@ void Command_MoveLine(View *view, int direction) { AddEdit(&edits, Rng(prev_line_start), string); } } - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets); + EndEdit(buffer, &edits, &view->carets); Int line_offset = direction == DIR_UP ? -1 : +1; for (Int i = 0; i < saved_xy.len; i += 1) { @@ -204,24 +202,24 @@ void Command_MoveLine(View *view, int direction) { } void Command_Replace(View *view, String16 string) { - Buffer *buffer = GetBuffer(view->active_buffer); Scratch scratch; - BeforeEdit(buffer, view->carets); + + Buffer *buffer = GetBuffer(view->active_buffer); + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); - Array edits = {scratch}; For(view->carets) AddEdit(&edits, it.range, string); - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets); + EndEdit(buffer, &edits, &view->carets); } void Command_DuplicateLine(View *view, int direction) { Assert(direction == DIR_UP || direction == DIR_DOWN); + Scratch scratch; + Buffer *buffer = GetBuffer(view->active_buffer); - BeforeEdit(buffer, view->carets); + BeginEdit(scratch, buffer, view->carets); For(view->carets) it = MakeCaret(GetFront(it)); MergeCarets(view); - Scratch scratch; Array edits = {scratch}; For(view->carets) { Int line = PosToLine(*buffer, it.range.min); @@ -230,8 +228,7 @@ void Command_DuplicateLine(View *view, int direction) { Int pos = direction == DIR_UP ? range.min : range.max; AddEdit(&edits, Rng(pos), string); } - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets); + EndEdit(buffer, &edits, &view->carets); Command_Move(view, direction); } @@ -292,11 +289,10 @@ void Command_IndentSelectedLines(View *view, bool shift = false) { Scratch scratch; Buffer *buffer = GetBuffer(view->active_buffer); - BeforeEdit(buffer, view->carets); + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); Array line_ranges_to_indent = GetSelectedLinesSorted(scratch, view); - Array edits = {scratch}; For(line_ranges_to_indent) { for (Int i = it.min; i < it.max; i += 1) { Range pos_range_of_line = GetLineRange(*buffer, i); @@ -315,9 +311,7 @@ void Command_IndentSelectedLines(View *view, bool shift = false) { } } } - - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets, !KILL_SELECTION); + EndEdit(buffer, &edits, &view->carets, !KILL_SELECTION); view->update_scroll = false; } @@ -325,13 +319,12 @@ void Command_TrimTrailingWhitespace(View *view, bool dont_trim_lines_with_cursor Scratch scratch; Buffer *buffer = GetBuffer(view->active_buffer); - BeforeEdit(buffer, view->carets); + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); Array lines_to_skip_triming = {}; if (dont_trim_lines_with_cursor) lines_to_skip_triming = GetSelectedLinesSorted(scratch, view); - Array edits = {scratch}; for (Int i = 0; i < buffer->line_starts.len; i += 1) { Int range_index = FindRangeByPos(lines_to_skip_triming, i); if (range_index != -1) continue; @@ -348,8 +341,7 @@ void Command_TrimTrailingWhitespace(View *view, bool dont_trim_lines_with_cursor AddEdit(&edits, whitespace_range, L""); } - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets, !KILL_SELECTION); + EndEdit(buffer, &edits, &view->carets, !KILL_SELECTION); view->update_scroll = false; } @@ -357,13 +349,12 @@ void Command_ConvertLineEndings(View *view, bool dont_trim_lines_with_cursor) { Scratch scratch; Buffer *buffer = GetBuffer(view->active_buffer); - BeforeEdit(buffer, view->carets); + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); Array lines_to_skip_triming = {}; if (dont_trim_lines_with_cursor) lines_to_skip_triming = GetSelectedLinesSorted(scratch, view); - Array edits = {scratch}; for (Int i = 0; i < buffer->line_starts.len; i += 1) { Int range_index = FindRangeByPos(lines_to_skip_triming, i); if (range_index != -1) continue; @@ -375,9 +366,7 @@ void Command_ConvertLineEndings(View *view, bool dont_trim_lines_with_cursor) { AddEdit(&edits, {range.max - 1, range.max}, L""); } } - - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets, !KILL_SELECTION); + EndEdit(buffer, &edits, &view->carets, !KILL_SELECTION); view->update_scroll = false; } @@ -385,11 +374,10 @@ void Command_KillSelectedLines(View *view) { Scratch scratch; Buffer *buffer = GetBuffer(view->active_buffer); - BeforeEdit(buffer, view->carets); + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); Array lines = GetSelectedLinesSorted(scratch, view); - Array edits = {scratch}; For(lines) { Range add_range = GetLineRange(*buffer, it.min); @@ -406,16 +394,15 @@ void Command_KillSelectedLines(View *view) { it.range.min = it.range.max = range.min; } - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets, KILL_SELECTION); + EndEdit(buffer, &edits, &view->carets, KILL_SELECTION); } void Command_Delete(View *view, int direction, bool ctrl = false) { Assert(direction == DIR_LEFT || direction == DIR_RIGHT); Scratch scratch; - Buffer *buffer = GetBuffer(view->active_buffer); - BeforeEdit(buffer, view->carets); + Buffer *buffer = GetBuffer(view->active_buffer); + Array edits = BeginEdit(scratch, buffer, view->carets); // Select things to delete For(view->carets) { @@ -442,10 +429,8 @@ void Command_Delete(View *view, int direction, bool ctrl = false) { } MergeCarets(view); - Array edits = {scratch}; For(view->carets) AddEdit(&edits, it.range, {}); - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets); + EndEdit(buffer, &edits, &view->carets); } void Command_SelectAll(View *view, String16 needle) { @@ -577,11 +562,10 @@ Array FindAllInBuffer(Allocator allocator, Buffer *buffer, String16 needl } void Command_IdentedNewLine(View *view) { - Buffer *buffer = GetBuffer(view->active_buffer); - Scratch scratch; - BeforeEdit(buffer, view->carets); + Buffer *buffer = GetBuffer(view->active_buffer); + Scratch scratch; + Array edits = BeginEdit(scratch, buffer, view->carets); MergeCarets(view); - Array edits = {scratch}; For(view->carets) { Int front = GetFront(it); Int line = PosToLine(*buffer, front); @@ -590,8 +574,7 @@ void Command_IdentedNewLine(View *view) { String16 string16 = ToString16(scratch, string); AddEdit(&edits, it.range, string16); } - ApplyEdits(buffer, edits); - AfterEdit(buffer, &edits, &view->carets); + EndEdit(buffer, &edits, &view->carets); } void WindowCommand(Event event, Window *window, View *view) { @@ -675,7 +658,7 @@ void WindowCommand(Event event, Window *window, View *view) { } else if (Ctrl(SDLK_V)) { Command_Paste(view); } else if (Ctrl(SDLK_X)) { - BeforeEdit(buffer, view->carets); + PreBeginEdit_SaveCaretHistory(buffer, view->carets); Command_Copy(view); Command_Replace(view, L""); } diff --git a/src/text_editor/todo.txt b/src/text_editor/todo.txt index 81d6fe8..d5946d3 100644 --- a/src/text_editor/todo.txt +++ b/src/text_editor/todo.txt @@ -1,5 +1,4 @@ - search as a command to execute which is going to be in the title bar -- maybe modify api BeginEdit - EndEdit - search backwards - draw indentation levels like in sublime (those lines) - we render chars one by one so seems relatively easy to figure out if whitespace belongs to beginning of line (make sure to add max value like 40 because of big files)