Files
text_editor/src/text_editor/fuzzy_search_view.cpp
T

136 lines
4.5 KiB
C++

String16 FetchFuzzyViewLoadLine(View *view) {
Buffer *buffer = GetBuffer(view->active_buffer);
Range range = view->carets[0].range;
String16 string = GetString(buffer, range);
if (GetSize(range) == 0) {
Int line = PosToLine(buffer, range.min);
if (line == 0) {
line = ClampTop(1ll, buffer->line_starts.len - 1ll);
}
string = GetLineStringWithoutNL(buffer, line);
Int idx = 0;
String16 delim = u"||>";
if (Seek(string, delim, &idx, SeekFlag_None)) {
string = Skip(string, idx + delim.len);
}
}
return string;
}
void OpenCommand(BSet active) {
String16 string = FetchFuzzyViewLoadLine(active.view);
Open(string);
}
float NewFuzzyRate(String16 s, String16 p) {
float score = 0;
// try to do this: https://github.com/junegunn/fzf/blob/master/src/algo/algo.go
return score;
}
float FuzzyRate(String16 s, String16 p) {
float score = 0;
for (Int outer_pi = 0; outer_pi < p.len; outer_pi += 1) {
String16 pit = Skip(p, outer_pi);
if (IsWhitespace(At(pit, 0))) {
continue;
}
float matching = 0;
for (Int outer_si = 0; outer_si < s.len; outer_si += 1) {
String16 sit = Skip(s, outer_si);
if (IsWhitespace(At(sit, 0))) {
continue;
}
Int si = 0;
Int pi = 0;
for (;si < sit.len && pi < pit.len;) {
while (si < sit.len && IsWhitespace(sit[si])) si += 1;
while (pi < pit.len && IsWhitespace(pit[pi])) pi += 1;
if (pi >= pit.len) break;
if (si >= sit.len) break;
if (ToLowerCase(sit[si]) == ToLowerCase(pit[pi])) {
matching += 1.0f;
} else {
break;
}
si += 1;
pi += 1;
}
}
score += matching;
}
score = score / (float)s.len;
return score;
}
inline bool MergeSortCompare(FuzzyPair *a, FuzzyPair *b) {
bool result = a->rating > b->rating;
return result;
}
Array<FuzzyPair> FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle) {
ProfileFunction();
if (line_min < 0 || line_min >= buffer->line_starts.len) return {};
if (line_max < 0 || line_min > buffer->line_starts.len) return {};
Array<FuzzyPair> ratings = {allocator};
Reserve(&ratings, line_max - line_min + 4);
for (Int i = line_min; i < line_max; i += 1) {
String16 s = GetLineStringWithoutNL(buffer, i);
Int idx = 0;
if (Seek(s, u"||>", &idx, SeekFlag_None)) {
s = GetPrefix(s, idx);
} else if (Seek(s, u"<||", &idx, SeekFlag_None)) {
s = GetPrefix(s, idx);
}
s = Trim(s);
float rating = FuzzyRate(s, needle);
Add(&ratings, {(int32_t)i, rating});
}
Array<FuzzyPair> temp = Copy(allocator, ratings);
MergeSort(ratings.len, ratings.data, temp.data);
return ratings;
}
void UpdateFuzzySearchView() {
Scratch scratch;
BSet active = GetBSet(ActiveWindowID);
String16 line_string = GetLineStringWithoutNL(active.buffer, 0);
uint64_t hash = HashBytes(line_string.data, line_string.len * sizeof(char16_t));
if (active.view->prev_search_line_hash != hash) {
active.view->prev_search_line_hash = hash;
Array<FuzzyPair> ratings = FuzzySearchLines(scratch, active.buffer, 1, active.buffer->line_starts.len, line_string);
Buffer *scratch_buff = CreateScratchBuffer(scratch, active.buffer->cap);
RawAppend(scratch_buff, line_string);
For(IterateInReverse(&ratings)) {
String16 s = GetLineStringWithoutNL(active.buffer, it.index);
if (s.len == 0) continue;
RawAppend(scratch_buff, u"\n");
RawAppend(scratch_buff, s);
}
Caret caret = active.view->carets[0];
SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets);
SelectEntireBuffer(active.view);
Replace(active.view, GetString(scratch_buff));
active.view->carets[0] = caret;
}
}
void SetFuzzy(View *view) {
AddCommand(&view->commands, "Open", "ctrl-q | enter | f12", [](){
BSet active = GetBSet(ActiveWindowID);
BSet main = GetBSet(PrimaryWindowID);
NextActiveWindowID = main.window->id;
String16 string = FetchFuzzyViewLoadLine(active.view);
Open(string);
});
view->update_hook = UpdateFuzzySearchView;
}