Skip to content

Commit 7c501f1

Browse files
authored
search: Restore implied 'AND' behavior in non-regex file match mode (#3659)
If multiple words are encountered, they will be treated as separate search terms and be matched separately, requiring all to 'hit' for a file to be included in results. Full wildcard matching will still work for each word. ref: linuxmint/mint22.3-beta#29
1 parent 8dbeb05 commit 7c501f1

File tree

2 files changed

+56
-20
lines changed

2 files changed

+56
-20
lines changed

libnemo-private/nemo-search-engine-advanced.c

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ typedef struct {
6666
GRegex *newline_re;
6767

6868
GRegex *filename_re;
69-
GPatternSpec *filename_glob_pattern;
69+
GList *filename_glob_patterns;
7070

7171
GMutex hit_list_lock;
7272
GList *hit_list; // holds FileSearchResults
@@ -445,6 +445,7 @@ search_thread_data_new (NemoSearchEngineAdvanced *engine,
445445
}
446446
} else {
447447
gchar *text, *normalized, *cased;
448+
gchar **words;
448449

449450
text = nemo_query_get_file_pattern (query);
450451
normalized = g_utf8_normalize (text, -1, G_NORMALIZE_NFD);
@@ -455,7 +456,37 @@ search_thread_data_new (NemoSearchEngineAdvanced *engine,
455456
cased = g_strdup (normalized);
456457
}
457458

458-
data->filename_glob_pattern = g_pattern_spec_new (cased);
459+
/* In (< 6.6), whitespace between words was treated as AND, and implied a filename
460+
* must include *this* AND *that* AND *other*. To preserve this behavior, split
461+
* the search text and wrap segments individually (*segment*) if no wildcard characters
462+
* already included, and generate a GPatternSpec for each segment. */
463+
words = g_strsplit_set (cased, " \t\r\n", -1);
464+
data->filename_glob_patterns = NULL;
465+
466+
for (gint i = 0; words[i] != NULL; i++) {
467+
if (words[i][0] != '\0') {
468+
g_autofree gchar *word_pattern = NULL;
469+
470+
if (strchr (words[i], '*') == NULL && strchr (words[i], '?') == NULL) {
471+
word_pattern = g_strdup_printf ("*%s*", words[i]);
472+
} else {
473+
word_pattern = g_strdup (words[i]);
474+
}
475+
476+
DEBUG ("pattern is '%s'", word_pattern);
477+
478+
data->filename_glob_patterns = g_list_prepend (data->filename_glob_patterns,
479+
g_pattern_spec_new (word_pattern));
480+
}
481+
}
482+
483+
g_strfreev (words);
484+
485+
data->filename_glob_patterns = g_list_reverse (data->filename_glob_patterns);
486+
487+
if (data->filename_glob_patterns == NULL) {
488+
data->filename_glob_patterns = g_list_prepend (NULL, g_pattern_spec_new ("*"));
489+
}
459490

460491
g_free (text);
461492
g_free (normalized);
@@ -540,7 +571,7 @@ search_thread_data_free (SearchThreadData *data)
540571
g_clear_pointer (&data->content_re, g_regex_unref);
541572
g_clear_pointer (&data->newline_re, g_regex_unref);
542573
g_clear_pointer (&data->filename_re, g_regex_unref);
543-
g_clear_pointer (&data->filename_glob_pattern, g_pattern_spec_free);
574+
g_list_free_full (data->filename_glob_patterns, (GDestroyNotify) g_pattern_spec_free);
544575
g_timer_destroy (data->timer);
545576
g_mutex_clear (&data->hit_list_lock);
546577

@@ -1011,7 +1042,17 @@ visit_directory (GFile *dir, SearchThreadData *data)
10111042
}
10121043

10131044
gchar *cased_reversed = g_utf8_strreverse (cased, -1);
1014-
hit = g_pattern_spec_match (data->filename_glob_pattern, strlen (cased), cased, cased_reversed);
1045+
gsize len = strlen (cased);
1046+
1047+
hit = TRUE;
1048+
for (GList *l = data->filename_glob_patterns; l != NULL; l = l->next) {
1049+
GPatternSpec *pattern = l->data;
1050+
if (!g_pattern_spec_match (pattern, len, cased, cased_reversed)) {
1051+
hit = FALSE;
1052+
break;
1053+
}
1054+
}
1055+
10151056
g_free (cased);
10161057
g_free (cased_reversed);
10171058
}

src/nemo-query-editor.c

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -511,31 +511,26 @@ nemo_query_editor_get_query (NemoQueryEditor *editor)
511511
nemo_query_set_location (query, editor->priv->current_uri);
512512

513513
sanitized = get_sanitized_file_search_string (editor);
514-
GString *file_string = g_string_new (sanitized);
515-
g_free (sanitized);
516514

517515
/* - Search for 'all' needs to be different depending on whether regex is enabled for files.
518-
- Our non-regex search traditionally implied '*words*', not 'words'. Now that we're using
519-
GPatternSpec, we need to add those ourselves. */
516+
- For regex: use '.*' for empty search
517+
- For non-regex: the search engine will handle splitting by whitespace and wrapping
518+
each word with asterisks for user convenience. */
520519
if (nemo_query_get_use_file_regex (query)) {
521-
if (g_strcmp0 (file_string->str, "") == 0) {
522-
g_string_assign (file_string, ".*");
520+
if (g_strcmp0 (sanitized, "") == 0) {
521+
nemo_query_set_file_pattern (query, ".*");
522+
} else {
523+
nemo_query_set_file_pattern (query, sanitized);
523524
}
524525
} else {
525-
if (g_strcmp0 (file_string->str, "") == 0) {
526-
g_string_assign (file_string, "*");
526+
if (g_strcmp0 (sanitized, "") == 0) {
527+
nemo_query_set_file_pattern (query, "*");
527528
} else {
528-
if (!g_str_has_prefix (file_string->str, "*")) {
529-
g_string_insert_c (file_string, 0, '*');
530-
}
531-
if (!g_str_has_suffix (file_string->str, "*")) {
532-
g_string_append_c (file_string, '*');
533-
}
529+
nemo_query_set_file_pattern (query, sanitized);
534530
}
535531
}
536532

537-
nemo_query_set_file_pattern (query, file_string->str);
538-
g_string_free (file_string, TRUE);
533+
g_free (sanitized);
539534

540535
return query;
541536
}

0 commit comments

Comments
 (0)