Skip to content
Snippets Groups Projects
Commit b6373ad8 authored by ppitu's avatar ppitu Committed by Alexander Schwinn
Browse files

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
parent 62fc1473
No related branches found
No related tags found
No related merge requests found
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment