Search case sensitive and word boundary

This commit is contained in:
Krzosa Karol
2025-12-27 15:54:10 +01:00
parent b6f3a1ebec
commit e4b84dde90
7 changed files with 110 additions and 32 deletions

View File

@@ -212,23 +212,51 @@ API bool Seek(String string, String find, int64_t *index_out, SeekFlag flags) {
int64_t index = i - 1; int64_t index = i - 1;
String substring = GetSlice(string, index, index + find.len); String substring = GetSlice(string, index, index + find.len);
if (AreEqual(substring, find, ignore_case)) { if (AreEqual(substring, find, ignore_case)) {
if (index_out) bool ok_boundary = true;
if (flags & SeekFlag_WordBoundary) {
String left = GetSlice(string, i - 1, i);
String right = GetSlice(string, i + find.len, i + find.len + 1);
if (left.len != 0 && !IsNonWord(left.data[0])) {
ok_boundary = false;
}
if (right.len != 0 && !IsNonWord(right.data[0])) {
ok_boundary = false;
}
}
if (ok_boundary) {
if (index_out) {
*index_out = index; *index_out = index;
}
result = true; result = true;
break; break;
} }
} }
}
} else { } else {
for (int64_t i = 0; i < string.len; i++) { for (int64_t i = 0; i < string.len; i++) {
String substring = GetSlice(string, i, i + find.len); String substring = GetSlice(string, i, i + find.len);
if (AreEqual(substring, find, ignore_case)) { if (AreEqual(substring, find, ignore_case)) {
if (index_out) bool ok_boundary = true;
if (flags & SeekFlag_WordBoundary) {
String left = GetSlice(string, i - 1, i);
String right = GetSlice(string, i + find.len, i + find.len + 1);
if (left.len != 0 && !IsNonWord(left.data[0])) {
ok_boundary = false;
}
if (right.len != 0 && !IsNonWord(right.data[0])) {
ok_boundary = false;
}
}
if (ok_boundary) {
if (index_out) {
*index_out = i; *index_out = i;
}
result = true; result = true;
break; break;
} }
} }
} }
}
return result; return result;
} }

View File

@@ -97,6 +97,7 @@ enum {
SeekFlag_None = 0, SeekFlag_None = 0,
SeekFlag_IgnoreCase = 1, SeekFlag_IgnoreCase = 1,
SeekFlag_MatchFindLast = 2, SeekFlag_MatchFindLast = 2,
SeekFlag_WordBoundary = 4,
}; };
API bool Seek(String string, String find, int64_t *index_out = NULL, SeekFlag flags = SeekFlag_None); API bool Seek(String string, String find, int64_t *index_out = NULL, SeekFlag flags = SeekFlag_None);

View File

@@ -222,23 +222,51 @@ API bool Seek(String16 string, String16 find, int64_t *index_out, SeekFlag flags
int64_t index = i - 1; int64_t index = i - 1;
String16 substring = GetSlice(string, index, index + find.len); String16 substring = GetSlice(string, index, index + find.len);
if (AreEqual(substring, find, ignore_case)) { if (AreEqual(substring, find, ignore_case)) {
if (index_out) bool ok_boundary = true;
if (flags & SeekFlag_WordBoundary) {
String16 left = GetSlice(string, i - 1, i);
String16 right = GetSlice(string, i + find.len, i + find.len + 1);
if (left.len != 0 && !IsNonWord(left.data[0])) {
ok_boundary = false;
}
if (right.len != 0 && !IsNonWord(right.data[0])) {
ok_boundary = false;
}
}
if (ok_boundary) {
if (index_out) {
*index_out = index; *index_out = index;
}
result = true; result = true;
break; break;
} }
} }
}
} else { } else {
for (int64_t i = 0; i < string.len; i++) { for (int64_t i = 0; i < string.len; i++) {
String16 substring = GetSlice(string, i, i + find.len); String16 substring = GetSlice(string, i, i + find.len);
if (AreEqual(substring, find, ignore_case)) { if (AreEqual(substring, find, ignore_case)) {
if (index_out) bool ok_boundary = true;
if (flags & SeekFlag_WordBoundary) {
String16 left = GetSlice(string, i - 1, i);
String16 right = GetSlice(string, i + find.len, i + find.len + 1);
if (left.len != 0 && !IsNonWord(left.data[0])) {
ok_boundary = false;
}
if (right.len != 0 && !IsNonWord(right.data[0])) {
ok_boundary = false;
}
}
if (ok_boundary) {
if (index_out) {
*index_out = i; *index_out = i;
}
result = true; result = true;
break; break;
} }
} }
} }
}
return result; return result;
} }

View File

@@ -6,6 +6,8 @@ bool Testing = false;
bool AppIsRunning = true; bool AppIsRunning = true;
bool WaitForEvents = true; bool WaitForEvents = true;
bool RunGCThisFrame; bool RunGCThisFrame;
bool SearchCaseSensitive = false;
bool SearchWordBoundary = false;
WindowID WindowIDs; WindowID WindowIDs;
ViewID ViewIDs; ViewID ViewIDs;

View File

