Instead of re-implementing the search-all algorithm everywhere it is
needed, move it to a re-usable function. This is useful because some
care is required to avoid improper rematches and endless loop, so
avoiding duplication is important (especially if something has to be
fixed someday).
Fix the search & replace algorithm to make sure a replacement won't
possibly affect the next one (e.g. in case of lookahead and lookbehind
regular expressions).
To do so, first find all occurrences and only then perform replacements,
instead of doing both together.
This fixes searching/replacing of any pattern that may be affected by
its replacement (e.g. patterns that look for something not a character
in the match range), including:
* Start/end of line:
Before this change, searching with regular expression "^A" and
replacing with an empty string on the input "AA" would have resulted
in an empty output ("^A" matching again after removing the first
one). Now it properly only removes the leading "A".
* Lookahead/lookbehind:
Pattern "(?<=a)b" with empty replacement and input "abb" would have
resulted in the output "a" instead of "ab".
* And more generally, many patterns matching non-characters like
positions or out-of-match characters.
When performing a regular expression search on a range, and there is a
match past the end of the range, search_find_text() used to improperly
return the position of the match, but without filling the
Sci_TextToFind structure. This lead to the calling code assume there
was a match, and maybe read the uninitialized fields in the
Sci_TextToFind structure, thus leading to undefined behavior.
So, fix search_find_text() so it properly returns -1 when there is a
match but it is outside the bounds.
Use the GtkComboBoxText API and the GtkComboBoxEntry replacement API
and map those to the old equivalents if not available.
This changes the type exposed by ui_combo_box_add_to_history() from
GtkComboBoxEntry to either GtkComboBox (under GTK2) or GtkComboBoxText
(under GTK3). This should not be too much of an issue since
GtkComboBoxEntry and GtkComboBoxtext are subclasses of GtkComboBox,
but this will still emit warnings when when the calling code passes
a GtkComboBoxEntry pointer to ui_combo_box_add_to_history().
However, this requires the calling code to use the same mapping as we
do (GtkComboBoxText = GtkComboBox on GTK2, even on 2.24), or things
will blow and it'll be hard to understand why. This wouldn't be an
issue if the calling code includes our gtkcompat.h header everywhere
it deals with combo boxes, which will be the case if it includes the
Geany headers everywhere but probably won't otherwise. Oh dear.
A possible kind of workaround may be for ui_combo_box_add_to_history()
to do type-checking on its argument and use the actually correct API
for that type.
f4eb89cd7d79738a9c6c45e29abdd9d15d22e4fd was partially wrong and
removed legitimate re-matches when two different matches ends at the
same position. Particularly, the replacement changes are reverted.
Interestingly, Perl and Python does not agree on how to do such
replacements. Python does what I did in the above-cited commit, e.g.
doesn't replace twice if the match end overlaps, but Perl does.
Perl looks more legitimate here since both Python and Perl does find
the overlapping matches when performing a search, so Python is the odd
guy here doing it differently on replace than it does upon search.
For example, replacing using the pattern "a?(?=b)" and the replacement
string "_":
Python: ababcdb -> _b_bcd_b
Perl: ababcdb -> __b__bcd_b
But finding using the same pattern on the same input gives the same
results on both:
Python: ababcdb -> ['a', '', 'a', '', '']
Perl: ababcdb -> ['a', '', 'a', '', '']
Anyway, GLib and us claim to support "Perl-compatible regular
expressions", so we gotta follow Perl, especially in such doubtful
situations.
Regular expressions might match empty ranges, which weren't handled
properly, but generally simply omitted.
For example, the regular expression "^$" (empty line) never matched
because we assumed empty results were not interesting, and actually
needed more care in the code. Alike, an expression matching only on
its lookahead part, like "a?(?=b)" against "b", would stop further
search, although it could even match a non-empty range if "ab" is
present later in the input. This last kind of expressions also lead
to double-replacement because they first matched "ab" and then "b"
alone when re-matching after the "a" replacement.
This commit fixes:
* searching when the matched range is empty;
* step-by-step search when matching an empty range;
* double replacement when the pattern re-matches an empty range
straight after a replacement;
* replacement to and empty string when the matching an empty range.
A know issue though is the step-by-step replacement that won't replace
an empty match but rather find the next match.
If a search matched the very last character of the document, next
search attempt started out of the document bounds. This even lead
to an infinite loop due to an improper sanity check.
By the way, this fixes matching of contiguous results, as the next
search used to improperly skip one character after the result.
Although this looks like a huge issue, it was actually visible almost
only on the match count since the whole matching line was printed.
Use the current document's directory unless the directory field has
already been edited and the current document has not changed.
Otherwise, prepend the current document's directory to the drop-down
history in case it is wanted.
This is useful to avoid losing the edited directory when it is less
likely the user wants to use the current document's directory.
Don't simply split the the extra options string on spaces to build the
grep argument list but rather split it in a shell-style fashion.
This is probably more intuitive for most users, is more consistent with
e.g. custom commands, and allows for spaces in an option or its
argument.
Closes#3516263.
The g_match_info_fetch_pos() function uses a signed value for the match_num
parameter, even though values less than 0 are not valid, so a cast is used.
This makes the code more readable, potentially more future-proof (if
the actual string changes) and better style (catches possible typos at
build-time).
Previously we could put into a message a string where escape sequences
were already translated.
In the code, now we pass the original text together with the one
that is actually searched for. New `original_text' field was added to
GeanySearchData. A bug was fixed in document.c:show_replace_summary(): it
did not escape the "No matches found for ..." string.
Patch by Eugene Arshinov, thanks.
git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5832 ea778897-0a13-0410-b9d1-a72fbfd435f5
grep's --include option doesn't filter files passed explicitly to grep,
so when we build the file list to search in, take the filters into
account.
Also drop the --include options in this case since they aren't useful.
git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5755 ea778897-0a13-0410-b9d1-a72fbfd435f5
User can now select what kind of file patterns should be used:
* all: all files are searched
* project: project patterns are used (only if a project is open)
* custom: manually entered custom patterns are used
Based on a patch by Jiří Techet, thanks.
git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5753 ea778897-0a13-0410-b9d1-a72fbfd435f5
G_(UN)?LIKELY() should be only used on whole conditional expressions,
and only if the branching is very highly predictable, not if it is only
more probable.
These macros should be used with care because a wrong prediction may
be a lot worst than what a good prediction can give.
git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5625 ea778897-0a13-0410-b9d1-a72fbfd435f5
* Don't use strlen(..) > 0 or == 0, simply check the first character
against 0;
* Fix a return without a value (my bad in last commit);
* Fix storing a literal in a non-const string.
git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5610 ea778897-0a13-0410-b9d1-a72fbfd435f5
search when there's no selection.
Change default Find Selection behaviour to not let the X selection
override the current word (can be confusing).
Add docs for Find Selection commands.
git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5253 ea778897-0a13-0410-b9d1-a72fbfd435f5