From 8b8229f73a4540ec8335a1450b10285b8f73c3d7 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Wed, 24 Jul 2024 13:23:20 +0200 Subject: [PATCH] Line range refactor --- src/text_editor/buffer.cpp | 19 +++++++ src/text_editor/buffer_fuzzy_search.cpp | 52 ++++++++++++++++++ src/text_editor/commands_window.cpp | 72 ++++--------------------- src/text_editor/text_editor.cpp | 1 + src/text_editor/text_editor.h | 4 +- src/text_editor/window_draw.cpp | 6 +-- 6 files changed, 85 insertions(+), 69 deletions(-) create mode 100644 src/text_editor/buffer_fuzzy_search.cpp diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index 2b54757..03550bb 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -64,6 +64,25 @@ Range GetLineRange(Buffer &buffer, Int line, Int *end_of_buffer = NULL) { return result; } +String16 GetLineString(Buffer &buffer, Int line, Int *end_of_buffer = NULL) { + Range range = GetLineRange(buffer, line, end_of_buffer); + String16 string = GetString(buffer, range); + return string; +} + +Range GetLineRangeWithoutNL(Buffer &buffer, Int line) { + Int end_of_buffer = 0; + Range line_range = GetLineRange(buffer, line, &end_of_buffer); + line_range.max = line_range.max - 1 + end_of_buffer; + return line_range; +} + +String16 GetLineStringWithoutNL(Buffer &buffer, Int line) { + Range range = GetLineRangeWithoutNL(buffer, line); + String16 string = GetString(buffer, range); + return string; +} + Int PosToLine(Buffer &buffer, Int pos) { Add(&buffer.line_starts, buffer.len + 1); diff --git a/src/text_editor/buffer_fuzzy_search.cpp b/src/text_editor/buffer_fuzzy_search.cpp new file mode 100644 index 0000000..fdfca9b --- /dev/null +++ b/src/text_editor/buffer_fuzzy_search.cpp @@ -0,0 +1,52 @@ +struct FuzzyPair { + Int index; + Int rating; +}; + +int64_t FuzzyCloserWordBegin = 5; +int64_t FuzzyConsecutiveMultiplier = 3; +int64_t FuzzyRate(String16 string, String16 with) { + int64_t points = 0; + int64_t consecutive = 0; + int64_t with_i = 0; + for (int64_t i = 0; i < string.len; i++) { + if (string.data[i] == with[with_i]) { + int64_t closer_begin = ClampBottom((int64_t)0, FuzzyCloserWordBegin - i); + points += closer_begin; + consecutive++; + with_i += 1; + } else { + points += consecutive * FuzzyConsecutiveMultiplier; + consecutive = 0; + with_i = 0; + } + + if (with_i >= with.len) with_i = 0; + } + points += consecutive * FuzzyConsecutiveMultiplier; + return points; +} + +Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle) { + Assert(line_min >= 0 && line_min < buffer->line_starts.len); + Assert(line_max >= 0 && line_max <= buffer->line_starts.len); + Array ratings = {allocator}; + for (Int i = line_min; i < line_max; i += 1) { + String16 s = GetLineStringWithoutNL(*buffer, i); + int64_t rating = FuzzyRate(s, needle); + Add(&ratings, {i, rating}); + } + + // bubble sort + for (int64_t i = 0; i < ratings.len - 1; i++) { + for (int64_t j = 0; j < ratings.len - 1; j++) { + if (ratings[j].rating < ratings[j + 1].rating) { + FuzzyPair temp = ratings[j]; + ratings[j] = ratings[j + 1]; + ratings[j + 1] = temp; + } + } + } + + return ratings; +} diff --git a/src/text_editor/commands_window.cpp b/src/text_editor/commands_window.cpp index c08844e..b42fde2 100644 --- a/src/text_editor/commands_window.cpp +++ b/src/text_editor/commands_window.cpp @@ -59,12 +59,11 @@ void Command_MoveCursorsToSide(Window *window, int direction, bool shift = false Buffer *buffer = GetBuffer(view.buffer_id); For(view.carets) { - Int end_of_buffer = 0; - Range line_range = GetLineRange(*buffer, PosToLine(*buffer, GetFront(it)), &end_of_buffer); + Range line_range = GetLineRangeWithoutNL(*buffer, PosToLine(*buffer, GetFront(it))); Int pos = line_range.min; if (direction == DIR_RIGHT) { - pos = line_range.max - (1 - end_of_buffer); + pos = line_range.max; } if (shift) { @@ -124,30 +123,6 @@ void Command_SelectEntireBuffer(View *view) { view->carets[0] = MakeCaret(0, buffer->len); } -int64_t FuzzyCloserWordBegin = 5; -int64_t FuzzyConsecutiveMultiplier = 3; -int64_t FuzzyRate(String16 string, String16 with) { - int64_t points = 0; - int64_t consecutive = 0; - int64_t with_i = 0; - for (int64_t i = 0; i < string.len; i++) { - if (string.data[i] == with[with_i]) { - int64_t closer_begin = ClampBottom((int64_t)0, FuzzyCloserWordBegin - i); - points += closer_begin; - consecutive++; - with_i += 1; - } else { - points += consecutive * FuzzyConsecutiveMultiplier; - consecutive = 0; - with_i = 0; - } - - if (with_i >= with.len) with_i = 0; - } - points += consecutive * FuzzyConsecutiveMultiplier; - return points; -} - void HandleActiveWindowBindings(Window *window) { View &view = *GetActiveView(window); Buffer *buffer = GetBuffer(view.buffer_id); @@ -334,39 +309,14 @@ void HandleActiveWindowBindings(Window *window) { } if (window->fuzzy_search && search) { - Range line_range = GetLineRange(*buffer, 0); - String16 string = GetString(*buffer, line_range); + Scratch scratch; + String16 first_line_string = GetLineStringWithoutNL(*buffer, 0); + Array ratings = FuzzySearchLines(scratch, buffer, 1, buffer->line_starts.len, first_line_string); - Scratch scratch; - struct Pair { - Int index; - Int rating; - }; - Array ratings = {scratch}; - for (Int i = 1; i < buffer->line_starts.len; i += 1) { - Range l = GetLineRange(*buffer, i); - String16 s = GetString(*buffer, l); - int64_t rating = FuzzyRate(s, string); - Add(&ratings, {i, rating}); - } - - // bubble sort - for (int64_t i = 0; i < ratings.len - 1; i++) { - for (int64_t j = 0; j < ratings.len - 1; j++) { - if (ratings[j].rating < ratings[j + 1].rating) { - Pair temp = ratings[j]; - ratings[j] = ratings[j + 1]; - ratings[j + 1] = temp; - } - } - } - - // Create a new buffer with Buffer *temp_buffer = CreateTempBuffer(scratch, buffer->cap); - ReplaceText(temp_buffer, {}, string); + ReplaceText(temp_buffer, GetEndAsRange(*temp_buffer), first_line_string); For(ratings) { - Range l = GetLineRange(*buffer, it.index); - String16 s = GetString(*buffer, l); + String16 s = GetLineString(*buffer, it.index); ReplaceText(temp_buffer, GetEndAsRange(*temp_buffer), s); } @@ -380,8 +330,7 @@ void HandleActiveWindowBindings(Window *window) { if (Press(KEY_ENTER)) { Scratch scratch; Int line = PosToLine(*buffer, GetFront(view.carets[0])); - Range range = GetLineRange(*buffer, line); - String16 string = GetString(*buffer, range); + String16 string = GetLineStringWithoutNL(*buffer, line); String16 eval_result = EvalString(scratch, string); if (Ctrl() && eval_result.len) { @@ -405,10 +354,7 @@ void HandleActiveWindowBindings(Window *window) { Command_Replace(view, eval_result); } - Int end_of_buffer = 0; - Range range = GetLineRange(*buffer, 0, &end_of_buffer); - range.max -= 1; - range.max += end_of_buffer; + Range range = GetLineRangeWithoutNL(*buffer, 0); Command_SelectRange(&view, range); Command_Replace(&view, {}); } diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index f0c1dc5..91b329d 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -17,6 +17,7 @@ #include "buffer.cpp" #include "buffer_multi_cursor.cpp" #include "buffer_history.cpp" +#include "buffer_fuzzy_search.cpp" #include "buffer_test_load.cpp" #include "management.cpp" diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h index 706d202..c20a53b 100644 --- a/src/text_editor/text_editor.h +++ b/src/text_editor/text_editor.h @@ -106,8 +106,8 @@ Int FrameID; Int LastFrameIDWhenScrolled; Int LastFrameIDWhenSwitchedActiveWindow; -Array WindowSwitchHistory; -WindowID ActiveWindow = {}; +Array WindowSwitchHistory; // @todo: probably better as a circular buffer +WindowID ActiveWindow; String16 EvalString(Allocator allocator, String16 string16); Rect2I GetVisibleCells(Window &window); diff --git a/src/text_editor/window_draw.cpp b/src/text_editor/window_draw.cpp index 2dffd7e..030a7bc 100644 --- a/src/text_editor/window_draw.cpp +++ b/src/text_editor/window_draw.cpp @@ -46,8 +46,7 @@ void DrawVisibleText(Window &window) { Rect2I visible = GetVisibleCells(window); for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < buffer->line_starts.len; line_index += 1) { - Range line_range = GetLineRange(*buffer, line_index); - String16 line_string = GetString(*buffer, line_range); + String16 line_string = GetLineString(*buffer, line_index); Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing}; pos -= view.scroll; @@ -118,8 +117,7 @@ void DrawSelection(Window &window, Caret &it) { Color color = ColorSelection; Rect2I vlines = GetVisibleCells(window); for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < buffer->line_starts.len; line += 1) { - Range range = GetLineRange(*buffer, line); - String16 line_string = GetString(*buffer, range); + String16 line_string = GetLineString(*buffer, line); for (Int col = vlines.min.x; col < vlines.max.x && col >= 0 && col < line_string.len; col += 1) { bool a = line > min.line && line < max.line;