Line range refactor
This commit is contained in:
@@ -64,6 +64,25 @@ Range GetLineRange(Buffer &buffer, Int line, Int *end_of_buffer = NULL) {
|
|||||||
return result;
|
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) {
|
Int PosToLine(Buffer &buffer, Int pos) {
|
||||||
Add(&buffer.line_starts, buffer.len + 1);
|
Add(&buffer.line_starts, buffer.len + 1);
|
||||||
|
|
||||||
|
|||||||
52
src/text_editor/buffer_fuzzy_search.cpp
Normal file
52
src/text_editor/buffer_fuzzy_search.cpp
Normal file
@@ -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<FuzzyPair> 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<FuzzyPair> 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;
|
||||||
|
}
|
||||||
@@ -59,12 +59,11 @@ void Command_MoveCursorsToSide(Window *window, int direction, bool shift = false
|
|||||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
|
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
Int end_of_buffer = 0;
|
Range line_range = GetLineRangeWithoutNL(*buffer, PosToLine(*buffer, GetFront(it)));
|
||||||
Range line_range = GetLineRange(*buffer, PosToLine(*buffer, GetFront(it)), &end_of_buffer);
|
|
||||||
|
|
||||||
Int pos = line_range.min;
|
Int pos = line_range.min;
|
||||||
if (direction == DIR_RIGHT) {
|
if (direction == DIR_RIGHT) {
|
||||||
pos = line_range.max - (1 - end_of_buffer);
|
pos = line_range.max;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shift) {
|
if (shift) {
|
||||||
@@ -124,30 +123,6 @@ void Command_SelectEntireBuffer(View *view) {
|
|||||||
view->carets[0] = MakeCaret(0, buffer->len);
|
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) {
|
void HandleActiveWindowBindings(Window *window) {
|
||||||
View &view = *GetActiveView(window);
|
View &view = *GetActiveView(window);
|
||||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
@@ -334,39 +309,14 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (window->fuzzy_search && search) {
|
if (window->fuzzy_search && search) {
|
||||||
Range line_range = GetLineRange(*buffer, 0);
|
|
||||||
String16 string = GetString(*buffer, line_range);
|
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
struct Pair {
|
String16 first_line_string = GetLineStringWithoutNL(*buffer, 0);
|
||||||
Int index;
|
Array<FuzzyPair> ratings = FuzzySearchLines(scratch, buffer, 1, buffer->line_starts.len, first_line_string);
|
||||||
Int rating;
|
|
||||||
};
|
|
||||||
Array<Pair> 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);
|
Buffer *temp_buffer = CreateTempBuffer(scratch, buffer->cap);
|
||||||
ReplaceText(temp_buffer, {}, string);
|
ReplaceText(temp_buffer, GetEndAsRange(*temp_buffer), first_line_string);
|
||||||
For(ratings) {
|
For(ratings) {
|
||||||
Range l = GetLineRange(*buffer, it.index);
|
String16 s = GetLineString(*buffer, it.index);
|
||||||
String16 s = GetString(*buffer, l);
|
|
||||||
ReplaceText(temp_buffer, GetEndAsRange(*temp_buffer), s);
|
ReplaceText(temp_buffer, GetEndAsRange(*temp_buffer), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,8 +330,7 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
if (Press(KEY_ENTER)) {
|
if (Press(KEY_ENTER)) {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Int line = PosToLine(*buffer, GetFront(view.carets[0]));
|
Int line = PosToLine(*buffer, GetFront(view.carets[0]));
|
||||||
Range range = GetLineRange(*buffer, line);
|
String16 string = GetLineStringWithoutNL(*buffer, line);
|
||||||
String16 string = GetString(*buffer, range);
|
|
||||||
String16 eval_result = EvalString(scratch, string);
|
String16 eval_result = EvalString(scratch, string);
|
||||||
|
|
||||||
if (Ctrl() && eval_result.len) {
|
if (Ctrl() && eval_result.len) {
|
||||||
@@ -405,10 +354,7 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
Command_Replace(view, eval_result);
|
Command_Replace(view, eval_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Int end_of_buffer = 0;
|
Range range = GetLineRangeWithoutNL(*buffer, 0);
|
||||||
Range range = GetLineRange(*buffer, 0, &end_of_buffer);
|
|
||||||
range.max -= 1;
|
|
||||||
range.max += end_of_buffer;
|
|
||||||
Command_SelectRange(&view, range);
|
Command_SelectRange(&view, range);
|
||||||
Command_Replace(&view, {});
|
Command_Replace(&view, {});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "buffer.cpp"
|
#include "buffer.cpp"
|
||||||
#include "buffer_multi_cursor.cpp"
|
#include "buffer_multi_cursor.cpp"
|
||||||
#include "buffer_history.cpp"
|
#include "buffer_history.cpp"
|
||||||
|
#include "buffer_fuzzy_search.cpp"
|
||||||
#include "buffer_test_load.cpp"
|
#include "buffer_test_load.cpp"
|
||||||
|
|
||||||
#include "management.cpp"
|
#include "management.cpp"
|
||||||
|
|||||||
@@ -106,8 +106,8 @@ Int FrameID;
|
|||||||
Int LastFrameIDWhenScrolled;
|
Int LastFrameIDWhenScrolled;
|
||||||
|
|
||||||
Int LastFrameIDWhenSwitchedActiveWindow;
|
Int LastFrameIDWhenSwitchedActiveWindow;
|
||||||
Array<WindowID> WindowSwitchHistory;
|
Array<WindowID> WindowSwitchHistory; // @todo: probably better as a circular buffer
|
||||||
WindowID ActiveWindow = {};
|
WindowID ActiveWindow;
|
||||||
|
|
||||||
String16 EvalString(Allocator allocator, String16 string16);
|
String16 EvalString(Allocator allocator, String16 string16);
|
||||||
Rect2I GetVisibleCells(Window &window);
|
Rect2I GetVisibleCells(Window &window);
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ void DrawVisibleText(Window &window) {
|
|||||||
|
|
||||||
Rect2I visible = GetVisibleCells(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) {
|
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 = GetLineString(*buffer, line_index);
|
||||||
String16 line_string = GetString(*buffer, line_range);
|
|
||||||
|
|
||||||
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
||||||
pos -= view.scroll;
|
pos -= view.scroll;
|
||||||
@@ -118,8 +117,7 @@ void DrawSelection(Window &window, Caret &it) {
|
|||||||
Color color = ColorSelection;
|
Color color = ColorSelection;
|
||||||
Rect2I vlines = GetVisibleCells(window);
|
Rect2I vlines = GetVisibleCells(window);
|
||||||
for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < buffer->line_starts.len; line += 1) {
|
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 = GetLineString(*buffer, line);
|
||||||
String16 line_string = GetString(*buffer, range);
|
|
||||||
|
|
||||||
for (Int col = vlines.min.x; col < vlines.max.x && col >= 0 && col < line_string.len; col += 1) {
|
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;
|
bool a = line > min.line && line < max.line;
|
||||||
|
|||||||
Reference in New Issue
Block a user