Improve edit api
This commit is contained in:
@@ -98,7 +98,7 @@ void ClearRedoStack(Buffer *buffer) {
|
|||||||
// We can invoke this before caret altering commands to save caret history
|
// 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
|
// and then call some editing command to edit which is not going to save carets
|
||||||
// @todo: this needs to be actually tested though!!!
|
// @todo: this needs to be actually tested though!!!
|
||||||
void BeforeEdit(Buffer *buffer, Array<Caret> &carets) {
|
Array<Edit> BeginEdit(Allocator allocator, Buffer *buffer, Array<Caret> &carets) {
|
||||||
Assert(buffer->edit_phase == 0 || buffer->edit_phase == 1);
|
Assert(buffer->edit_phase == 0 || buffer->edit_phase == 1);
|
||||||
if (buffer->edit_phase == 0) {
|
if (buffer->edit_phase == 0) {
|
||||||
buffer->edit_phase += 1;
|
buffer->edit_phase += 1;
|
||||||
@@ -106,11 +106,19 @@ void BeforeEdit(Buffer *buffer, Array<Caret> &carets) {
|
|||||||
SaveHistoryBeforeMergeCursor(buffer, &buffer->undo_stack, carets);
|
SaveHistoryBeforeMergeCursor(buffer, &buffer->undo_stack, carets);
|
||||||
ClearRedoStack(buffer);
|
ClearRedoStack(buffer);
|
||||||
}
|
}
|
||||||
|
Array<Edit> result = {allocator};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreBeginEdit_SaveCaretHistory(Buffer *buffer, Array<Caret> &carets) {
|
||||||
|
BeginEdit({}, buffer, carets);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KILL_SELECTION = true;
|
bool KILL_SELECTION = true;
|
||||||
void AfterEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets, bool kill_selection = true) {
|
void EndEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets, bool kill_selection = true) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
|
ApplyEdits(buffer, *edits);
|
||||||
|
|
||||||
Assert(buffer->edit_phase == 2);
|
Assert(buffer->edit_phase == 2);
|
||||||
buffer->edit_phase -= 2;
|
buffer->edit_phase -= 2;
|
||||||
|
|
||||||
|
|||||||
@@ -463,6 +463,7 @@ void AppendToConsole(String16 string) {
|
|||||||
|
|
||||||
// @todo: ?
|
// @todo: ?
|
||||||
View *view = FindView(buffer->id);
|
View *view = FindView(buffer->id);
|
||||||
|
Assert(view);
|
||||||
|
|
||||||
bool scroll_to_end = false;
|
bool scroll_to_end = false;
|
||||||
if (view) {
|
if (view) {
|
||||||
|
|||||||
@@ -47,24 +47,20 @@ void Command_Paste(View *view) {
|
|||||||
|
|
||||||
// Regular paste
|
// Regular paste
|
||||||
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
|
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
|
||||||
BeforeEdit(buffer, view->carets);
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
For(view->carets) AddEdit(&edits, it.range, string);
|
For(view->carets) AddEdit(&edits, it.range, string);
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets);
|
||||||
AfterEdit(buffer, &edits, &view->carets);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multicursor paste
|
// Multicursor paste
|
||||||
BeforeEdit(buffer, view->carets);
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
for (int64_t i = 0; i < view->carets.len; i += 1) {
|
for (int64_t i = 0; i < view->carets.len; i += 1) {
|
||||||
String16 string = SavedClipboardCursors[i];
|
String16 string = SavedClipboardCursors[i];
|
||||||
Caret &it = view->carets[i];
|
Caret &it = view->carets[i];
|
||||||
AddEdit(&edits, it.range, string);
|
AddEdit(&edits, it.range, string);
|
||||||
}
|
}
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets);
|
||||||
AfterEdit(buffer, &edits, &view->carets);
|
|
||||||
}
|
}
|
||||||
@@ -163,10 +163,9 @@ void Command_MoveLine(View *view, int direction) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
BeforeEdit(buffer, view->carets);
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
Array<XYPair> saved_xy = {scratch};
|
Array<XYPair> saved_xy = {scratch};
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
For(view->carets) {
|
For(view->carets) {
|
||||||
Add(&saved_xy, {PosToXY(*buffer, GetFront(it)), PosToXY(*buffer, GetBack(it))});
|
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)};
|
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);
|
AddEdit(&edits, Rng(prev_line_start), string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets);
|
||||||
AfterEdit(buffer, &edits, &view->carets);
|
|
||||||
|
|
||||||
Int line_offset = direction == DIR_UP ? -1 : +1;
|
Int line_offset = direction == DIR_UP ? -1 : +1;
|
||||||
for (Int i = 0; i < saved_xy.len; i += 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) {
|
void Command_Replace(View *view, String16 string) {
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
BeforeEdit(buffer, view->carets);
|
|
||||||
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
For(view->carets) AddEdit(&edits, it.range, string);
|
For(view->carets) AddEdit(&edits, it.range, string);
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets);
|
||||||
AfterEdit(buffer, &edits, &view->carets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Command_DuplicateLine(View *view, int direction) {
|
void Command_DuplicateLine(View *view, int direction) {
|
||||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
||||||
|
Scratch scratch;
|
||||||
|
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
BeforeEdit(buffer, view->carets);
|
BeginEdit(scratch, buffer, view->carets);
|
||||||
For(view->carets) it = MakeCaret(GetFront(it));
|
For(view->carets) it = MakeCaret(GetFront(it));
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
|
|
||||||
Scratch scratch;
|
|
||||||
Array<Edit> edits = {scratch};
|
Array<Edit> edits = {scratch};
|
||||||
For(view->carets) {
|
For(view->carets) {
|
||||||
Int line = PosToLine(*buffer, it.range.min);
|
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;
|
Int pos = direction == DIR_UP ? range.min : range.max;
|
||||||
AddEdit(&edits, Rng(pos), string);
|
AddEdit(&edits, Rng(pos), string);
|
||||||
}
|
}
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets);
|
||||||
AfterEdit(buffer, &edits, &view->carets);
|
|
||||||
|
|
||||||
Command_Move(view, direction);
|
Command_Move(view, direction);
|
||||||
}
|
}
|
||||||
@@ -292,11 +289,10 @@ void Command_IndentSelectedLines(View *view, bool shift = false) {
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
|
||||||
BeforeEdit(buffer, view->carets);
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
|
|
||||||
Array<Range> line_ranges_to_indent = GetSelectedLinesSorted(scratch, view);
|
Array<Range> line_ranges_to_indent = GetSelectedLinesSorted(scratch, view);
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
For(line_ranges_to_indent) {
|
For(line_ranges_to_indent) {
|
||||||
for (Int i = it.min; i < it.max; i += 1) {
|
for (Int i = it.min; i < it.max; i += 1) {
|
||||||
Range pos_range_of_line = GetLineRange(*buffer, i);
|
Range pos_range_of_line = GetLineRange(*buffer, i);
|
||||||
@@ -315,9 +311,7 @@ void Command_IndentSelectedLines(View *view, bool shift = false) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EndEdit(buffer, &edits, &view->carets, !KILL_SELECTION);
|
||||||
ApplyEdits(buffer, edits);
|
|
||||||
AfterEdit(buffer, &edits, &view->carets, !KILL_SELECTION);
|
|
||||||
view->update_scroll = false;
|
view->update_scroll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,13 +319,12 @@ void Command_TrimTrailingWhitespace(View *view, bool dont_trim_lines_with_cursor
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
|
||||||
BeforeEdit(buffer, view->carets);
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
|
|
||||||
Array<Range> lines_to_skip_triming = {};
|
Array<Range> lines_to_skip_triming = {};
|
||||||
if (dont_trim_lines_with_cursor) lines_to_skip_triming = GetSelectedLinesSorted(scratch, view);
|
if (dont_trim_lines_with_cursor) lines_to_skip_triming = GetSelectedLinesSorted(scratch, view);
|
||||||
|
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
for (Int i = 0; i < buffer->line_starts.len; i += 1) {
|
for (Int i = 0; i < buffer->line_starts.len; i += 1) {
|
||||||
Int range_index = FindRangeByPos(lines_to_skip_triming, i);
|
Int range_index = FindRangeByPos(lines_to_skip_triming, i);
|
||||||
if (range_index != -1) continue;
|
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"");
|
AddEdit(&edits, whitespace_range, L"");
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets, !KILL_SELECTION);
|
||||||
AfterEdit(buffer, &edits, &view->carets, !KILL_SELECTION);
|
|
||||||
view->update_scroll = false;
|
view->update_scroll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,13 +349,12 @@ void Command_ConvertLineEndings(View *view, bool dont_trim_lines_with_cursor) {
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
|
||||||
BeforeEdit(buffer, view->carets);
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
|
|
||||||
Array<Range> lines_to_skip_triming = {};
|
Array<Range> lines_to_skip_triming = {};
|
||||||
if (dont_trim_lines_with_cursor) lines_to_skip_triming = GetSelectedLinesSorted(scratch, view);
|
if (dont_trim_lines_with_cursor) lines_to_skip_triming = GetSelectedLinesSorted(scratch, view);
|
||||||
|
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
for (Int i = 0; i < buffer->line_starts.len; i += 1) {
|
for (Int i = 0; i < buffer->line_starts.len; i += 1) {
|
||||||
Int range_index = FindRangeByPos(lines_to_skip_triming, i);
|
Int range_index = FindRangeByPos(lines_to_skip_triming, i);
|
||||||
if (range_index != -1) continue;
|
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"");
|
AddEdit(&edits, {range.max - 1, range.max}, L"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EndEdit(buffer, &edits, &view->carets, !KILL_SELECTION);
|
||||||
ApplyEdits(buffer, edits);
|
|
||||||
AfterEdit(buffer, &edits, &view->carets, !KILL_SELECTION);
|
|
||||||
view->update_scroll = false;
|
view->update_scroll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,11 +374,10 @@ void Command_KillSelectedLines(View *view) {
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
|
||||||
BeforeEdit(buffer, view->carets);
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
|
|
||||||
Array<Range> lines = GetSelectedLinesSorted(scratch, view);
|
Array<Range> lines = GetSelectedLinesSorted(scratch, view);
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
For(lines) {
|
For(lines) {
|
||||||
|
|
||||||
Range add_range = GetLineRange(*buffer, it.min);
|
Range add_range = GetLineRange(*buffer, it.min);
|
||||||
@@ -406,16 +394,15 @@ void Command_KillSelectedLines(View *view) {
|
|||||||
it.range.min = it.range.max = range.min;
|
it.range.min = it.range.max = range.min;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets, KILL_SELECTION);
|
||||||
AfterEdit(buffer, &edits, &view->carets, KILL_SELECTION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Command_Delete(View *view, int direction, bool ctrl = false) {
|
void Command_Delete(View *view, int direction, bool ctrl = false) {
|
||||||
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
|
||||||
|
|
||||||
BeforeEdit(buffer, view->carets);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
|
|
||||||
// Select things to delete
|
// Select things to delete
|
||||||
For(view->carets) {
|
For(view->carets) {
|
||||||
@@ -442,10 +429,8 @@ void Command_Delete(View *view, int direction, bool ctrl = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
For(view->carets) AddEdit(&edits, it.range, {});
|
For(view->carets) AddEdit(&edits, it.range, {});
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets);
|
||||||
AfterEdit(buffer, &edits, &view->carets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Command_SelectAll(View *view, String16 needle) {
|
void Command_SelectAll(View *view, String16 needle) {
|
||||||
@@ -579,9 +564,8 @@ Array<Range> FindAllInBuffer(Allocator allocator, Buffer *buffer, String16 needl
|
|||||||
void Command_IdentedNewLine(View *view) {
|
void Command_IdentedNewLine(View *view) {
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
BeforeEdit(buffer, view->carets);
|
Array<Edit> edits = BeginEdit(scratch, buffer, view->carets);
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
For(view->carets) {
|
For(view->carets) {
|
||||||
Int front = GetFront(it);
|
Int front = GetFront(it);
|
||||||
Int line = PosToLine(*buffer, front);
|
Int line = PosToLine(*buffer, front);
|
||||||
@@ -590,8 +574,7 @@ void Command_IdentedNewLine(View *view) {
|
|||||||
String16 string16 = ToString16(scratch, string);
|
String16 string16 = ToString16(scratch, string);
|
||||||
AddEdit(&edits, it.range, string16);
|
AddEdit(&edits, it.range, string16);
|
||||||
}
|
}
|
||||||
ApplyEdits(buffer, edits);
|
EndEdit(buffer, &edits, &view->carets);
|
||||||
AfterEdit(buffer, &edits, &view->carets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowCommand(Event event, Window *window, View *view) {
|
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)) {
|
} else if (Ctrl(SDLK_V)) {
|
||||||
Command_Paste(view);
|
Command_Paste(view);
|
||||||
} else if (Ctrl(SDLK_X)) {
|
} else if (Ctrl(SDLK_X)) {
|
||||||
BeforeEdit(buffer, view->carets);
|
PreBeginEdit_SaveCaretHistory(buffer, view->carets);
|
||||||
Command_Copy(view);
|
Command_Copy(view);
|
||||||
Command_Replace(view, L"");
|
Command_Replace(view, L"");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
- search as a command to execute which is going to be in the title bar
|
- search as a command to execute which is going to be in the title bar
|
||||||
- maybe modify api BeginEdit - EndEdit
|
|
||||||
|
|
||||||
- search backwards
|
- 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)
|
- 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)
|
||||||
|
|||||||
Reference in New Issue
Block a user