Files
text_editor/src/text_editor/window_command.cpp

188 lines
6.5 KiB
C++

void CommandWindowInit() {
Window *window = CreateWind();
CommandWindowID = window->id;
Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "command_bar"));
buffer->special = true;
View *view = CreateView(buffer->id);
view->special = true;
window->active_view = view->id;
window->draw_line_numbers = false;
window->draw_scrollbar = false;
window->draw_darker = true;
window->draw_line_highlight = true;
window->layout = false;
window->visible = false;
window->sync_visibility_with_focus = true;
window->lose_focus_on_escape = true;
window->jump_history = false;
}
void CommandWindowLayout(Rect2I *rect, Int wx, Int wy) {
Window *n = GetWindow(CommandWindowID);
Rect2I copy_rect = *rect;
if (!n->visible) {
rect = &copy_rect;
}
Int barsize = Clamp((Int)n->font->line_spacing*10, (Int)0, (Int)wx - 100);
n->document_rect = n->total_rect = CutBottom(rect, barsize);
}
int32_t FuzzyRate(String16 string, String16 with) {
ProfileFunction();
if (with.len == 0) return 0;
int32_t points = 0;
int32_t consecutive = 0;
int32_t with_i = 0;
for (int32_t i = 0; i < string.len; i++) {
if (ToLowerCase(string.data[i]) == ToLowerCase(with[with_i])) {
consecutive += 1;
with_i += 1;
} else {
with_i = 0;
points += consecutive * consecutive;
consecutive = 0;
}
if (with_i >= with.len) with_i = 0;
}
points += consecutive * consecutive;
return points;
}
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);
int32_t 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 CommandWindowUpdate() {
ProfileFunction();
BSet active = GetBSet(ActiveWindowID);
if (active.window->id == CommandWindowID) {
if (!ProcessIsActive(active.view->id)) {
Scratch scratch;
String16 line_string = GetLineStringWithoutNL(active.buffer, 0);
if (active.view->prev_search_line != line_string) {
active.view->prev_search_line = line_string;
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 Command_ShowCommands() {
if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == Command_ShowCommands) {
NextActiveWindowID = LastActiveLayoutWindowID;
return;
}
ProfileFunction();
BSet command_bar = GetBSet(CommandWindowID);
command_bar.window->visible = true;
NextActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer);
For (CommandFunctions) {
if (it.name == "OpenCommand") {
continue;
}
RawAppendf(command_bar.buffer, "\n:%S", it.name);
}
command_bar.view->update_scroll = true;
SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer));
} RegisterCommand(Command_ShowCommands, "ctrl-shift-p");
void Command_ShowDebugBufferList() {
if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == Command_ShowDebugBufferList) {
NextActiveWindowID = LastActiveLayoutWindowID;
return;
}
ProfileFunction();
BSet command_bar = GetBSet(CommandWindowID);
command_bar.window->visible = true;
NextActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer);
For (Buffers) {
RawAppendf(command_bar.buffer, "\n%S", it->name);
}
command_bar.view->update_scroll = true;
SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer));
} RegisterCommand(Command_ShowDebugBufferList, "");
void Command_ShowBufferList() {
if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == Command_ShowBufferList) {
NextActiveWindowID = LastActiveLayoutWindowID;
return;
}
ProfileFunction();
BSet command_bar = GetBSet(CommandWindowID);
command_bar.window->visible = true;
NextActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer);
For (Buffers) {
if (it->special || it->temp) {
continue;
}
RawAppendf(command_bar.buffer, "\n%S", it->name);
}
command_bar.view->update_scroll = true;
SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer));
} RegisterCommand(Command_ShowBufferList, "ctrl-p");
void OpenCommand(BSet active) {
ProfileFunction();
Range range = active.view->carets[0].range;
String16 string = FetchLoadWord(active.view);
if (GetSize(range) == 0) {
Int line = PosToLine(active.buffer, range.min);
if (line == 0) {
line = ClampTop(1ll, active.buffer->line_starts.len - 1ll);
}
string = GetLineStringWithoutNL(active.buffer, line);
}
Open(string);
}
void Command_OpenCommand() {
if (ActiveWindowID != CommandWindowID) {
return;
}
BSet active = GetBSet(ActiveWindowID);
BSet main = GetBSet(LastActiveLayoutWindowID);
NextActiveWindowID = main.window->id;
OpenCommand(active);
} RegisterCommand(Command_OpenCommand, "ctrl-q | enter");