Skip to content

Commit 82fdf0f

Browse files
committed
search: Restore implied 'AND' behavior in non-regex file match
mode. 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 82fdf0f

File tree

2 files changed

+50
-20
lines changed

2 files changed

+50
-20
lines changed

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

Lines changed: 39 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
@@ -455,7 +455,32 @@ search_thread_data_new (NemoSearchEngineAdvanced *engine,
455455
cased = g_strdup (normalized);
456456
}
457457

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

460485
g_free (text);
461486
g_free (normalized);
@@ -540,7 +565,7 @@ search_thread_data_free (SearchThreadData *data)
540565
g_clear_pointer (&data->content_re, g_regex_unref);
541566
g_clear_pointer (&data->newline_re, g_regex_unref);
542567
g_clear_pointer (&data->filename_re, g_regex_unref);
543-
g_clear_pointer (&data->filename_glob_pattern, g_pattern_spec_free);
568+
g_list_free_full (data->filename_glob_patterns, (GDestroyNotify) g_pattern_spec_free);
544569
g_timer_destroy (data->timer);
545570
g_mutex_clear (&data->hit_list_lock);
546571

@@ -1011,7 +1036,17 @@ visit_directory (GFile *dir, SearchThreadData *data)
10111036
}
10121037

10131038
gchar *cased_reversed = g_utf8_strreverse (cased, -1);
1014-
hit = g_pattern_spec_match (data->filename_glob_pattern, strlen (cased), cased, cased_reversed);
1039+
gsize len = strlen (cased);
1040+
1041+
hit = TRUE;
1042+
for (GList *l = data->filename_glob_patterns; l != NULL; l = l->next) {
1043+
GPatternSpec *pattern = l->data;
1044+
if (!g_pattern_spec_match (pattern, len, cased, cased_reversed)) {
1045+
hit = FALSE;
1046+
break;
1047+
}
1048+
}
1049+
10151050
g_free (cased);
10161051
g_free (cased_reversed);
10171052
}

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)