Search case sensitive and word boundary
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user