@@ -126,14 +126,18 @@ void IdentedNewLine(View *view) {
Caret FindPrev(Buffer *buffer, String16 needle, Caret caret) { Caret FindPrev(Buffer *buffer, String16 needle, Caret caret) {
Int pos = GetFront(caret); Int pos = GetFront(caret);
String16 medium = GetString(buffer, {0, pos}); String16 medium = GetString(buffer, {0, pos});
SeekFlag flag = SearchCaseSensitive ? SeekFlag_None : SeekFlag_IgnoreCase;
if (SearchWordBoundary) {
flag |= SeekFlag_WordBoundary;
}
Caret result = caret; Caret result = caret;
Int index = 0; Int index = 0;
if (Seek(medium, needle, &index, SeekFlag_MatchFindLast)) { if (Seek(medium, needle, &index, flag | SeekFlag_MatchFindLast)) {
result = MakeCaret(index, index + needle.len); result = MakeCaret(index, index + needle.len);
} else { } else {
medium = GetString(buffer); medium = GetString(buffer);
if (Seek(medium, needle, &index, SeekFlag_MatchFindLast)) { if (Seek(medium, needle, &index, flag | SeekFlag_MatchFindLast)) {
result = MakeCaret(index, index + needle.len); result = MakeCaret(index, index + needle.len);
} }
} }
@@ -144,14 +148,18 @@ Caret FindPrev(Buffer *buffer, String16 needle, Caret caret) {
Caret FindNext(Buffer *buffer, String16 needle, Caret caret) { Caret FindNext(Buffer *buffer, String16 needle, Caret caret) {
Int pos = GetMax(caret); Int pos = GetMax(caret);
String16 medium = GetString(buffer, {pos, INT64_MAX}); String16 medium = GetString(buffer, {pos, INT64_MAX});
SeekFlag flag = SearchCaseSensitive ? SeekFlag_None : SeekFlag_IgnoreCase;
if (SearchWordBoundary) {
flag |= SeekFlag_WordBoundary;
}
Caret result = caret; Caret result = caret;
Int index = 0; Int index = 0;
if (Seek(medium, needle, &index)) { if (Seek(medium, needle, &index, flag)) {
result = MakeCaret(pos + index + needle.len, pos + index); result = MakeCaret(pos + index + needle.len, pos + index);
} else { } else {
medium = GetString(buffer); medium = GetString(buffer);
if (Seek(medium, needle, &index)) { if (Seek(medium, needle, &index, flag)) {
result = MakeCaret(index + needle.len, index); result = MakeCaret(index + needle.len, index);
} }
} }
@@ -163,9 +171,13 @@ Array<Caret> FindAll(Allocator allocator, Buffer *buffer, String16 needle) {
Array<Caret> result = {allocator}; Array<Caret> result = {allocator};
String16 string = GetString(buffer); String16 string = GetString(buffer);
String16 start = string; String16 start = string;
SeekFlag flag = SearchCaseSensitive ? SeekFlag_None : SeekFlag_IgnoreCase;
if (SearchWordBoundary) {
flag |= SeekFlag_WordBoundary;
}
for (;;) { for (;;) {
Int index = 0; Int index = 0;
if (Seek(string, needle, &index)) { if (Seek(string, needle, &index, flag)) {
Int back = index + (Int)(string.data - start.data); Int back = index + (Int)(string.data - start.data);
Int front = back + needle.len; Int front = back + needle.len;
Add(&result, MakeCaret(front, back)); Add(&result, MakeCaret(front, back));

View File

@@ -100,7 +100,6 @@ void Command_SearchAll() {
set.window->visible = false; set.window->visible = false;
} RegisterCommand(Command_SearchAll, "alt-f3"); } RegisterCommand(Command_SearchAll, "alt-f3");
void Command_SearchAllInSearch() { void Command_SearchAllInSearch() {
if (ActiveWindowID != SearchWindowID) { if (ActiveWindowID != SearchWindowID) {
return; return;
@@ -110,6 +109,13 @@ void Command_SearchAllInSearch() {
set.window->visible = false; set.window->visible = false;
} RegisterCommand(Command_SearchAllInSearch, "alt-enter"); } RegisterCommand(Command_SearchAllInSearch, "alt-enter");
void Command_ToggleCaseSensitiveSearch() {
SearchCaseSensitive = !SearchCaseSensitive;
} RegisterCommand(Command_ToggleCaseSensitiveSearch, "alt-c");
void Command_ToggleSearchWordBoundary() {
SearchWordBoundary = !SearchWordBoundary;
} RegisterCommand(Command_ToggleSearchWordBoundary, "alt-w");
void SearchWindowUpdate() { void SearchWindowUpdate() {
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);

View File

@@ -81,10 +81,11 @@ void StatusWindowUpdate() {
Array<Edit> edits = ReplaceEx(scratch, title.view, u" |"); Array<Edit> edits = ReplaceEx(scratch, title.view, u" |");
} }
// replace data up to separator with filename and stuff // replace data up to separator with filename and stuff
const char *reopen = main.buffer->changed_on_disk ? " :Reopen" : ""; const char *reopen = main.buffer->changed_on_disk ? " :Reopen" : "";
String s = Format(scratch, "# %S:%lld:%lld%s", main.buffer->name, (long long)xy.line + 1ll, (long long)xy.col + 1ll, reopen); const char *case_sens = SearchCaseSensitive ? " C" : "";
const char *word_bound = SearchWordBoundary ? " W" : "";
String s = Format(scratch, "# %S:%lld:%lld%s%s", main.buffer->name, (long long)xy.line + 1ll, (long long)xy.col + 1ll, case_sens, word_bound, reopen);
For (ActiveProcesses) { For (ActiveProcesses) {
if (it.view_id == main.view->id.id) { if (it.view_id == main.view->id.id) {
s = Format(scratch, "%S %lld :KillProcess", s, (long long)it.id); s = Format(scratch, "%S %lld :KillProcess", s, (long long)it.id);