Ticket #3885: 3885-search-exclude.patch
File 3885-search-exclude.patch, 48.5 KB (added by esauloff, 7 years ago) |
---|
-
lib/search.h
From 2f1721bb45082dc5fd4211275208dc7f1715e072 Mon Sep 17 00:00:00 2001 From: Georgii Iesaulov <esauloff@gmail.com> Date: Fri, 8 Dec 2017 00:42:56 -0500 Subject: [PATCH 1/7] Add support of '|' delimiter to exclude files for shell patterns Signed-off-by: Georgii Iesaulov <esauloff@gmail.com> --- lib/search.h | 10 ++++++ lib/search/regex.c | 62 +++++++++++++++++++++++++++++---- lib/search/search.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 6 deletions(-) diff --git a/lib/search.h b/lib/search.h index 6e79609bc..bc6f09b02 100644
a b typedef struct mc_search_struct 110 110 /* prepared conditions */ 111 111 GPtrArray *conditions; 112 112 113 /* prepared conditions: to exclude patterns for MC_SEARCH_T_GLOB type */ 114 GPtrArray *conditions_exclude; 115 113 116 /* original search string */ 114 117 gchar *original; 115 118 gsize original_len; 119 120 /* original search string: to exclude patterns for MC_SEARCH_T_GLOB type */ 121 gchar *original_exclude; 122 gsize original_exclude_len; 123 116 124 #ifdef HAVE_CHARSET 117 125 gchar *original_charset; 118 126 #endif … … mc_search_t *mc_search_new_len (const gchar * original, gsize original_len, 146 154 void mc_search_free (mc_search_t * lc_mc_search); 147 155 148 156 gboolean mc_search_prepare (mc_search_t * mc_search); 157 gboolean mc_search_prepare_include (mc_search_t * mc_search); 158 gboolean mc_search_prepare_exclude (mc_search_t * mc_search); 149 159 150 160 gboolean mc_search_run (mc_search_t * mc_search, const void *user_data, gsize start_search, 151 161 gsize end_search, gsize * found_len); -
lib/search/regex.c
diff --git a/lib/search/regex.c b/lib/search/regex.c index a577ea3d5..f082b1577 100644
a b mc_search__g_regex_match_full_safe (const GRegex * regex, 320 320 321 321 static mc_search__found_cond_t 322 322 mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * regex, 323 GString * search_str )323 GString * search_str, gboolean do_not_cleanup) 324 324 { 325 325 #ifdef SEARCH_TYPE_GLIB 326 326 GError *mcerror = NULL; … … mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * 329 329 (regex, search_str->str, search_str->len, 0, G_REGEX_MATCH_NEWLINE_ANY, 330 330 &lc_mc_search->regex_match_info, &mcerror)) 331 331 { 332 g_match_info_free (lc_mc_search->regex_match_info); 333 lc_mc_search->regex_match_info = NULL; 332 if (!do_not_cleanup) 333 { 334 g_match_info_free (lc_mc_search->regex_match_info); 335 lc_mc_search->regex_match_info = NULL; 336 } 337 334 338 if (mcerror != NULL) 335 339 { 336 340 lc_mc_search->error = MC_SEARCH_E_REGEX; … … mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * 359 363 /* --------------------------------------------------------------------------------------------- */ 360 364 361 365 static mc_search__found_cond_t 362 mc_search__regex_found_cond (mc_search_t * lc_mc_search, GString * search_str)366 mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * search_str) 363 367 { 364 368 gsize loop1; 365 369 … … mc_search__regex_found_cond (mc_search_t * lc_mc_search, GString * search_str) 375 379 376 380 ret = 377 381 mc_search__regex_found_cond_one (lc_mc_search, mc_search_cond->regex_handle, 378 search_str); 382 search_str, FALSE); 383 if (ret != COND__NOT_FOUND) 384 return ret; 385 } 386 return COND__NOT_ALL_FOUND; 387 } 388 389 /* --------------------------------------------------------------------------------------------- */ 390 391 static mc_search__found_cond_t 392 mc_search__regex_found_cond_exclude (mc_search_t * lc_mc_search, GString * search_str) 393 { 394 gsize loop1; 395 396 for (loop1 = 0; loop1 < lc_mc_search->conditions_exclude->len; loop1++) 397 { 398 mc_search_cond_t *mc_search_cond; 399 mc_search__found_cond_t ret; 400 401 mc_search_cond = 402 (mc_search_cond_t *) g_ptr_array_index (lc_mc_search->conditions_exclude, loop1); 403 404 if (!mc_search_cond->regex_handle) 405 { 406 continue; 407 } 408 409 ret = 410 mc_search__regex_found_cond_one (lc_mc_search, mc_search_cond->regex_handle, 411 search_str, TRUE); 379 412 if (ret != COND__NOT_FOUND) 413 { 380 414 return ret; 415 } 381 416 } 417 382 418 return COND__NOT_ALL_FOUND; 383 419 } 384 420 … … mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 889 925 gint start_pos; 890 926 gint end_pos; 891 927 928 mc_search__found_cond_t ret_combined; 929 892 930 if (lc_mc_search->regex_buffer != NULL) 893 931 g_string_set_size (lc_mc_search->regex_buffer, 0); 894 932 else … … mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 952 990 virtual_pos = current_pos; 953 991 } 954 992 955 switch (mc_search__regex_found_cond (lc_mc_search, lc_mc_search->regex_buffer)) 993 ret_combined = 994 mc_search__regex_found_cond_include (lc_mc_search, lc_mc_search->regex_buffer); 995 if (ret_combined == COND__FOUND_OK) 996 { 997 if (lc_mc_search->search_type == MC_SEARCH_T_GLOB && 998 mc_search__regex_found_cond_exclude (lc_mc_search, 999 lc_mc_search->regex_buffer) == COND__FOUND_OK) 1000 { 1001 ret_combined = COND__NOT_ALL_FOUND; 1002 } 1003 } 1004 1005 switch (ret_combined) 956 1006 { 957 1007 case COND__FOUND_OK: 958 1008 #ifdef SEARCH_TYPE_GLIB -
lib/search/search.c
diff --git a/lib/search/search.c b/lib/search/search.c index e9e160a09..72c786a30 100644
a b mc_search_free (mc_search_t * lc_mc_search) 191 191 if (lc_mc_search->conditions != NULL) 192 192 mc_search__conditions_free (lc_mc_search->conditions); 193 193 194 if (lc_mc_search->conditions_exclude != NULL) 195 { 196 mc_search__conditions_free (lc_mc_search->conditions_exclude); 197 } 198 194 199 #ifdef SEARCH_TYPE_GLIB 195 200 if (lc_mc_search->regex_match_info != NULL) 196 201 g_match_info_free (lc_mc_search->regex_match_info); … … mc_search_free (mc_search_t * lc_mc_search) 208 213 209 214 gboolean 210 215 mc_search_prepare (mc_search_t * lc_mc_search) 216 { 217 gboolean ret; 218 219 const gchar *exclusion_delim = "|"; 220 gchar **tokens; 221 222 ret = TRUE; 223 224 if (lc_mc_search != NULL && lc_mc_search->search_type == MC_SEARCH_T_GLOB) 225 { 226 tokens = g_strsplit (lc_mc_search->original, exclusion_delim, 0); 227 if (g_strv_length (tokens) == 2) 228 { 229 g_free (lc_mc_search->original); 230 231 lc_mc_search->original_len = strlen (tokens[0]); 232 lc_mc_search->original = g_strndup (tokens[0], lc_mc_search->original_len); 233 234 lc_mc_search->original_exclude_len = strlen (tokens[1]); 235 lc_mc_search->original_exclude = 236 g_strndup (tokens[1], lc_mc_search->original_exclude_len); 237 } 238 g_strfreev (tokens); 239 240 ret = mc_search_prepare_exclude (lc_mc_search); 241 } 242 243 return (ret && mc_search_prepare_include (lc_mc_search)); 244 } 245 246 /* --------------------------------------------------------------------------------------------- */ 247 248 gboolean 249 mc_search_prepare_include (mc_search_t * lc_mc_search) 211 250 { 212 251 GPtrArray *ret; 213 252 … … mc_search_prepare (mc_search_t * lc_mc_search) 263 302 264 303 /* --------------------------------------------------------------------------------------------- */ 265 304 305 gboolean 306 mc_search_prepare_exclude (mc_search_t * lc_mc_search) 307 { 308 GPtrArray *ret; 309 310 ret = g_ptr_array_new (); 311 #ifdef HAVE_CHARSET 312 if (lc_mc_search->is_all_charsets) 313 { 314 gsize loop1; 315 316 for (loop1 = 0; loop1 < codepages->len; loop1++) 317 { 318 const char *id; 319 gsize recoded_str_len; 320 gchar *buffer; 321 322 id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id; 323 if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0) 324 { 325 g_ptr_array_add (ret, 326 mc_search__cond_struct_new (lc_mc_search, 327 lc_mc_search->original_exclude, 328 lc_mc_search->original_exclude_len, 329 lc_mc_search->original_charset)); 330 continue; 331 } 332 333 buffer = 334 mc_search__recode_str (lc_mc_search->original_exclude, 335 lc_mc_search->original_exclude_len, 336 lc_mc_search->original_charset, id, &recoded_str_len); 337 338 g_ptr_array_add (ret, 339 mc_search__cond_struct_new (lc_mc_search, buffer, 340 recoded_str_len, id)); 341 g_free (buffer); 342 } 343 } 344 else 345 { 346 g_ptr_array_add (ret, 347 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 348 lc_mc_search->original_exclude_len, 349 lc_mc_search->original_charset)); 350 } 351 #else 352 g_ptr_array_add (ret, 353 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 354 lc_mc_search->original_exclude_len, 355 str_detect_termencoding ())); 356 #endif 357 lc_mc_search->conditions_exclude = ret; 358 359 return (lc_mc_search->error == MC_SEARCH_E_OK); 360 } 361 362 /* --------------------------------------------------------------------------------------------- */ 363 266 364 /** 267 365 * Carries out the search. 268 366 * -
lib/search/regex.c
-- 2.14.3 From d530c43ea2289ddc9b740b53ef494bdc43c5d19e Mon Sep 17 00:00:00 2001 From: Georgii Iesaulov <esauloff@gmail.com> Date: Fri, 8 Dec 2017 00:44:53 -0500 Subject: [PATCH 2/7] Comment changed pieces for file search exclusion Signed-off-by: Georgii Iesaulov <esauloff@gmail.com> --- lib/search/regex.c | 26 ++++++++++++++++++++++++++ lib/search/search.c | 19 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lib/search/regex.c b/lib/search/regex.c index f082b1577..82753027f 100644
a b mc_search__g_regex_match_full_safe (const GRegex * regex, 318 318 319 319 /* --------------------------------------------------------------------------------------------- */ 320 320 321 /* 322 * Argument do_not_cleanup is used to distinguish *_include() vs *_exclude() calls to avoid 323 * clean-up of lc_mc_search->regex_match_info structure: if file does not match *_include() call, 324 * it is not considered anymore, but if file does not match *_exclude() call, it still can be 325 * considered and regex_match_info is used later in mc_search__run_regex(). 326 */ 321 327 static mc_search__found_cond_t 322 328 mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * regex, 323 329 GString * search_str, gboolean do_not_cleanup) … … mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * 362 368 363 369 /* --------------------------------------------------------------------------------------------- */ 364 370 371 /* 372 * To distinguish this method and newly added mc_search__regex_found_cond_exclude() - method was 373 * renamed, original name is mc_search__regex_found_cond(). No changes done to method internal 374 * logic except for added argument in mc_search__regex_found_cond_one() call. 375 */ 365 376 static mc_search__found_cond_t 366 377 mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * search_str) 367 378 { … … mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * searc 388 399 389 400 /* --------------------------------------------------------------------------------------------- */ 390 401 402 /* 403 * This method logic reflects mc_search__regex_found_cond_include() internals except for using 404 * exclusion array lc_mc_search->conditions_exclude to check if considered file matches exclusion 405 * pattern and should not be included in search result. 406 * TRUE is passed to mc_search__regex_found_cond_one() call to not clean-up 407 * lc_mc_search->regex_match_info structure if file does not match exclusion pattern. 408 */ 391 409 static mc_search__found_cond_t 392 410 mc_search__regex_found_cond_exclude (mc_search_t * lc_mc_search, GString * search_str) 393 411 { … … mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 925 943 gint start_pos; 926 944 gint end_pos; 927 945 946 /* Variable will contain result of *_include() method and then *_exclude() if needed */ 928 947 mc_search__found_cond_t ret_combined; 929 948 930 949 if (lc_mc_search->regex_buffer != NULL) … … mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 990 1009 virtual_pos = current_pos; 991 1010 } 992 1011 1012 /* 1013 * Check file exclusion for MC_SEARCH_T_GLOB search type. 1014 * Each considered file is checked to match inclusion pattern first. 1015 * If file matches and COND__FOUND_OK is returned from *_include() method, then exclusion 1016 * is checked with *_exclude(). If file matches for exclusion, found status COND__FOUND_OK 1017 * is changed to COND__NOT_ALL_FOUND to avoid file from search results. 1018 */ 993 1019 ret_combined = 994 1020 mc_search__regex_found_cond_include (lc_mc_search, lc_mc_search->regex_buffer); 995 1021 if (ret_combined == COND__FOUND_OK) -
lib/search/search.c
diff --git a/lib/search/search.c b/lib/search/search.c index 72c786a30..fe1887d73 100644
a b mc_search_free (mc_search_t * lc_mc_search) 211 211 212 212 /* --------------------------------------------------------------------------------------------- */ 213 213 214 /* 215 * Wrapper method to cover both mc_search_prepare_include() and mc_search_prepare_exclude() calls. 216 * Exclude portion works only for MC_SEARCH_T_GLOB search type. 217 */ 214 218 gboolean 215 219 mc_search_prepare (mc_search_t * lc_mc_search) 216 220 { 217 221 gboolean ret; 218 222 223 /* Hardcoded delimiter to split lc_mc_search->original to inclusion and exclusion patterns */ 219 224 const gchar *exclusion_delim = "|"; 220 225 gchar **tokens; 221 226 … … mc_search_prepare (mc_search_t * lc_mc_search) 224 229 if (lc_mc_search != NULL && lc_mc_search->search_type == MC_SEARCH_T_GLOB) 225 230 { 226 231 tokens = g_strsplit (lc_mc_search->original, exclusion_delim, 0); 232 233 /* 234 * Only if two tokens (only one delimiter '|' was specified) are found, 235 * lc_mc_search->original string is splitted, freed, and then initialized again. 236 * lc_mc_search->original_exclude is initialized afterwards. 237 */ 227 238 if (g_strv_length (tokens) == 2) 228 239 { 229 240 g_free (lc_mc_search->original); … … mc_search_prepare (mc_search_t * lc_mc_search) 245 256 246 257 /* --------------------------------------------------------------------------------------------- */ 247 258 259 /* 260 * To distinguish this method and newly added mc_search_prepare_exclude() - method was renamed, 261 * original name is mc_search_prepare(). No changes done to method internal logic. 262 */ 248 263 gboolean 249 264 mc_search_prepare_include (mc_search_t * lc_mc_search) 250 265 { … … mc_search_prepare_include (mc_search_t * lc_mc_search) 302 317 303 318 /* --------------------------------------------------------------------------------------------- */ 304 319 320 /* 321 * This method logic reflects mc_search_prepare_include() internals except for using 322 * exclusion pattern lc_mc_search->original_exclude to fill array lc_mc_search->conditions_exclude. 323 */ 305 324 gboolean 306 325 mc_search_prepare_exclude (mc_search_t * lc_mc_search) 307 326 { -
lib/search/search.c
-- 2.14.3 From 91a8fbd04abf7c50c9e40f018c62a721a379f14f Mon Sep 17 00:00:00 2001 From: Georgii Iesaulov <esauloff@gmail.com> Date: Mon, 11 Dec 2017 03:44:58 -0500 Subject: [PATCH 3/7] Check if exclusion delimiter is escaped properly Signed-off-by: Georgii Iesaulov <esauloff@gmail.com> --- lib/search/search.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/search/search.c b/lib/search/search.c index fe1887d73..8cfed53ba 100644
a b mc_search__conditions_free (GPtrArray * array) 122 122 g_ptr_array_free (array, TRUE); 123 123 } 124 124 125 /* --------------------------------------------------------------------------------------------- */ 126 127 static gboolean 128 mc_search_is_character_escaped (gchar * string, gchar ** string_start) 129 { 130 if (string == NULL || &string == string_start || *(string - 1) != '\\') 131 { 132 return FALSE; 133 } 134 135 return !mc_search_is_character_escaped (string - 1, string_start); 136 } 137 125 138 /* --------------------------------------------------------------------------------------------- */ 126 139 /*** public functions ****************************************************************************/ 127 140 /* --------------------------------------------------------------------------------------------- */ … … mc_search_prepare (mc_search_t * lc_mc_search) 222 235 223 236 /* Hardcoded delimiter to split lc_mc_search->original to inclusion and exclusion patterns */ 224 237 const gchar *exclusion_delim = "|"; 238 gboolean is_exclusion_escaped; 225 239 gchar **tokens; 226 240 227 241 ret = TRUE; 228 242 229 243 if (lc_mc_search != NULL && lc_mc_search->search_type == MC_SEARCH_T_GLOB) 230 244 { 245 is_exclusion_escaped = 246 mc_search_is_character_escaped (g_strstr_len (lc_mc_search->original, 247 lc_mc_search->original_len, 248 exclusion_delim), 249 &lc_mc_search->original); 250 231 251 tokens = g_strsplit (lc_mc_search->original, exclusion_delim, 0); 232 252 233 253 /* … … mc_search_prepare (mc_search_t * lc_mc_search) 235 255 * lc_mc_search->original string is splitted, freed, and then initialized again. 236 256 * lc_mc_search->original_exclude is initialized afterwards. 237 257 */ 238 if ( g_strv_length (tokens) == 2)258 if ((g_strv_length (tokens) == 2) && !is_exclusion_escaped) 239 259 { 240 260 g_free (lc_mc_search->original); 241 261 -
lib/search/regex.c
-- 2.14.3 From 23815836e9eb3e8e962fefa020ff8e3d2a47eb53 Mon Sep 17 00:00:00 2001 From: Georgii Iesaulov <esauloff@gmail.com> Date: Tue, 12 Dec 2017 16:18:34 -0500 Subject: [PATCH 4/7] Apply doxygen format for comments Signed-off-by: Georgii Iesaulov <esauloff@gmail.com> --- lib/search/regex.c | 46 ++++++++++++++++++++++++++++++++-------------- lib/search/search.c | 51 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 25 deletions(-) diff --git a/lib/search/regex.c b/lib/search/regex.c index 82753027f..c6ad7174b 100644
a b mc_search__g_regex_match_full_safe (const GRegex * regex, 318 318 319 319 /* --------------------------------------------------------------------------------------------- */ 320 320 321 /* 322 * Argument do_not_cleanup is used to distinguish *_include() vs *_exclude() calls to avoid 323 * clean-up of lc_mc_search->regex_match_info structure: if file does not match *_include() call, 324 * it is not considered anymore, but if file does not match *_exclude() call, it still can be 325 * considered and regex_match_info is used later in mc_search__run_regex(). 321 /** 322 * Checks if object #search_str matches one particular search criteria represented with #regex. 323 * Param #do_not_cleanup is used to avoid clean-up of lc_mc_search->regex_match_info structure: 324 * if file does not match *_include() call, it is not considered anymore, but if file 325 * does not match *_exclude() call, it still can be considered and regex_match_info 326 * is used later in mc_search__run_regex(). 327 * 328 * @note lc_mc_search->regex_match_info is freed and initialized with NULL 329 * if #search_str does not match #regex 330 * 331 * @param lc_mc_search search criteria 332 * @param regex regular expression representing search criteria 333 * @param search_str object to check criteria on 334 * @param do_not_cleanup TRUE if lc_mc_search->regex_match_info should be freed and initialized 335 * with NULL in case #search_str does not match #regex, FALSE otherwise 336 * 337 * @return search results 326 338 */ 327 339 static mc_search__found_cond_t 328 340 mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * regex, … … mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * 368 380 369 381 /* --------------------------------------------------------------------------------------------- */ 370 382 371 /* 372 * To distinguish this method and newly added mc_search__regex_found_cond_exclude() - method was 373 * renamed, original name is mc_search__regex_found_cond(). No changes done to method internal 374 * logic except for added argument in mc_search__regex_found_cond_one() call. 383 /** 384 * Checks if object #search_str matches any inclusion search criterias. 385 * 386 * @param lc_mc_search search criteria 387 * @param search_str object to check criteria on 388 * 389 * @return search results 375 390 */ 376 391 static mc_search__found_cond_t 377 392 mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * search_str) … … mc_search__regex_found_cond_include (mc_search_t * lc_mc_search, GString * searc 399 414 400 415 /* --------------------------------------------------------------------------------------------- */ 401 416 402 /* 403 * This method logic reflects mc_search__regex_found_cond_include() internals except for using 404 * exclusion array lc_mc_search->conditions_exclude to check if considered file matches exclusion 405 * pattern and should not be included in search result. 417 /** 418 * Checks if object #search_str matches any exclusion search criterias. 406 419 * TRUE is passed to mc_search__regex_found_cond_one() call to not clean-up 407 420 * lc_mc_search->regex_match_info structure if file does not match exclusion pattern. 421 * 422 * @param lc_mc_search search criteria 423 * @param search_str object to check criteria on 424 * 425 * @return search results 408 426 */ 409 427 static mc_search__found_cond_t 410 428 mc_search__regex_found_cond_exclude (mc_search_t * lc_mc_search, GString * search_str) … … mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 1012 1030 /* 1013 1031 * Check file exclusion for MC_SEARCH_T_GLOB search type. 1014 1032 * Each considered file is checked to match inclusion pattern first. 1015 * If file matches and COND__FOUND_OK is returned from*_include() method, then exclusion1033 * If file matches and COND__FOUND_OK is returned with *_include() method, then exclusion 1016 1034 * is checked with *_exclude(). If file matches for exclusion, found status COND__FOUND_OK 1017 1035 * is changed to COND__NOT_ALL_FOUND to avoid file from search results. 1018 1036 */ -
lib/search/search.c
diff --git a/lib/search/search.c b/lib/search/search.c index 8cfed53ba..ad21b007a 100644
a b mc_search__conditions_free (GPtrArray * array) 124 124 125 125 /* --------------------------------------------------------------------------------------------- */ 126 126 127 /** 128 * Checks whether specified character with #string parameter is escaped properly with '\' symbol. 129 * 130 * @example for string "abc\|def" where character '|' is escaped with single '\', TRUE is returned; 131 * for string "abc\\|def" - character '|' is not escaped while preceding '\' is, 132 * FALSE is returned. 133 * 134 * @param string fisrt character in string which is checked for preceding escape chars 135 * @param string_start start address of full string containing #string 136 * 137 * @return TRUE if character in #string is escaped properly, FALSE otherwise 138 */ 127 139 static gboolean 128 140 mc_search_is_character_escaped (gchar * string, gchar ** string_start) 129 141 { … … mc_search_free (mc_search_t * lc_mc_search) 224 236 225 237 /* --------------------------------------------------------------------------------------------- */ 226 238 227 /* 228 * Wrapper method to cover both mc_search_prepare_include() and mc_search_prepare_exclude() calls. 229 * Exclude portion works only for MC_SEARCH_T_GLOB search type. 239 /** 240 * Covers mc_search_prepare_include() and mc_search_prepare_exclude() calls. 241 * Wrapper method which covers *_include() and *_exclude() calls, and exclude logic works 242 * for MC_SEARCH_T_GLOB only. 243 * Splits original search criteria only in case single delimiter character exists in 244 * criteria string and character is not escaped. 245 * 246 * @param lc_mc_search search criteria 247 * 248 * @return TRUE if inclusion and exclusion criterias are initialized successfully, FALSE otherwise 230 249 */ 231 250 gboolean 232 251 mc_search_prepare (mc_search_t * lc_mc_search) 233 252 { 234 253 gboolean ret; 235 254 236 /* Hardcoded delimiter to split lc_mc_search->original to inclusion and exclusion patterns */255 /* Hardcoded delimiter to split lc_mc_search->original into inclusion and exclusion parts */ 237 256 const gchar *exclusion_delim = "|"; 238 257 gboolean is_exclusion_escaped; 239 258 gchar **tokens; … … mc_search_prepare (mc_search_t * lc_mc_search) 242 261 243 262 if (lc_mc_search != NULL && lc_mc_search->search_type == MC_SEARCH_T_GLOB) 244 263 { 264 /* Check if #exclusion_delim is escaped with '\' symbol */ 245 265 is_exclusion_escaped = 246 266 mc_search_is_character_escaped (g_strstr_len (lc_mc_search->original, 247 267 lc_mc_search->original_len, … … mc_search_prepare (mc_search_t * lc_mc_search) 251 271 tokens = g_strsplit (lc_mc_search->original, exclusion_delim, 0); 252 272 253 273 /* 254 * Only if two tokens (only one delimiter '|' was specified) are found,274 * If two tokens (one delimiter '|' is specified) are found and delimiter is not escaped, 255 275 * lc_mc_search->original string is splitted, freed, and then initialized again. 256 276 * lc_mc_search->original_exclude is initialized afterwards. 257 277 */ … … mc_search_prepare (mc_search_t * lc_mc_search) 276 296 277 297 /* --------------------------------------------------------------------------------------------- */ 278 298 279 /* 280 * To distinguish this method and newly added mc_search_prepare_exclude() - method was renamed, 281 * original name is mc_search_prepare(). No changes done to method internal logic. 299 /** 300 * Initializes inclusion search criteria. 301 * Parses inclusion search criteria to regular expression and adds it to lc_mc_search->conditions. 302 * 303 * @param lc_mc_search search criteria 304 * 305 * @return TRUE if inclusion search criteria is initialized successfully, FALSE otherwise 282 306 */ 283 307 gboolean 284 308 mc_search_prepare_include (mc_search_t * lc_mc_search) … … mc_search_prepare_include (mc_search_t * lc_mc_search) 337 361 338 362 /* --------------------------------------------------------------------------------------------- */ 339 363 340 /* 341 * This method logic reflects mc_search_prepare_include() internals except for using 342 * exclusion pattern lc_mc_search->original_exclude to fill array lc_mc_search->conditions_exclude. 364 /** 365 * Initializes exclusion search criteria. 366 * Parses exclusion search criteria to regular expression and adds it 367 * to lc_mc_search->conditions_exclude. 368 * 369 * @param lc_mc_search search criteria 370 * 371 * @return TRUE if exclusion search criteria is initialized successfully, FALSE otherwise 343 372 */ 344 373 gboolean 345 374 mc_search_prepare_exclude (mc_search_t * lc_mc_search) -
doc/man/mc.1.in
-- 2.14.3 From 1f2c243a52e6210d3881136a0bbeac6873487d60 Mon Sep 17 00:00:00 2001 From: Georgii Iesaulov <esauloff@gmail.com> Date: Tue, 12 Dec 2017 16:19:56 -0500 Subject: [PATCH 5/7] Reflect changes in Find Files and Select Files dialogs in hlp/man documents Signed-off-by: Georgii Iesaulov <esauloff@gmail.com> --- doc/man/mc.1.in | 14 +++++++++++--- doc/man/ru/mc.1.in | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/doc/man/mc.1.in b/doc/man/mc.1.in index aace39942..761866e81 100644
a b figure. 1418 1418 The "File name" input field contains a filename pattern to be searched 1419 1419 for. It is interpreted as a shell pattern or as a regular expression 1420 1420 depending on the state of the "Using shell patterns" checkbox. An empty 1421 value is valid and matches any file name. 1421 value is valid and matches any file name. To exclude some files or 1422 filename patterns from search results when using shell patterns, 1423 delimiter '|' (pipe symbol) can be used to split "File name" string 1424 into inclusion and exclusion parts. If more than one '|' symbol is found, 1425 exclusion logic does not apply. 1422 1426 .PP 1423 1427 The "Content" input field contains a string to search for within the 1424 1428 files. Leave this field empty to disable searching file contents. … … inside inodes and thus don't waste much disk space). 2754 2758 2755 2759 .\"NODE "Select/Unselect Files" 2756 2760 .SH "Select/Unselect Files" 2757 The dialog of group of files and directories selection or u selection.2761 The dialog of group of files and directories selection or unselection. 2758 2762 The 2759 2763 .\"LINK2" 2760 2764 input line … … expressions (see ed (1)). When 2779 2783 checkbox is on, the selection will be case sensitive characters. 2780 2784 If 2781 2785 .I Case sensitive 2782 is off, the case will be ignored. 2786 is off, the case will be ignored. To exclude some files or 2787 filename patterns from selection/unselection results when using 2788 Shell patterns, delimiter '|' (pipe symbol) can be used to split 2789 search string into inclusion and exclusion parts. If more than 2790 one '|' symbol is found, exclusion logic does not apply. 2783 2791 .\"NODE "Diff Viewer" 2784 2792 .SH "Internal Diff Viewer" 2785 2793 The mcdiff is a visual diff tool. You can compare two files and edit them -
doc/man/ru/mc.1.in
diff --git a/doc/man/ru/mc.1.in b/doc/man/ru/mc.1.in index 4a1ab012d..7f1de18fe 100644
a b Midnight Commander\-а. Для возврата к вашему приложен 536 536 то пометка файлов и каталогов будет производиться с учетом регистра символов имён. 537 537 Если опция 538 538 .I С учётом регистра 539 отключена, то регистр символов учитываться не будет. 539 отключена, то регистр символов учитываться не будет. Для того, чтобы исключить 540 некоторые файлы или маски имён файлов из результатов выборки при использовании 541 "Образцы в стиле shell", разделяющий символ '|' (вертикальная черта) может быть 542 использован. Символ '|' разделяет строку поиска на две части, 543 первая часть используется для включения файлов в результаты выборки, 544 вторая часть - для исключения файлов. Логика исключения не работает 545 если в строке найдено больше одного символа '|'. 540 546 .PP 541 547 .B \\\\ (backslash) 542 548 Клавиша "\\" снимает отметку с группы файлов, то есть производит … … Midnight Commander создает дерево путем просмотра т 1503 1509 Поле "Шаблон имени" содержит маску имени файла, по которой происходит поиск. 1504 1510 В зависимости от опции "Метасимволы shell" маска интерпретируется либо по тем же 1505 1511 правилам, что и в командной оболочке, либо как регулярное выражение. Пустое 1506 поле также допустимо и соответствует любому имени. 1512 поле также допустимо и соответствует любому имени. Для того, чтобы исключить 1513 некоторые файлы или маски имён файлов из результатов поиска при использовании 1514 "Метасимволов shell", разделяющий символ '|' (вертикальная черта) может быть 1515 использован. Символ '|' разделяет строку "Шаблон имени" на две части, 1516 первая часть используется для включения файлов в результаты поиска, 1517 вторая часть - для исключения файлов. Логика исключения не работает 1518 если в строке найдено больше одного символа '|'. 1507 1519 .PP 1508 1520 Поле "Содержимое" позволяет задать текст, который надо найти. Если это поле 1509 1521 пусто, то поиск по содержимому файлов производиться не будет. -
doc/man/mc.1.in
-- 2.14.3 From 6a388462e0044d75b7c4fe17bb3c5db500c7d8fd Mon Sep 17 00:00:00 2001 From: Georgii Iesaulov <esauloff@gmail.com> Date: Tue, 12 Dec 2017 23:03:30 -0500 Subject: [PATCH 6/7] Mention how to escape '|' delimiter in hlp/man documents Signed-off-by: Georgii Iesaulov <esauloff@gmail.com> --- doc/man/mc.1.in | 8 ++++++-- doc/man/ru/mc.1.in | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/man/mc.1.in b/doc/man/mc.1.in index 761866e81..56de34912 100644
a b value is valid and matches any file name. To exclude some files or 1422 1422 filename patterns from search results when using shell patterns, 1423 1423 delimiter '|' (pipe symbol) can be used to split "File name" string 1424 1424 into inclusion and exclusion parts. If more than one '|' symbol is found, 1425 exclusion logic does not apply. 1425 exclusion logic does not apply. To screen delimiter sign and search for 1426 '|' symbol literally, escape it with single '\\' (backslash symbol) 1427 like so "\\|". 1426 1428 .PP 1427 1429 The "Content" input field contains a string to search for within the 1428 1430 files. Leave this field empty to disable searching file contents. … … is off, the case will be ignored. To exclude some files or 2787 2789 filename patterns from selection/unselection results when using 2788 2790 Shell patterns, delimiter '|' (pipe symbol) can be used to split 2789 2791 search string into inclusion and exclusion parts. If more than 2790 one '|' symbol is found, exclusion logic does not apply. 2792 one '|' symbol is found, exclusion logic does not apply. To screen 2793 delimiter sign and search for '|' symbol literally, escape it 2794 with single '\\' (backslash symbol) like so "\\|". 2791 2795 .\"NODE "Diff Viewer" 2792 2796 .SH "Internal Diff Viewer" 2793 2797 The mcdiff is a visual diff tool. You can compare two files and edit them -
doc/man/ru/mc.1.in
diff --git a/doc/man/ru/mc.1.in b/doc/man/ru/mc.1.in index 7f1de18fe..7a93e6393 100644
a b Midnight Commander\-а. Для возврата к вашему приложен 542 542 использован. Символ '|' разделяет строку поиска на две части, 543 543 первая часть используется для включения файлов в результаты выборки, 544 544 вторая часть - для исключения файлов. Логика исключения не работает 545 если в строке найдено больше одного символа '|'. 545 если в строке найдено больше одного символа '|'. Для того, чтобы экранировать 546 разделяющий символ и начать поиск с символом '|', необходимо использовать 547 одиночный символ '\\' (обратная косая черта): "\\|". 546 548 .PP 547 549 .B \\\\ (backslash) 548 550 Клавиша "\\" снимает отметку с группы файлов, то есть производит … … Midnight Commander создает дерево путем просмотра т 1515 1517 использован. Символ '|' разделяет строку "Шаблон имени" на две части, 1516 1518 первая часть используется для включения файлов в результаты поиска, 1517 1519 вторая часть - для исключения файлов. Логика исключения не работает 1518 если в строке найдено больше одного символа '|'. 1520 если в строке найдено больше одного символа '|'. Для того, чтобы 1521 экранировать разделяющий символ и начать поиск с символом '|', необходимо 1522 использовать одиночный символ '\\' (обратная косая черта): "\\|". 1519 1523 .PP 1520 1524 Поле "Содержимое" позволяет задать текст, который надо найти. Если это поле 1521 1525 пусто, то поиск по содержимому файлов производиться не будет. -
lib/search.h
-- 2.14.3 From 380031265594cb929a262914be32b57eeda8dee3 Mon Sep 17 00:00:00 2001 From: Georgii Iesaulov <esauloff@gmail.com> Date: Tue, 12 Dec 2017 23:06:39 -0500 Subject: [PATCH 7/7] Hide mc_search_prepare_include() and *_exclude() methods in file static section Signed-off-by: Georgii Iesaulov <esauloff@gmail.com> --- lib/search.h | 2 - lib/search/search.c | 266 ++++++++++++++++++++++++++-------------------------- 2 files changed, 133 insertions(+), 135 deletions(-) diff --git a/lib/search.h b/lib/search.h index bc6f09b02..752eea835 100644
a b mc_search_t *mc_search_new_len (const gchar * original, gsize original_len, 154 154 void mc_search_free (mc_search_t * lc_mc_search); 155 155 156 156 gboolean mc_search_prepare (mc_search_t * mc_search); 157 gboolean mc_search_prepare_include (mc_search_t * mc_search);158 gboolean mc_search_prepare_exclude (mc_search_t * mc_search);159 157 160 158 gboolean mc_search_run (mc_search_t * mc_search, const void *user_data, gsize start_search, 161 159 gsize end_search, gsize * found_len); -
lib/search/search.c
diff --git a/lib/search/search.c b/lib/search/search.c index ad21b007a..4dfd2ae6d 100644
a b mc_search__cond_struct_free (mc_search_cond_t * mc_search_cond) 115 115 116 116 /* --------------------------------------------------------------------------------------------- */ 117 117 118 /** 119 * Initializes inclusion search criteria. 120 * Parses inclusion search criteria to regular expression and adds it to lc_mc_search->conditions. 121 * 122 * @param lc_mc_search search criteria 123 * 124 * @return TRUE if inclusion search criteria is initialized successfully, FALSE otherwise 125 */ 126 static gboolean 127 mc_search_prepare_include (mc_search_t * lc_mc_search) 128 { 129 GPtrArray *ret; 130 131 ret = g_ptr_array_new (); 132 #ifdef HAVE_CHARSET 133 if (lc_mc_search->is_all_charsets) 134 { 135 gsize loop1; 136 137 for (loop1 = 0; loop1 < codepages->len; loop1++) 138 { 139 const char *id; 140 gsize recoded_str_len; 141 gchar *buffer; 142 143 id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id; 144 if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0) 145 { 146 g_ptr_array_add (ret, 147 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 148 lc_mc_search->original_len, 149 lc_mc_search->original_charset)); 150 continue; 151 } 152 153 buffer = 154 mc_search__recode_str (lc_mc_search->original, lc_mc_search->original_len, 155 lc_mc_search->original_charset, id, &recoded_str_len); 156 157 g_ptr_array_add (ret, 158 mc_search__cond_struct_new (lc_mc_search, buffer, 159 recoded_str_len, id)); 160 g_free (buffer); 161 } 162 } 163 else 164 { 165 g_ptr_array_add (ret, 166 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 167 lc_mc_search->original_len, 168 lc_mc_search->original_charset)); 169 } 170 #else 171 g_ptr_array_add (ret, 172 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original, 173 lc_mc_search->original_len, 174 str_detect_termencoding ())); 175 #endif 176 lc_mc_search->conditions = ret; 177 178 return (lc_mc_search->error == MC_SEARCH_E_OK); 179 } 180 181 /* --------------------------------------------------------------------------------------------- */ 182 183 /** 184 * Initializes exclusion search criteria. 185 * Parses exclusion search criteria to regular expression and adds it 186 * to lc_mc_search->conditions_exclude. 187 * 188 * @param lc_mc_search search criteria 189 * 190 * @return TRUE if exclusion search criteria is initialized successfully, FALSE otherwise 191 */ 192 static gboolean 193 mc_search_prepare_exclude (mc_search_t * lc_mc_search) 194 { 195 GPtrArray *ret; 196 197 ret = g_ptr_array_new (); 198 #ifdef HAVE_CHARSET 199 if (lc_mc_search->is_all_charsets) 200 { 201 gsize loop1; 202 203 for (loop1 = 0; loop1 < codepages->len; loop1++) 204 { 205 const char *id; 206 gsize recoded_str_len; 207 gchar *buffer; 208 209 id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id; 210 if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0) 211 { 212 g_ptr_array_add (ret, 213 mc_search__cond_struct_new (lc_mc_search, 214 lc_mc_search->original_exclude, 215 lc_mc_search->original_exclude_len, 216 lc_mc_search->original_charset)); 217 continue; 218 } 219 220 buffer = 221 mc_search__recode_str (lc_mc_search->original_exclude, 222 lc_mc_search->original_exclude_len, 223 lc_mc_search->original_charset, id, &recoded_str_len); 224 225 g_ptr_array_add (ret, 226 mc_search__cond_struct_new (lc_mc_search, buffer, 227 recoded_str_len, id)); 228 g_free (buffer); 229 } 230 } 231 else 232 { 233 g_ptr_array_add (ret, 234 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 235 lc_mc_search->original_exclude_len, 236 lc_mc_search->original_charset)); 237 } 238 #else 239 g_ptr_array_add (ret, 240 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude, 241 lc_mc_search->original_exclude_len, 242 str_detect_termencoding ())); 243 #endif 244 lc_mc_search->conditions_exclude = ret; 245 246 return (lc_mc_search->error == MC_SEARCH_E_OK); 247 } 248 249 /* --------------------------------------------------------------------------------------------- */ 250 118 251 static void 119 252 mc_search__conditions_free (GPtrArray * array) 120 253 { … … mc_search_prepare (mc_search_t * lc_mc_search) 296 429 297 430 /* --------------------------------------------------------------------------------------------- */ 298 431 299 /**300 * Initializes inclusion search criteria.301 * Parses inclusion search criteria to regular expression and adds it to lc_mc_search->conditions.302 *303 * @param lc_mc_search search criteria304 *305 * @return TRUE if inclusion search criteria is initialized successfully, FALSE otherwise306 */307 gboolean308 mc_search_prepare_include (mc_search_t * lc_mc_search)309 {310 GPtrArray *ret;311 312 ret = g_ptr_array_new ();313 #ifdef HAVE_CHARSET314 if (lc_mc_search->is_all_charsets)315 {316 gsize loop1;317 318 for (loop1 = 0; loop1 < codepages->len; loop1++)319 {320 const char *id;321 gsize recoded_str_len;322 gchar *buffer;323 324 id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id;325 if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0)326 {327 g_ptr_array_add (ret,328 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original,329 lc_mc_search->original_len,330 lc_mc_search->original_charset));331 continue;332 }333 334 buffer =335 mc_search__recode_str (lc_mc_search->original, lc_mc_search->original_len,336 lc_mc_search->original_charset, id, &recoded_str_len);337 338 g_ptr_array_add (ret,339 mc_search__cond_struct_new (lc_mc_search, buffer,340 recoded_str_len, id));341 g_free (buffer);342 }343 }344 else345 {346 g_ptr_array_add (ret,347 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original,348 lc_mc_search->original_len,349 lc_mc_search->original_charset));350 }351 #else352 g_ptr_array_add (ret,353 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original,354 lc_mc_search->original_len,355 str_detect_termencoding ()));356 #endif357 lc_mc_search->conditions = ret;358 359 return (lc_mc_search->error == MC_SEARCH_E_OK);360 }361 362 /* --------------------------------------------------------------------------------------------- */363 364 /**365 * Initializes exclusion search criteria.366 * Parses exclusion search criteria to regular expression and adds it367 * to lc_mc_search->conditions_exclude.368 *369 * @param lc_mc_search search criteria370 *371 * @return TRUE if exclusion search criteria is initialized successfully, FALSE otherwise372 */373 gboolean374 mc_search_prepare_exclude (mc_search_t * lc_mc_search)375 {376 GPtrArray *ret;377 378 ret = g_ptr_array_new ();379 #ifdef HAVE_CHARSET380 if (lc_mc_search->is_all_charsets)381 {382 gsize loop1;383 384 for (loop1 = 0; loop1 < codepages->len; loop1++)385 {386 const char *id;387 gsize recoded_str_len;388 gchar *buffer;389 390 id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id;391 if (g_ascii_strcasecmp (id, lc_mc_search->original_charset) == 0)392 {393 g_ptr_array_add (ret,394 mc_search__cond_struct_new (lc_mc_search,395 lc_mc_search->original_exclude,396 lc_mc_search->original_exclude_len,397 lc_mc_search->original_charset));398 continue;399 }400 401 buffer =402 mc_search__recode_str (lc_mc_search->original_exclude,403 lc_mc_search->original_exclude_len,404 lc_mc_search->original_charset, id, &recoded_str_len);405 406 g_ptr_array_add (ret,407 mc_search__cond_struct_new (lc_mc_search, buffer,408 recoded_str_len, id));409 g_free (buffer);410 }411 }412 else413 {414 g_ptr_array_add (ret,415 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude,416 lc_mc_search->original_exclude_len,417 lc_mc_search->original_charset));418 }419 #else420 g_ptr_array_add (ret,421 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original_exclude,422 lc_mc_search->original_exclude_len,423 str_detect_termencoding ()));424 #endif425 lc_mc_search->conditions_exclude = ret;426 427 return (lc_mc_search->error == MC_SEARCH_E_OK);428 }429 430 /* --------------------------------------------------------------------------------------------- */431 432 432 /** 433 433 * Carries out the search. 434 434 *