From: Olaf Wintermann Date: Mon, 2 Feb 2026 19:40:14 +0000 (+0100) Subject: implement regex search X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=7b084b7b968e545fca68fb02ed9d974b0751a69b;p=note.git implement regex search --- diff --git a/application/note.c b/application/note.c index e23d53f..61e27e8 100644 --- a/application/note.c +++ b/application/note.c @@ -344,7 +344,7 @@ int text_search( int pos, bool backwards, bool case_sensitive, - bool regex, + regex_t *regex, int *result_begin, int *result_end) { @@ -353,9 +353,20 @@ int text_search( cxstring subtext = cx_strsubs(text, pos); if(!regex) { result = case_sensitive ? cx_strstr(subtext, search) : text_search_strcasestr(subtext, search); + if(result.ptr) { + *result_begin = (int)(result.ptr - text.ptr); + *result_end = *result_begin + search.length; + return 1; + } } else { - // regex search - // TODO + // case_sensitive parameter is ignored in regex mode + regmatch_t match; + if(regexec(regex, subtext.ptr, 1, &match, 0) != 0) { + return 0; + } + *result_begin = match.rm_so + pos; + *result_end = match.rm_eo + pos; + return 1; } } else { // use text_search in forward-mode as long as result_end < pos @@ -370,13 +381,8 @@ int text_search( prev_begin = begin; prev_end = end; } - if(prev_begin >= 0) { - result = cx_strn(text.ptr + prev_begin, prev_end-prev_begin); - } - } - if(result.ptr) { - *result_begin = (int)(result.ptr - text.ptr); - *result_end = *result_begin + search.length; + *result_begin = prev_begin; + *result_end = prev_end; return 1; } return 0; @@ -402,10 +408,21 @@ static void note_search(NoteModel *note, bool backwards) { int pos = get_search_start_pos(note, backwards); bool cs = (bool)ui_get(note->search_cs); - bool regex = (bool)ui_get(note->search_regex); + regex_t regex; + bool enable_regex = (bool)ui_get(note->search_regex); + if(enable_regex) { + int flags = REG_EXTENDED; + if(!cs) { + flags |= REG_ICASE; + } + if(regcomp(®ex, searchstr.ptr, flags)) { + enable_regex = FALSE; + // TODO: show invalid regex error + } + } int begin, end; - if(text_search(text, searchstr, pos, backwards, regex, cs, &begin, &end)) { + if(text_search(text, searchstr, pos, backwards, cs, enable_regex ? ®ex : NULL, &begin, &end)) { note->text->setposition(note->text, end); note->text->setselection(note->text, begin, end); note->text->showposition(note->text, begin); diff --git a/application/note.h b/application/note.h index f7be359..3e099e0 100644 --- a/application/note.h +++ b/application/note.h @@ -32,6 +32,8 @@ #include "application.h" #include "editor.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -78,7 +80,7 @@ int text_search( int pos, bool backwards, bool case_sensitive, - bool regex, + regex_t *regex, int *result_begin, int *result_end); diff --git a/application/tests/test-note.c b/application/tests/test-note.c index fd23ec7..6c6edc0 100644 --- a/application/tests/test-note.c +++ b/application/tests/test-note.c @@ -30,6 +30,7 @@ #include "../note.h" +#include CX_TEST(test_text_search_strcasestr) { CX_TEST_DO { @@ -68,28 +69,28 @@ CX_TEST(test_text_search_cs) { // test from pos 0 int begin = -1; int end = -1; - int ret = text_search(str, cx_str("123"), 0, FALSE, TRUE, FALSE, &begin, &end); + int ret = text_search(str, cx_str("123"), 0, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 0); CX_TEST_ASSERT(end == 3); begin = -1; end = -1; - ret = text_search(str, cx_str("4567"), 0, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("4567"), 0, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 4); CX_TEST_ASSERT(end == 8); begin = -1; end = -1; - ret = text_search(str, cx_str("edfghj"), 0, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("edfghj"), 0, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 18); CX_TEST_ASSERT(end == 24); begin = -1; end = -1; - ret = text_search(str, cx_str("abc"), 0, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("abc"), 0, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 13); CX_TEST_ASSERT(end == 16); @@ -97,49 +98,49 @@ CX_TEST(test_text_search_cs) { // test from other positions begin = -1; end = -1; - ret = text_search(str, cx_str("4567"), 4, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("4567"), 4, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 4); CX_TEST_ASSERT(end == 8); begin = -1; end = -1; - ret = text_search(str, cx_str("abc"), 14, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("abc"), 14, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 33); CX_TEST_ASSERT(end == 36); - ret = text_search(str, cx_str("4567"), 20, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("4567"), 20, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(!ret); - ret = text_search(str, cx_str("edfghj"), 19, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("edfghj"), 19, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(!ret); // case sensitive test - ret = text_search(str, cx_str("ABCD"), 0, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("ABCD"), 0, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(!ret); - ret = text_search(str, cx_str("Xyz"), 0, FALSE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("Xyz"), 0, FALSE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(!ret); // backwards search begin = -1; end = -1; - ret = text_search(str, cx_str("abc"), 36, TRUE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("abc"), 36, TRUE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 33); CX_TEST_ASSERT(end == 36); begin = -1; end = -1; - ret = text_search(str, cx_str("edf"), 25, TRUE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("edf"), 25, TRUE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 18); CX_TEST_ASSERT(end == 21); begin = -1; end = -1; - ret = text_search(str, cx_str("abc"), 25, TRUE, TRUE, FALSE, &begin, &end); + ret = text_search(str, cx_str("abc"), 25, TRUE, TRUE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 13); CX_TEST_ASSERT(end == 16); @@ -153,21 +154,21 @@ CX_TEST(test_text_search_ci) { // test from pos 0 int begin = -1; int end = -1; - int ret = text_search(str, cx_str("abc"), 0, FALSE, FALSE, FALSE, &begin, &end); + int ret = text_search(str, cx_str("abc"), 0, FALSE, FALSE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 0); CX_TEST_ASSERT(end == 3); begin = -1; end = -1; - ret = text_search(str, cx_str("def"), 0, FALSE, FALSE, FALSE, &begin, &end); + ret = text_search(str, cx_str("def"), 0, FALSE, FALSE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 4); CX_TEST_ASSERT(end == 7); begin = -1; end = -1; - ret = text_search(str, cx_str("DEF"), 0, FALSE, FALSE, FALSE, &begin, &end); + ret = text_search(str, cx_str("DEF"), 0, FALSE, FALSE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 4); CX_TEST_ASSERT(end == 7); @@ -175,14 +176,14 @@ CX_TEST(test_text_search_ci) { // test other pos begin = -1; end = -1; - ret = text_search(str, cx_str("DEF"), 4, FALSE, FALSE, FALSE, &begin, &end); + ret = text_search(str, cx_str("DEF"), 4, FALSE, FALSE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 4); CX_TEST_ASSERT(end == 7); begin = -1; end = -1; - ret = text_search(str, cx_str("ABC"), 8, FALSE, FALSE, FALSE, &begin, &end); + ret = text_search(str, cx_str("ABC"), 8, FALSE, FALSE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 16); CX_TEST_ASSERT(end == 19); @@ -190,16 +191,58 @@ CX_TEST(test_text_search_ci) { // backwards begin = -1; end = -1; - ret = text_search(str, cx_str("aBc"), 19, TRUE, FALSE, FALSE, &begin, &end); + ret = text_search(str, cx_str("aBc"), 19, TRUE, FALSE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 16); CX_TEST_ASSERT(end == 19); begin = -1; end = -1; - ret = text_search(str, cx_str("xyz"), 19, TRUE, FALSE, FALSE, &begin, &end); + ret = text_search(str, cx_str("xyz"), 19, TRUE, FALSE, NULL, &begin, &end); CX_TEST_ASSERT(ret); CX_TEST_ASSERT(begin == 12); CX_TEST_ASSERT(end == 15); } } + +CX_TEST(test_text_search_regex) { + CX_TEST_DO { + cxstring str = cx_str("hello world test string text end"); + + regex_t regex; + CX_TEST_ASSERT(!regcomp(®ex, "te[^ ]* ", REG_EXTENDED)); + + int begin, end, ret; + + // from pos 0 + begin = -1; + end = -1; + ret = text_search(str, cx_str(""), 0, FALSE, FALSE, ®ex, &begin, &end); + CX_TEST_ASSERT(ret); + CX_TEST_ASSERT(begin == 12); + CX_TEST_ASSERT(end == 17); + + // from pos > 0 + begin = -1; + end = -1; + ret = text_search(str, cx_str(""), 4, FALSE, FALSE, ®ex, &begin, &end); + CX_TEST_ASSERT(ret); + CX_TEST_ASSERT(begin == 12); + CX_TEST_ASSERT(end == 17); + + // negative + begin = -1; + end = -1; + ret = text_search(str, cx_str(""), 26, FALSE, FALSE, ®ex, &begin, &end); + CX_TEST_ASSERT(!ret); + + // backwards + begin = -1; + end = -1; + ret = text_search(str, cx_str(""), 20, TRUE, FALSE, ®ex, &begin, &end); + CX_TEST_ASSERT(ret); + CX_TEST_ASSERT(begin == 12); + CX_TEST_ASSERT(end == 17); + } + +} diff --git a/application/tests/test-note.h b/application/tests/test-note.h index 3404d3c..d3a629a 100644 --- a/application/tests/test-note.h +++ b/application/tests/test-note.h @@ -38,6 +38,7 @@ extern "C" { CX_TEST(test_text_search_strcasestr); CX_TEST(test_text_search_cs); CX_TEST(test_text_search_ci); +CX_TEST(test_text_search_regex); #ifdef __cplusplus diff --git a/application/tests/testmain.c b/application/tests/testmain.c index 36fcb61..481f47a 100644 --- a/application/tests/testmain.c +++ b/application/tests/testmain.c @@ -81,6 +81,7 @@ int main(int argc, char **argv) { cx_test_register(suite, test_text_search_strcasestr); cx_test_register(suite, test_text_search_cs); cx_test_register(suite, test_text_search_ci); + cx_test_register(suite, test_text_search_regex); cx_test_run_stdout(suite); int err = suite->failure > 0 ? 1 : 0;