WordComplete working
This commit is contained in:
@@ -218,14 +218,14 @@ void CMD_KillProcess() {
|
|||||||
void CMD_MakeFontLarger() {
|
void CMD_MakeFontLarger() {
|
||||||
FontSize += 1;
|
FontSize += 1;
|
||||||
ReloadFont(PathToFont, (U32)FontSize);
|
ReloadFont(PathToFont, (U32)FontSize);
|
||||||
CMD_CenterView();
|
CenterPrimaryViews();
|
||||||
} RegisterCommand(CMD_MakeFontLarger, "ctrl-equals", "Increase the font size");
|
} RegisterCommand(CMD_MakeFontLarger, "ctrl-equals", "Increase the font size");
|
||||||
|
|
||||||
void CMD_MakeFontSmaller() {
|
void CMD_MakeFontSmaller() {
|
||||||
if (FontSize > 4) {
|
if (FontSize > 4) {
|
||||||
FontSize -= 1;
|
FontSize -= 1;
|
||||||
ReloadFont(PathToFont, (U32)FontSize);
|
ReloadFont(PathToFont, (U32)FontSize);
|
||||||
CMD_CenterView();
|
CenterPrimaryViews();
|
||||||
}
|
}
|
||||||
} RegisterCommand(CMD_MakeFontSmaller, "ctrl-minus", "Decrease the font size");
|
} RegisterCommand(CMD_MakeFontSmaller, "ctrl-minus", "Decrease the font size");
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ Int ErrorCount;
|
|||||||
#if 1
|
#if 1
|
||||||
String16 InitialScratchContent;
|
String16 InitialScratchContent;
|
||||||
#else
|
#else
|
||||||
String16 InitialScratchContent = uR"==(0
|
String16 InitialScratchContent = uR"==(C:/text_editor/src/text_editor/text_editor.cpp
|
||||||
|
0
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ void CMD_KillSelectedLines() {
|
|||||||
void CMD_IndentSelectedLines() {
|
void CMD_IndentSelectedLines() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
IndentSelectedLines(active.view);
|
IndentSelectedLines(active.view);
|
||||||
} RegisterCommand(CMD_IndentSelectedLines, "ctrl-rightbracket | tab", "");
|
} RegisterCommand(CMD_IndentSelectedLines, "ctrl-rightbracket", "");
|
||||||
|
|
||||||
void CMD_DedentSelectedLines() {
|
void CMD_DedentSelectedLines() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
IndentSelectedLines(active.view, true);
|
IndentSelectedLines(active.view, true);
|
||||||
} RegisterCommand(CMD_DedentSelectedLines, "ctrl-leftbracket | shift-tab", "");
|
} RegisterCommand(CMD_DedentSelectedLines, "ctrl-leftbracket", "");
|
||||||
|
|
||||||
void CMD_DuplicateLineDown() {
|
void CMD_DuplicateLineDown() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// MAAAAAAAAAAAAN I DONT LIKE THIS CODE, BUT HOPE IT WORKS
|
||||||
|
|
||||||
struct Lexer2 {
|
struct Lexer2 {
|
||||||
char16_t *at;
|
char16_t *at;
|
||||||
};
|
};
|
||||||
@@ -8,71 +10,213 @@ Lexer2 BeginLexing(String16 data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String16 Next(Lexer2 *lexer) {
|
String16 Next(Lexer2 *lexer) {
|
||||||
while (lexer->at[0] != 0 && !IsAlphanumeric(lexer->at[0])) {
|
while (lexer->at[0] != 0 && IsNonWord(lexer->at[0])) {
|
||||||
lexer->at += 1;
|
lexer->at += 1;
|
||||||
}
|
}
|
||||||
String16 result = {lexer->at, 0};
|
String16 result = {lexer->at, 0};
|
||||||
while (IsAlphanumeric(lexer->at[0])) {
|
while (lexer->at[0] != 0 && IsWord(lexer->at[0])) {
|
||||||
lexer->at += 1;
|
lexer->at += 1;
|
||||||
result.len += 1;
|
result.len += 1;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WordCompleteS {
|
struct StringAndDistance {
|
||||||
String16 string;
|
String16 string;
|
||||||
Int distance;
|
Int distance;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Contains(Array<WordCompleteS> *arr, String16 string) {
|
bool Contains(Array<StringAndDistance> *arr, String16 string) {
|
||||||
For (*arr) {
|
For (*arr) {
|
||||||
if (it.string == string) return true;
|
if (it.string == string) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool MergeSortCompare(WordCompleteS *EntryA, WordCompleteS *EntryB) {
|
inline bool MergeSortCompare(StringAndDistance *EntryA, StringAndDistance *EntryB) {
|
||||||
bool result = EntryA->distance > EntryB->distance;
|
bool result = EntryA->distance > EntryB->distance;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMD_WordComplete() {
|
struct {
|
||||||
// @todo: handle multiple carets
|
BlockArena arena;
|
||||||
// @todo: indent when shift otherwise wordcomplte
|
String16 prefix_string;
|
||||||
// @todo: loop through buffers
|
String16 last_string;
|
||||||
// @todo: iterate by pressing 'tab' continously
|
mco_coro *co;
|
||||||
Scratch scratch;
|
Buffer *buffer;
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
View *view;
|
||||||
Caret caret = active.view->carets[0];
|
Int original_caret_pos;
|
||||||
Range range = caret.range;
|
Int direction;
|
||||||
if (GetSize(range) != 0) {
|
} CWS;
|
||||||
return;
|
|
||||||
}
|
|
||||||
range.min = GetWordStart(active.buffer, range.min);
|
|
||||||
String16 prefix = GetString(active.buffer, range);
|
|
||||||
|
|
||||||
String16 string = GetString(active.buffer);
|
void CWSLexIdentifiers(Array<StringAndDistance> *out_idents, Buffer *buffer) {
|
||||||
|
Array<StringAndDistance> idents = {CWS.arena};
|
||||||
Array<WordCompleteS> idents = {scratch};
|
String16 string = GetString(buffer);
|
||||||
Lexer2 lexer = BeginLexing(string.data);
|
Lexer2 lexer = BeginLexing(string.data);
|
||||||
for (int i = 0;; i += 1) {
|
for (int i = 0;; i += 1) {
|
||||||
String16 token = Next(&lexer);
|
String16 token = Next(&lexer);
|
||||||
if (token.len <= 0) break;
|
if (token.len <= 0) {
|
||||||
if (StartsWith(token, prefix) && token != prefix && !Contains(&idents, token)) {
|
break;
|
||||||
Int pos = token.data - active.buffer->str;
|
}
|
||||||
Int distance = Absolute(range.min - pos);
|
if (StartsWith(token, CWS.prefix_string) && token != CWS.prefix_string && !Contains(&idents, token)) {
|
||||||
Add(&idents, {token, distance});
|
Int pos = token.data - buffer->str;
|
||||||
|
Int distance = Absolute(CWS.original_caret_pos - pos);
|
||||||
|
Add(&idents, {Copy16(CWS.arena, token), distance});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idents.len > 1) {
|
if (idents.len > 1) {
|
||||||
Array<WordCompleteS> temp = TightCopy(scratch, idents);
|
Array<StringAndDistance> temp = TightCopy(CWS.arena, idents);
|
||||||
MergeSort(idents.len, idents.data, temp.data);
|
MergeSort(idents.len, idents.data, temp.data);
|
||||||
}
|
}
|
||||||
if (idents.len > 0) {
|
For (idents) {
|
||||||
String16 ident = idents[0].string;
|
if (!Contains(out_idents, it.string)) Add(out_idents, it);
|
||||||
ident = Skip(ident, prefix.len);
|
|
||||||
ident = Copy16(scratch, ident);
|
|
||||||
Replace(active.view, ident);
|
|
||||||
}
|
}
|
||||||
} RegisterCommand(CMD_WordComplete, "ctrl-b", "Completes the current word");
|
}
|
||||||
|
|
||||||
|
void CompleteWord2(mco_coro *co) {
|
||||||
|
Array<BufferID> buffers = {CWS.arena};
|
||||||
|
{
|
||||||
|
Add(&buffers, CWS.buffer->id);
|
||||||
|
ForItem (window, Windows) {
|
||||||
|
if (window->visible) {
|
||||||
|
View *view = GetView(window->active_view);
|
||||||
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
if (!Contains(buffers, buffer->id)) {
|
||||||
|
Add(&buffers, buffer->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Int len = 0;
|
||||||
|
For (IterateInReverse(&window->goto_history)) {
|
||||||
|
View *view = GetView(it.view_id);
|
||||||
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
if (!Contains(buffers, buffer->id)) {
|
||||||
|
Add(&buffers, buffer->id);
|
||||||
|
len += 1;
|
||||||
|
if (len > 16) continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Window *active = GetWindow(ActiveWindowID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer *curr_buffer = NULL;
|
||||||
|
Int buffer_i = 0;
|
||||||
|
Array<StringAndDistance> idents = {CWS.arena};
|
||||||
|
Add(&idents, {CWS.prefix_string, 0});
|
||||||
|
for (Int i = 1;;) {
|
||||||
|
if (i >= idents.len) {
|
||||||
|
while (buffer_i < buffers.len) {
|
||||||
|
curr_buffer = GetBuffer(buffers[buffer_i++]);
|
||||||
|
CWSLexIdentifiers(&idents, curr_buffer);
|
||||||
|
if (i < idents.len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= idents.len) {
|
||||||
|
goto yield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StringAndDistance it = idents[i];
|
||||||
|
String16 ident = Copy16(CWS.arena, it.string);
|
||||||
|
CWS.last_string = ident;
|
||||||
|
Range range = EncloseWord(curr_buffer, CWS.original_caret_pos);
|
||||||
|
View *view = GetViewForFixingWhenBufferCommand(curr_buffer);
|
||||||
|
SelectRange(view, range);
|
||||||
|
Replace(view, ident);
|
||||||
|
yield:;
|
||||||
|
mco_yield(co);
|
||||||
|
i += CWS.direction;
|
||||||
|
i = Clamp(i, 0ll, idents.len - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompleteWord(View *view, Int pos) {
|
||||||
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
Range prefix_string_range = {GetWordStart(buffer, pos), pos};
|
||||||
|
String16 prefix = GetString(buffer, prefix_string_range);
|
||||||
|
bool continue_with_previous = CWS.co && CWS.last_string == prefix && CWS.buffer == buffer;
|
||||||
|
if (!continue_with_previous) {
|
||||||
|
if (CWS.co) {
|
||||||
|
mco_result res = mco_destroy(CWS.co);
|
||||||
|
Assert(res == MCO_SUCCESS);
|
||||||
|
CWS.co = NULL;
|
||||||
|
}
|
||||||
|
Release(&CWS.arena);
|
||||||
|
MemoryZero(&CWS, sizeof(CWS));
|
||||||
|
|
||||||
|
CWS.buffer = buffer;
|
||||||
|
CWS.view = view;
|
||||||
|
CWS.original_caret_pos = pos;
|
||||||
|
CWS.prefix_string = Copy16(CWS.arena, prefix);
|
||||||
|
|
||||||
|
mco_desc desc = mco_desc_init(CompleteWord2, NULL);
|
||||||
|
mco_result res = mco_create(&CWS.co, &desc);
|
||||||
|
Assert(res == MCO_SUCCESS);
|
||||||
|
}
|
||||||
|
CWS.direction = 1;
|
||||||
|
mco_result res = mco_resume(CWS.co);
|
||||||
|
Assert(res == MCO_SUCCESS);
|
||||||
|
|
||||||
|
if (mco_status(CWS.co) == MCO_DEAD) {
|
||||||
|
res = mco_destroy(CWS.co);
|
||||||
|
Assert(res == MCO_SUCCESS);
|
||||||
|
CWS.co = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CompletePrevWord(View *view, Int pos) {
|
||||||
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
Range prefix_string_range = {GetWordStart(buffer, pos), pos};
|
||||||
|
String16 prefix = GetString(buffer, prefix_string_range);
|
||||||
|
bool continue_with_previous = CWS.co && CWS.last_string == prefix && CWS.buffer == buffer;
|
||||||
|
if (!continue_with_previous) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CWS.direction = -1;
|
||||||
|
mco_result res = mco_resume(CWS.co);
|
||||||
|
Assert(res == MCO_SUCCESS);
|
||||||
|
if (mco_status(CWS.co) == MCO_DEAD) {
|
||||||
|
res = mco_destroy(CWS.co);
|
||||||
|
Assert(res == MCO_SUCCESS);
|
||||||
|
CWS.co = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMD_CompleteWord() {
|
||||||
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
bool ok = active.view->carets.len == 1 && GetSize(active.view->carets[0].range) == 0;
|
||||||
|
if (!ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CompleteWord(active.view, active.view->carets[0].range.min);
|
||||||
|
} RegisterCommand(CMD_CompleteWord, "", "Completes the current word");
|
||||||
|
|
||||||
|
void CMD_CompletePrevWord() {
|
||||||
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
bool ok = active.view->carets.len == 1 && GetSize(active.view->carets[0].range) == 0;
|
||||||
|
if (!ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CompletePrevWord(active.view, active.view->carets[0].range.min);
|
||||||
|
} RegisterCommand(CMD_CompletePrevWord, "", "Completes the current word");
|
||||||
|
|
||||||
|
void CMD_CompletePrevWordOrDedent() {
|
||||||
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
if (active.view->carets.len == 1 && GetSize(active.view->carets[0].range) == 0) {
|
||||||
|
CMD_CompletePrevWord();
|
||||||
|
} else {
|
||||||
|
IndentSelectedLines(active.view, true);
|
||||||
|
}
|
||||||
|
} RegisterCommand(CMD_CompletePrevWordOrDedent, "shift-tab", "Completes the current word or it indents it, when single caret with no selection it goes for word complete");
|
||||||
|
|
||||||
|
void CMD_CompleteWordOrIndent() {
|
||||||
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
if (active.view->carets.len == 1 && GetSize(active.view->carets[0].range) == 0) {
|
||||||
|
CMD_CompleteWord();
|
||||||
|
} else {
|
||||||
|
IndentSelectedLines(active.view);
|
||||||
|
}
|
||||||
|
} RegisterCommand(CMD_CompleteWordOrIndent, "tab", "Completes the current word or it indents it, when single caret with no selection it goes for word complete");
|
||||||
@@ -381,6 +381,14 @@ void CenterView(WindowID window) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CenterPrimaryViews() {
|
||||||
|
For (Windows) {
|
||||||
|
if (it->primary) {
|
||||||
|
CenterView(it->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BSet GetBSet(Window *window) {
|
BSet GetBSet(Window *window) {
|
||||||
BSet set = {window};
|
BSet set = {window};
|
||||||
set.view = GetView(set.window->active_view);
|
set.view = GetView(set.window->active_view);
|
||||||
|
|||||||
Reference in New Issue
Block a user