xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit 5a53d0381293aba48277577b87fb05dc91b732ac

Introduce MatcherExpr enumeration
Specifies how to interpret a matcher expression in a more extensible way
than a simple boolean flag.
Author: xaizek
Author date (UTC): 2026-07-17 08:34
Committer name: xaizek
Committer date (UTC): 2026-07-17 08:34
Parent(s): 8e68938ad3836e924dcadc0b1b6a817b232690a4
Signing key: 99DC5E4DB05F6BE2
Tree: bad0165a0aeb4b7cc5f3e2c8495d0bedc9f8058f
File Lines added Lines deleted
src/cfg/info.c 4 2
src/cmd_handlers.c 1 1
src/filtering.c 2 1
src/utils/matcher.c 2 2
src/utils/matcher.h 8 2
src/utils/matchers.c 2 1
tests/misc/cmdline_editing.c 1 1
tests/test-support/test-utils.c 4 2
tests/utils/matcher.c 53 51
File src/cfg/info.c changed (mode: 100644) (index 4b7f19ccc..56d338b46)
... ... set_manual_filter(view_t *view, const char value[])
1270 1270 matcher_t *matcher; matcher_t *matcher;
1271 1271
1272 1272 (void)replace_string(&view->prev_manual_filter, value); (void)replace_string(&view->prev_manual_filter, value);
1273 matcher = matcher_alloc(value, FILTER_DEF_CASE_SENSITIVITY, 0, "", &error);
1273 matcher =
1274 matcher_alloc(value, FILTER_DEF_CASE_SENSITIVITY, ME_DEF_REGEX, "", &error);
1274 1275 free(error); free(error);
1275 1276
1276 1277 /* If setting filter value has failed, try to setup an empty value instead. */ /* If setting filter value has failed, try to setup an empty value instead. */
1277 1278 if(matcher == NULL) if(matcher == NULL)
1278 1279 { {
1279 1280 (void)replace_string(&view->prev_manual_filter, ""); (void)replace_string(&view->prev_manual_filter, "");
1280 matcher = matcher_alloc("", FILTER_DEF_CASE_SENSITIVITY, 0, "", &error);
1281 matcher =
1282 matcher_alloc("", FILTER_DEF_CASE_SENSITIVITY, ME_DEF_REGEX, "", &error);
1281 1283 free(error); free(error);
1282 1284 assert(matcher != NULL && "Can't init manual filter."); assert(matcher != NULL && "Can't init manual filter.");
1283 1285 } }
File src/cmd_handlers.c changed (mode: 100644) (index 49575fac8..38ba96c22)
... ... set_view_filter(view_t *view, const char filter[], const char fallback[],
2661 2661 { {
2662 2662 char *error; char *error;
2663 2663 matcher_t *const matcher = matcher_alloc(filter, FILTER_DEF_CASE_SENSITIVITY, matcher_t *const matcher = matcher_alloc(filter, FILTER_DEF_CASE_SENSITIVITY,
2664 0, fallback, &error);
2664 ME_DEF_REGEX, fallback, &error);
2665 2665 if(matcher == NULL) if(matcher == NULL)
2666 2666 { {
2667 2667 ui_sb_errf("Name filter not set: %s", error); ui_sb_errf("Name filter not set: %s", error);
File src/filtering.c changed (mode: 100644) (index 9976a5822..7addd527c)
... ... replace_matcher(matcher_t **matcher, const char expr[])
286 286 char *error; char *error;
287 287
288 288 matcher_free(*matcher); matcher_free(*matcher);
289 *matcher = matcher_alloc(expr, FILTER_DEF_CASE_SENSITIVITY, 0, "", &error);
289 *matcher =
290 matcher_alloc(expr, FILTER_DEF_CASE_SENSITIVITY, ME_DEF_REGEX, "", &error);
290 291 free(error); free(error);
291 292 } }
292 293
File src/utils/matcher.c changed (mode: 100644) (index f7e2f3dcf..e1e7165e4)
... ... static int is_mime_expr(const char expr[]);
76 76 TSTATIC int matcher_is_fast(const matcher_t *matcher); TSTATIC int matcher_is_fast(const matcher_t *matcher);
77 77
78 78 matcher_t * matcher_t *
79 matcher_alloc(const char expr[], int cs_by_def, int glob_by_def,
79 matcher_alloc(const char expr[], int cs_by_def, MatcherExpr expr_kind,
80 80 const char on_empty_re[], char **error) const char on_empty_re[], char **error)
81 81 { {
82 82 const char *orig_expr = expr; const char *orig_expr = expr;
 
... ... matcher_alloc(const char expr[], int cs_by_def, int glob_by_def,
85 85 int strip; int strip;
86 86 const int full_path = is_full_path(expr, re, glob, &strip); const int full_path = is_full_path(expr, re, glob, &strip);
87 87
88 MType type = determine_type(expr, re, glob, glob_by_def, &strip);
88 MType type = determine_type(expr, re, glob, expr_kind == ME_DEF_GLOB, &strip);
89 89 matcher_t template = { matcher_t template = {
90 90 .type = type, .type = type,
91 91 .raw = strdup(expr + strip), .raw = strdup(expr + strip),
File src/utils/matcher.h changed (mode: 100644) (index d6622026c..0c2a208b4)
26 26
27 27 /* File path/name matcher (glob/regexp/mime-type). */ /* File path/name matcher (glob/regexp/mime-type). */
28 28
29 /* Specifies how to interpret a matcher expression. */
30 typedef enum {
31 ME_DEF_REGEX, /* Handle undecorated form as a regular expression. */
32 ME_DEF_GLOB, /* Handle undecorated form as a glob. */
33 } MatcherExpr;
34
29 35 /* Opaque matcher type. */ /* Opaque matcher type. */
30 36 typedef struct matcher_t matcher_t; typedef struct matcher_t matcher_t;
31 37
 
... ... typedef struct matcher_t matcher_t;
33 39 * if passed in regexp is empty. Returns matcher on success and sets *error to * if passed in regexp is empty. Returns matcher on success and sets *error to
34 40 * NULL, otherwise NULL is returned and *error is initialized with newly * NULL, otherwise NULL is returned and *error is initialized with newly
35 41 * allocated string describing the error. */ * allocated string describing the error. */
36 matcher_t * matcher_alloc(const char expr[], int cs_by_def, int glob_by_def,
37 const char on_empty_re[], char **error);
42 matcher_t * matcher_alloc(const char expr[], int cs_by_def,
43 MatcherExpr expr_kind, const char on_empty_re[], char **error);
38 44
39 45 /* Creates a glob matcher not processing any decorations. Expression is either /* Creates a glob matcher not processing any decorations. Expression is either
40 46 * an empty string (matches nothing, not allowed by matcher_alloc()) or a * an empty string (matches nothing, not allowed by matcher_alloc()) or a
File src/utils/matchers.c changed (mode: 100644) (index a83730ed6..26f619414)
... ... matchers_alloc(const char list[], int cs_by_def, int glob_by_def,
98 98 return NULL; return NULL;
99 99 } }
100 100
101 const MatcherExpr expr_kind = (glob_by_def ? ME_DEF_GLOB : ME_DEF_REGEX);
101 102 for(i = 0; i < nexprs; ++i) for(i = 0; i < nexprs; ++i)
102 103 { {
103 matchers->list[i] = matcher_alloc(exprs[i], cs_by_def, glob_by_def,
104 matchers->list[i] = matcher_alloc(exprs[i], cs_by_def, expr_kind,
104 105 on_empty_re, error); on_empty_re, error);
105 106 if(matchers->list[i] == NULL) if(matchers->list[i] == NULL)
106 107 { {
File tests/misc/cmdline_editing.c changed (mode: 100644) (index 4d4c98d6e..c8d552712)
... ... SETUP()
47 47 char *error; char *error;
48 48 matcher_free(curr_view->manual_filter); matcher_free(curr_view->manual_filter);
49 49 assert_non_null(curr_view->manual_filter = assert_non_null(curr_view->manual_filter =
50 matcher_alloc("{filt}", 0, 0, "", &error));
50 matcher_alloc("{filt}", 0, ME_DEF_REGEX, "", &error));
51 51 assert_success(filter_set(&curr_view->auto_filter, "auto-filter")); assert_success(filter_set(&curr_view->auto_filter, "auto-filter"));
52 52 assert_success(filter_set(&curr_view->local_filter.filter, "local-filter")); assert_success(filter_set(&curr_view->local_filter.filter, "local-filter"));
53 53
File tests/test-support/test-utils.c changed (mode: 100644) (index 8c265f1d2..e35b43e2d)
... ... view_setup(view_t *view)
269 269 view->column_count = 1; view->column_count = 1;
270 270
271 271 assert_success(filter_init(&view->local_filter.filter, 1)); assert_success(filter_init(&view->local_filter.filter, 1));
272 assert_non_null(view->manual_filter = matcher_alloc("", 0, 0, "", &error));
272 view->manual_filter = matcher_alloc("", 0, ME_DEF_REGEX, "", &error);
273 assert_non_null(view->manual_filter);
273 274 assert_success(filter_init(&view->auto_filter, 1)); assert_success(filter_init(&view->auto_filter, 1));
274 275
275 276 strcpy(view->curr_dir, "/path"); strcpy(view->curr_dir, "/path");
 
... ... replace_matcher(matcher_t **matcher, const char expr[])
646 647 char *error; char *error;
647 648
648 649 matcher_free(*matcher); matcher_free(*matcher);
649 *matcher = matcher_alloc(expr, FILTER_DEF_CASE_SENSITIVITY, 0, "", &error);
650 *matcher =
651 matcher_alloc(expr, FILTER_DEF_CASE_SENSITIVITY, ME_DEF_REGEX, "", &error);
650 652 free(error); free(error);
651 653
652 654 return (*matcher == NULL); return (*matcher == NULL);
File tests/utils/matcher.c changed (mode: 100644) (index f315ca8e3..edf309958)
... ... TEST(empty_matcher_can_be_created)
22 22 char *error; char *error;
23 23 matcher_t *m; matcher_t *m;
24 24
25 assert_non_null(m = matcher_alloc("", 0, 0, "", &error));
25 assert_non_null(m = matcher_alloc("", 0, ME_DEF_REGEX, "", &error));
26 26 assert_true(matcher_is_empty(m)); assert_true(matcher_is_empty(m));
27 27
28 28 assert_false(matcher_matches(m, "")); assert_false(matcher_matches(m, ""));
 
... ... TEST(empty_matcher_can_be_created)
34 34 TEST(empty_matcher_matches_nothing_can_be_created) TEST(empty_matcher_matches_nothing_can_be_created)
35 35 { {
36 36 char *error; char *error;
37 matcher_t *m = matcher_alloc("", 0, 0, "", &error);
37 matcher_t *m = matcher_alloc("", 0, ME_DEF_REGEX, "", &error);
38 38 assert_true(matcher_is_empty(m)); assert_true(matcher_is_empty(m));
39 39 assert_string_equal(NULL, error); assert_string_equal(NULL, error);
40 40
 
... ... TEST(glob)
46 46 char *error; char *error;
47 47 matcher_t *m; matcher_t *m;
48 48
49 assert_non_null(m = matcher_alloc("{*.ext}", 0, 1, "", &error));
49 assert_non_null(m = matcher_alloc("{*.ext}", 0, ME_DEF_GLOB, "", &error));
50 50 assert_null(error); assert_null(error);
51 51
52 52 check_glob(m); check_glob(m);
 
... ... TEST(regexp)
59 59 char *error; char *error;
60 60 matcher_t *m; matcher_t *m;
61 61
62 assert_non_null(m = matcher_alloc("/^x*$/", 0, 1, "", &error));
62 assert_non_null(m = matcher_alloc("/^x*$/", 0, ME_DEF_GLOB, "", &error));
63 63 assert_null(error); assert_null(error);
64 64
65 65 check_regexp(m); check_regexp(m);
 
... ... TEST(defaulted_glob)
72 72 char *error; char *error;
73 73 matcher_t *m; matcher_t *m;
74 74
75 assert_non_null(m = matcher_alloc("*.ext", 0, 1, "", &error));
75 assert_non_null(m = matcher_alloc("*.ext", 0, ME_DEF_GLOB, "", &error));
76 76 assert_null(error); assert_null(error);
77 77
78 78 check_glob(m); check_glob(m);
 
... ... TEST(defaulted_regexp)
85 85 char *error; char *error;
86 86 matcher_t *m; matcher_t *m;
87 87
88 assert_non_null(m = matcher_alloc("^x*$", 0, 0, "", &error));
88 assert_non_null(m = matcher_alloc("^x*$", 0, ME_DEF_REGEX, "", &error));
89 89 assert_null(error); assert_null(error);
90 90
91 91 check_regexp(m); check_regexp(m);
 
... ... TEST(defaulted_regexp)
96 96 TEST(full_path_glob) TEST(full_path_glob)
97 97 { {
98 98 char *error; char *error;
99 matcher_t *m;
100
101 assert_non_null(m = matcher_alloc("{{/tmp/[^/].ext}}", 0, 1, "", &error));
99 matcher_t *m = matcher_alloc("{{/tmp/[^/].ext}}", 0, ME_DEF_GLOB, "", &error);
100 assert_non_null(m);
102 101 assert_null(error); assert_null(error);
103 102
104 103 assert_true(matcher_matches(m, "/tmp/a.ext")); assert_true(matcher_matches(m, "/tmp/a.ext"));
 
... ... TEST(full_path_glob)
115 114 TEST(full_path_regexp) TEST(full_path_regexp)
116 115 { {
117 116 char *error; char *error;
118 matcher_t *m;
119
120 assert_non_null(m = matcher_alloc("//^/tmp/[^/]+\\.ext$//", 0, 1, "",
121 &error));
117 matcher_t *m =
118 matcher_alloc("//^/tmp/[^/]+\\.ext$//", 0, ME_DEF_GLOB, "", &error);
119 assert_non_null(m);
122 120 assert_null(error); assert_null(error);
123 121
124 122 assert_true(matcher_matches(m, "/tmp/a.ext")); assert_true(matcher_matches(m, "/tmp/a.ext"));
 
... ... TEST(matcher_negation)
137 135 char *error; char *error;
138 136 matcher_t *m; matcher_t *m;
139 137
140 assert_non_null(m = matcher_alloc("!{*.ext}", 0, 1, "", &error));
138 assert_non_null(m = matcher_alloc("!{*.ext}", 0, ME_DEF_GLOB, "", &error));
141 139 assert_null(error); assert_null(error);
142 140 assert_true(matcher_matches(m, "file.ext2")); assert_true(matcher_matches(m, "file.ext2"));
143 141 assert_false(matcher_matches(m, "name.ext")); assert_false(matcher_matches(m, "name.ext"));
144 142 matcher_free(m); matcher_free(m);
145 143
146 assert_non_null(m = matcher_alloc("!/^x*$/", 0, 1, "", &error));
144 assert_non_null(m = matcher_alloc("!/^x*$/", 0, ME_DEF_GLOB, "", &error));
147 145 assert_null(error); assert_null(error);
148 146 assert_true(matcher_matches(m, "axxxxx")); assert_true(matcher_matches(m, "axxxxx"));
149 147 assert_false(matcher_matches(m, "xxxxx")); assert_false(matcher_matches(m, "xxxxx"));
150 148 matcher_free(m); matcher_free(m);
151 149
152 assert_non_null(m = matcher_alloc("!*.ext", 0, 1, "", &error));
150 assert_non_null(m = matcher_alloc("!*.ext", 0, ME_DEF_GLOB, "", &error));
153 151 assert_null(error); assert_null(error);
154 152 assert_true(matcher_matches(m, "!abc.ext")); assert_true(matcher_matches(m, "!abc.ext"));
155 153 assert_false(matcher_matches(m, "!abc.ext2")); assert_false(matcher_matches(m, "!abc.ext2"));
156 154 matcher_free(m); matcher_free(m);
157 155
158 assert_non_null(m = matcher_alloc("!x*$", 0, 0, "", &error));
156 assert_non_null(m = matcher_alloc("!x*$", 0, ME_DEF_REGEX, "", &error));
159 157 assert_null(error); assert_null(error);
160 158 assert_true(matcher_matches(m, "a!xx")); assert_true(matcher_matches(m, "a!xx"));
161 159 assert_false(matcher_matches(m, "xx")); assert_false(matcher_matches(m, "xx"));
162 160 matcher_free(m); matcher_free(m);
163 161
164 assert_non_null(m = matcher_alloc("!{{/tmp/[^/].ext}}", 0, 1, "", &error));
162 m = matcher_alloc("!{{/tmp/[^/].ext}}", 0, ME_DEF_GLOB, "", &error);
163 assert_non_null(m);
165 164 assert_null(error); assert_null(error);
166 165 assert_true(matcher_matches(m, "/tmp/a.ext1")); assert_true(matcher_matches(m, "/tmp/a.ext1"));
167 166 assert_false(matcher_matches(m, "/tmp/a.ext")); assert_false(matcher_matches(m, "/tmp/a.ext"));
168 167 matcher_free(m); matcher_free(m);
169 168
170 assert_non_null(m = matcher_alloc("!//^/tmp/[^/]+\\.ext$//", 0, 1, "",
171 &error));
169 m = matcher_alloc("!//^/tmp/[^/]+\\.ext$//", 0, ME_DEF_GLOB, "", &error);
170 assert_non_null(m);
172 171 assert_null(error); assert_null(error);
173 172 assert_true(matcher_matches(m, "/bin/ab.ext")); assert_true(matcher_matches(m, "/bin/ab.ext"));
174 173 assert_false(matcher_matches(m, "/tmp/ab.ext")); assert_false(matcher_matches(m, "/tmp/ab.ext"));
 
... ... TEST(empty_regexp)
180 179 char *error; char *error;
181 180 matcher_t *m; matcher_t *m;
182 181
183 assert_non_null(m = matcher_alloc("", 0, 0, ".*\\.ext", &error));
182 assert_non_null(m = matcher_alloc("", 0, ME_DEF_REGEX, ".*\\.ext", &error));
184 183 assert_null(error); assert_null(error);
185 184 assert_true(matcher_matches(m, "/tmp/a.ext")); assert_true(matcher_matches(m, "/tmp/a.ext"));
186 185 assert_false(matcher_matches(m, "/tmp/a.axt")); assert_false(matcher_matches(m, "/tmp/a.axt"));
 
... ... TEST(empty_regexp)
188 187 assert_string_equal(".*\\.ext", matcher_get_undec(m)); assert_string_equal(".*\\.ext", matcher_get_undec(m));
189 188 matcher_free(m); matcher_free(m);
190 189
191 assert_non_null(m = matcher_alloc("//", 0, 1, ".*\\.ext", &error));
190 assert_non_null(m = matcher_alloc("//", 0, ME_DEF_GLOB, ".*\\.ext", &error));
192 191 assert_null(error); assert_null(error);
193 192 assert_true(matcher_matches(m, "/tmp/a.ext")); assert_true(matcher_matches(m, "/tmp/a.ext"));
194 193 assert_false(matcher_matches(m, "/tmp/a.axt")); assert_false(matcher_matches(m, "/tmp/a.axt"));
 
... ... TEST(empty_regexp)
196 195 assert_string_equal(".*\\.ext", matcher_get_undec(m)); assert_string_equal(".*\\.ext", matcher_get_undec(m));
197 196 matcher_free(m); matcher_free(m);
198 197
199 assert_non_null(m = matcher_alloc("//i", 0, 1, ".*\\.ext", &error));
198 assert_non_null(m = matcher_alloc("//i", 0, ME_DEF_GLOB, ".*\\.ext", &error));
200 199 assert_null(error); assert_null(error);
201 200 assert_true(matcher_matches(m, "/tmp/a.Ext")); assert_true(matcher_matches(m, "/tmp/a.Ext"));
202 201 assert_false(matcher_matches(m, "/tmp/a.axt")); assert_false(matcher_matches(m, "/tmp/a.axt"));
 
... ... TEST(empty_regexp)
204 203 assert_string_equal(".*\\.ext", matcher_get_undec(m)); assert_string_equal(".*\\.ext", matcher_get_undec(m));
205 204 matcher_free(m); matcher_free(m);
206 205
207 assert_non_null(m = matcher_alloc("//Iii", 0, 1, ".*\\.ext", &error));
206 m = matcher_alloc("//Iii", 0, ME_DEF_GLOB, ".*\\.ext", &error);
207 assert_non_null(m);
208 208 assert_null(error); assert_null(error);
209 209 assert_true(matcher_matches(m, "/tmp/a.Ext")); assert_true(matcher_matches(m, "/tmp/a.Ext"));
210 210 assert_false(matcher_matches(m, "/tmp/a.axt")); assert_false(matcher_matches(m, "/tmp/a.axt"));
 
... ... TEST(empty_regexp)
212 212 assert_string_equal(".*\\.ext", matcher_get_undec(m)); assert_string_equal(".*\\.ext", matcher_get_undec(m));
213 213 matcher_free(m); matcher_free(m);
214 214
215 assert_non_null(m = matcher_alloc("////I", 0, 1, "tmp/.*\\.Ext", &error));
215 m = matcher_alloc("////I", 0, ME_DEF_GLOB, "tmp/.*\\.Ext", &error);
216 assert_non_null(m);
216 217 assert_null(error); assert_null(error);
217 218 assert_true(matcher_matches(m, "/tmp/a.Ext")); assert_true(matcher_matches(m, "/tmp/a.Ext"));
218 219 assert_false(matcher_matches(m, "/tmp/a.axt")); assert_false(matcher_matches(m, "/tmp/a.axt"));
 
... ... TEST(wrong_regex_flag)
226 227 char *error; char *error;
227 228 matcher_t *m; matcher_t *m;
228 229
229 assert_null(m = matcher_alloc("/reg/x", 0, 1, ".*\\.ext", &error));
230 assert_null(m = matcher_alloc("/reg/x", 0, ME_DEF_GLOB, ".*\\.ext", &error));
230 231 assert_non_null(error); assert_non_null(error);
231 232 free(error); free(error);
232 233 } }
 
... ... TEST(expr_includes_itself)
236 237 char *error; char *error;
237 238 matcher_t *m; matcher_t *m;
238 239
239 assert_non_null(m = matcher_alloc("*.c", 0, 1, "", &error));
240 assert_non_null(m = matcher_alloc("*.c", 0, ME_DEF_GLOB, "", &error));
240 241 assert_null(error); assert_null(error);
241 242
242 243 assert_true(matcher_includes(m, m)); assert_true(matcher_includes(m, m));
 
... ... TEST(different_exprs_match_inclusion)
249 250 char *error; char *error;
250 251 matcher_t *m1, *m2; matcher_t *m1, *m2;
251 252
252 assert_non_null(m1 = matcher_alloc("*.c", 0, 1, "", &error));
253 assert_non_null(m1 = matcher_alloc("*.c", 0, ME_DEF_GLOB, "", &error));
253 254 assert_null(error); assert_null(error);
254 assert_non_null(m2 = matcher_alloc("/.*\\.c/", 0, 1, "", &error));
255 assert_non_null(m2 = matcher_alloc("/.*\\.c/", 0, ME_DEF_GLOB, "", &error));
255 256 assert_null(error); assert_null(error);
256 257
257 258 assert_false(matcher_includes(m1, m2)); assert_false(matcher_includes(m1, m2));
 
... ... TEST(global_match_inclusion)
265 266 char *error; char *error;
266 267 matcher_t *m1, *m2; matcher_t *m1, *m2;
267 268
268 assert_non_null(m1 = matcher_alloc("*.cpp,*.c", 0, 1, "", &error));
269 assert_non_null(m1 = matcher_alloc("*.cpp,*.c", 0, ME_DEF_GLOB, "", &error));
269 270 assert_null(error); assert_null(error);
270 assert_non_null(m2 = matcher_alloc("*.c", 0, 1, "", &error));
271 assert_non_null(m2 = matcher_alloc("*.c", 0, ME_DEF_GLOB, "", &error));
271 272 assert_null(error); assert_null(error);
272 273
273 274 assert_true(matcher_includes(m1, m2)); assert_true(matcher_includes(m1, m2));
 
... ... TEST(global_match_no_inclusion)
281 282 char *error; char *error;
282 283 matcher_t *m1, *m2; matcher_t *m1, *m2;
283 284
284 assert_non_null(m1 = matcher_alloc("*.cpp,*.c", 0, 1, "", &error));
285 assert_non_null(m1 = matcher_alloc("*.cpp,*.c", 0, ME_DEF_GLOB, "", &error));
285 286 assert_null(error); assert_null(error);
286 assert_non_null(m2 = matcher_alloc("*.hpp", 0, 1, "", &error));
287 assert_non_null(m2 = matcher_alloc("*.hpp", 0, ME_DEF_GLOB, "", &error));
287 288 assert_null(error); assert_null(error);
288 289
289 290 assert_false(matcher_includes(m1, m2)); assert_false(matcher_includes(m1, m2));
 
... ... TEST(regex_inclusion_case_is_taken_into_account)
297 298 char *error; char *error;
298 299 matcher_t *m1, *m2; matcher_t *m1, *m2;
299 300
300 assert_non_null(m1 = matcher_alloc("/a/I", 0, 1, "", &error));
301 assert_non_null(m1 = matcher_alloc("/a/I", 0, ME_DEF_GLOB, "", &error));
301 302 assert_null(error); assert_null(error);
302 assert_non_null(m2 = matcher_alloc("/A/I", 0, 1, "", &error));
303 assert_non_null(m2 = matcher_alloc("/A/I", 0, ME_DEF_GLOB, "", &error));
303 304 assert_null(error); assert_null(error);
304 305
305 306 assert_false(matcher_includes(m1, m2)); assert_false(matcher_includes(m1, m2));
 
... ... TEST(globs_are_cloned)
313 314 char *error; char *error;
314 315 matcher_t *m, *clone; matcher_t *m, *clone;
315 316
316 assert_non_null(m = matcher_alloc("{*.ext}", 0, 1, "", &error));
317 assert_non_null(m = matcher_alloc("{*.ext}", 0, ME_DEF_GLOB, "", &error));
317 318 assert_null(error); assert_null(error);
318 319 assert_non_null(clone = matcher_clone(m)); assert_non_null(clone = matcher_clone(m));
319 320
 
... ... TEST(globs_are_case_insensitive)
329 330 char *error; char *error;
330 331 matcher_t *m, *clone; matcher_t *m, *clone;
331 332
332 assert_non_null(m = matcher_alloc("{*.ExT}", 0, 1, "", &error));
333 assert_non_null(m = matcher_alloc("{*.ExT}", 0, ME_DEF_GLOB, "", &error));
333 334 assert_null(error); assert_null(error);
334 335 assert_non_null(clone = matcher_clone(m)); assert_non_null(clone = matcher_clone(m));
335 336
 
... ... TEST(fast_globs)
345 346 char *error; char *error;
346 347 matcher_t *m; matcher_t *m;
347 348
348 m = matcher_alloc("{*suffix,prefix*,mid*dle,literal}", 0, 1, "", &error);
349 m = matcher_alloc("{*suffix,prefix*,mid*dle,literal}", 0, ME_DEF_GLOB, "",
350 &error);
349 351 assert_true(matcher_is_fast(m)); assert_true(matcher_is_fast(m));
350 352 assert_non_null(m); assert_non_null(m);
351 353 assert_null(error); assert_null(error);
 
... ... TEST(fast_globs)
353 355 matcher_free(m); matcher_free(m);
354 356
355 357 /* Control against equivalent non-fast-globs. */ /* Control against equivalent non-fast-globs. */
356 m = matcher_alloc("{*[s]uffix,[p]refix*,[m]id*dle,[l]iteral}", 0, 1, "",
357 &error);
358 m = matcher_alloc("{*[s]uffix,[p]refix*,[m]id*dle,[l]iteral}", 0, ME_DEF_GLOB,
359 "", &error);
358 360 assert_false(matcher_is_fast(m)); assert_false(matcher_is_fast(m));
359 361 assert_non_null(m); assert_non_null(m);
360 362 assert_null(error); assert_null(error);
361 363 check_fast_globs(m); check_fast_globs(m);
362 364 matcher_free(m); matcher_free(m);
363 365
364 m = matcher_alloc("{mid\\*dle}", 0, 1, "", &error);
366 m = matcher_alloc("{mid\\*dle}", 0, ME_DEF_GLOB, "", &error);
365 367 assert_true(matcher_is_fast(m)); assert_true(matcher_is_fast(m));
366 368 assert_true(matcher_matches(m, "mid*dle")); assert_true(matcher_matches(m, "mid*dle"));
367 369 assert_false(matcher_matches(m, "middle")); assert_false(matcher_matches(m, "middle"));
 
... ... TEST(regexps_are_cloned)
373 375 char *error; char *error;
374 376 matcher_t *m, *clone; matcher_t *m, *clone;
375 377
376 assert_non_null(m = matcher_alloc("/^x*$/", 0, 1, "", &error));
378 assert_non_null(m = matcher_alloc("/^x*$/", 0, ME_DEF_GLOB, "", &error));
377 379 assert_null(error); assert_null(error);
378 380 assert_non_null(clone = matcher_clone(m)); assert_non_null(clone = matcher_clone(m));
379 381
 
... ... TEST(regexps_are_cloned)
387 389 TEST(comma_escaping) TEST(comma_escaping)
388 390 { {
389 391 char *error; char *error;
390 matcher_t *m;
391
392 assert_non_null(m = matcher_alloc("{a,,b,*.ext,c,,d}", 0, 1, "", &error));
392 matcher_t *m = matcher_alloc("{a,,b,*.ext,c,,d}", 0, ME_DEF_GLOB, "", &error);
393 assert_non_null(m);
393 394 assert_null(error); assert_null(error);
394 395
395 396 check_glob(m); check_glob(m);
 
... ... TEST(mime_type_pattern, IF(has_mime_type_detection))
430 431 char *error; char *error;
431 432 matcher_t *m; matcher_t *m;
432 433
433 assert_non_null(m = matcher_alloc("<text/plain>", 0, 1, "", &error));
434 m = matcher_alloc("<text/plain>", 0, ME_DEF_GLOB, "", &error);
435 assert_non_null(m);
434 436 assert_null(error); assert_null(error);
435 437 assert_true(matcher_matches(m, TEST_DATA_PATH "/read/dos-line-endings")); assert_true(matcher_matches(m, TEST_DATA_PATH "/read/dos-line-endings"));
436 438 assert_false(matcher_matches(m, TEST_DATA_PATH "/read/binary-data")); assert_false(matcher_matches(m, TEST_DATA_PATH "/read/binary-data"));
437 439 matcher_free(m); matcher_free(m);
438 440
439 assert_non_null(m = matcher_alloc("<text/*>", 0, 1, "", &error));
441 assert_non_null(m = matcher_alloc("<text/*>", 0, ME_DEF_GLOB, "", &error));
440 442 assert_null(error); assert_null(error);
441 443 assert_true(matcher_matches(m, TEST_DATA_PATH "/read/dos-line-endings")); assert_true(matcher_matches(m, TEST_DATA_PATH "/read/dos-line-endings"));
442 444 assert_false(matcher_matches(m, TEST_DATA_PATH "/read/binary-data")); assert_false(matcher_matches(m, TEST_DATA_PATH "/read/binary-data"));
 
... ... TEST(mime_type_inclusion, IF(has_mime_type_detection))
448 450 char *error; char *error;
449 451 matcher_t *m, *m1, *m2; matcher_t *m, *m1, *m2;
450 452
451 assert_non_null(m = matcher_alloc("<a/b,c/Dd>", 0, 1, "", &error));
453 assert_non_null(m = matcher_alloc("<a/b,c/Dd>", 0, ME_DEF_GLOB, "", &error));
452 454 assert_null(error); assert_null(error);
453 assert_non_null(m1 = matcher_alloc("<c/dd>", 0, 1, "", &error));
455 assert_non_null(m1 = matcher_alloc("<c/dd>", 0, ME_DEF_GLOB, "", &error));
454 456 assert_null(error); assert_null(error);
455 assert_non_null(m2 = matcher_alloc("<c/d>", 0, 1, "", &error));
457 assert_non_null(m2 = matcher_alloc("<c/d>", 0, ME_DEF_GLOB, "", &error));
456 458 assert_null(error); assert_null(error);
457 459
458 460 assert_true(matcher_includes(m, m)); assert_true(matcher_includes(m, m));
 
... ... TEST(mime_type_of_link_is_that_of_its_ultimate_target,
475 477
476 478 char *expr = format_str("<%s>", get_mimetype(SANDBOX_PATH, 0)); char *expr = format_str("<%s>", get_mimetype(SANDBOX_PATH, 0));
477 479
478 assert_non_null(m = matcher_alloc(expr, 0, 1, "", &error));
480 assert_non_null(m = matcher_alloc(expr, 0, ME_DEF_GLOB, "", &error));
479 481 assert_null(error); assert_null(error);
480 482 assert_true(matcher_matches(m, "link")); assert_true(matcher_matches(m, "link"));
481 483 assert_true(matcher_matches(m, "link2")); assert_true(matcher_matches(m, "link2"));
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master