From b6373ad8f4b1d325bafda41277088404570640d1 Mon Sep 17 00:00:00 2001 From: ppitu <piotr.chmura.1998@gmail.com> Date: Tue, 28 Jun 2022 21:08:07 +0000 Subject: [PATCH] Bulk Renamer: Allow multiple matches when using regex (Issue #230) When using 'Search & Replace' with regular expression, only the first match was found and replaced. With this patch, all patterns matching the expression will be found and replaced. MR !235 --- .../thunar-sbr/thunar-sbr-replace-renamer.c | 168 +++++++++--------- 1 file changed, 85 insertions(+), 83 deletions(-) diff --git a/plugins/thunar-sbr/thunar-sbr-replace-renamer.c b/plugins/thunar-sbr/thunar-sbr-replace-renamer.c index 6bb33dc62..fbf5fbef5 100644 --- a/plugins/thunar-sbr/thunar-sbr-replace-renamer.c +++ b/plugins/thunar-sbr/thunar-sbr-replace-renamer.c @@ -454,107 +454,109 @@ thunar_sbr_replace_renamer_pcre_exec (ThunarSbrReplaceRenamer *replace_renamer, gint *ovec; gint olen; gint rc; + gint index_match; + gint first_index_after_match = 0; /* guess an initial ovec size */ olen = (replace_renamer->pcre_capture_count + 10) * 3; ovec = g_new0 (gint, olen); - /* try to match the subject (increasing ovec on-demand) */ - for (rc = 0; rc <= 0; ) - { - /* try to exec, will return 0 if the ovec is too small */ - rc = pcre_exec (replace_renamer->pcre_pattern, NULL, subject, strlen (subject), 0, PCRE_NOTEMPTY, ovec, olen); - if (G_UNLIKELY (rc < 0)) - { - /* no match or error */ - g_free (ovec); - return g_strdup (subject); - } - else if (rc == 0) - { - /* ovec too small, try to increase */ - olen += 18; - ovec = g_realloc (ovec, olen * sizeof (gint)); - } - } - /* allocate a string for the result */ result = g_string_sized_new (32); - /* append the text before the match */ - g_string_append_len (result, subject, ovec[0]); + /* go through string */ + while ((size_t) first_index_after_match < strlen (subject)) + { + /* if rc <= 0 we have no match any more */ + rc = pcre_exec (replace_renamer->pcre_pattern, NULL, subject, strlen (subject), first_index_after_match, PCRE_NOTEMPTY, ovec, olen); + if (rc <= 0) + break; + + index_match = ovec[0]; - /* apply the replacement */ - for (r = replace_renamer->replacement; *r != '\0'; r = g_utf8_next_char (r)) + /* append the subject text between the matches */ + for (gint j = first_index_after_match; j < index_match; j++) { - if (G_UNLIKELY ((r[0] == '\\' || r[0] == '$') && r[1] != '\0')) - { - /* skip the first char ($ or \) */ - r += 1; + g_string_append_c (result, subject[j]); + } - /* default to no subst */ - first = 0; - second = 0; + /* over[1] is the first index after a match */ + first_index_after_match = ovec[1]; - /* check the char after the \ or $ */ - if (r[0] == '+' && rc > 1) - { - /* \+ and $+ is replaced with the last subpattern */ - first = ovec[(rc - 1) * 2]; - second = ovec[(rc - 1) * 2 + 1]; - } - else if (r[0] == '&') - { - /* \& and $& is replaced with the first subpattern (the whole match) */ - first = ovec[0]; - second = ovec[1]; - } - else if (r[0] == '`') - { - /* \` and $` is replaced with the text before the whole match */ - first = 0; - second = ovec[0]; - } - else if (r[0] == '\'') - { - /* \' and $' is replaced with the text after the whole match */ - first = ovec[1]; - second = strlen (subject) - 1; - } - else if (g_ascii_isdigit (r[0])) - { - /* \<num> and $<num> is replaced with the <num>th subpattern */ - idx = (r[0] - '0'); - if (G_LIKELY (idx >= 0 && idx < rc)) - { - first = ovec[2 * idx]; - second = ovec[2 * idx + 1]; - } - } - else if (r[-1] == r[0]) - { - /* just add the $ or \ char */ - g_string_append_c (result, r[0]); - continue; - } - else - { - /* just ignore the $ or \ char */ - continue; - } + for (r = replace_renamer->replacement; *r != '\0'; r = g_utf8_next_char (r)) + { + if (G_UNLIKELY ((r[0] == '\\' || r[0] == '$') && r[1] != '\0')) + { + /* skip the first char ($ or \) */ + r += 1; + + /* default to no subst */ + first = 0; + second = 0; - /* substitute the string */ - g_string_append_len (result, subject + first, second - first); + /* check the char after the \ or $ */ + if (r[0] == '+' && rc > 1) + { + /* \+ and $+ is replaced with the last subpattern */ + first = ovec[(rc - 1) * 2]; + second = ovec[(rc - 1) * 2 + 1]; } - else + else if (r[0] == '&') + { + /* \& and $& is replaced with the first subpattern (the whole match) */ + first = ovec[0]; + second = ovec[1]; + } + else if (r[0] == '`') { - /* just append the unichar */ - g_string_append_unichar (result, g_utf8_get_char (r)); + /* \` and $` is replaced with the text before the whole match */ + first = 0; + second = ovec[0]; } + else if (r[0] == '\'') + { + /* \' and $' is replaced with the text after the whole match */ + first = ovec[1]; + second = strlen (subject) - 1; + } + else if (g_ascii_isdigit (r[0])) + { + /* \<num> and $<num> is replaced with the <num>th subpattern */ + idx = (r[0] - '0'); + if (G_LIKELY (idx >= 0 && idx < rc)) + { + first = ovec[2 * idx]; + second = ovec[2 * idx + 1]; + } + } + else if (r[-1] == r[0]) + { + /* just add the $ or \ char */ + g_string_append_c (result, r[0]); + continue; + } + else + { + /* just ignore the $ or \ char */ + continue; + } + + /* substitute the string */ + g_string_append_len (result, subject + first, second - first); + } + else + { + /* just append the unichar */ + g_string_append_unichar (result, g_utf8_get_char (r)); + } } + } - /* append the text after the match */ - g_string_append (result, subject + ovec[1]); + /* append rest of subject string */ + for (size_t i = first_index_after_match; i < strlen (subject); i++) + { + g_string_append_c (result, subject[i]); + } /* release the output vector */ g_free (ovec); -- GitLab