136 lines
4.5 KiB
C++
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;
|
|
}
|