summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2017-10-11 19:24:01 +0800
committerMaxime Coste <mawww@kakoune.org>2017-11-01 14:05:14 +0800
commit2b97e4e124abd675ccbeef80fff4722d9f7b0fe3 (patch)
treed7b459dcbd33c02c465eeaeaea03f55214a57ab2
parent3c999aba3758188c91143c3c16742faa168b06df (diff)
Regex: Fix handling of ^ and $ in backward matching mode
-rw-r--r--src/regex_impl.cc6
-rw-r--r--src/regex_impl.hh19
-rw-r--r--src/selectors.cc2
3 files changed, 19 insertions, 8 deletions
diff --git a/src/regex_impl.cc b/src/regex_impl.cc
index bb1f3537..11d0429a 100644
--- a/src/regex_impl.cc
+++ b/src/regex_impl.cc
@@ -1193,6 +1193,12 @@ auto test_regex = UnitTest{[]{
}
{
+ TestVM<MatchDirection::Backward> vm{R"($)"};
+ kak_assert(vm.exec("foo\nbar\nbaz\nqux", RegexExecFlags::Search | RegexExecFlags::NotEndOfLine));
+ kak_assert(StringView{vm.captures()[0]} == "\nqux");
+ }
+
+ {
TestVM<> vm{R"(()*)"};
kak_assert(not vm.exec(" "));
}
diff --git a/src/regex_impl.hh b/src/regex_impl.hh
index 6f2137ce..9a8efdd7 100644
--- a/src/regex_impl.hh
+++ b/src/regex_impl.hh
@@ -130,23 +130,28 @@ public:
bool exec(Iterator begin, Iterator end, RegexExecFlags flags)
{
- const bool forward = direction == MatchDirection::Forward;
+ if (flags & RegexExecFlags::NotInitialNull and begin == end)
+ return false;
+
+ constexpr bool forward = direction == MatchDirection::Forward;
const bool prev_avail = flags & RegexExecFlags::PrevAvailable;
+
m_begin = Utf8It{utf8::iterator<Iterator>{forward ? begin : end,
prev_avail ? begin-1 : begin, end}};
m_end = Utf8It{utf8::iterator<Iterator>{forward ? end : begin,
prev_avail ? begin-1 : begin, end}};
- m_flags = flags;
-
- if (flags & RegexExecFlags::NotInitialNull and m_begin == m_end)
- return false;
+ if (forward)
+ m_flags = flags;
+ else // Flip line begin/end flags as we flipped the instructions on compilation.
+ m_flags = (RegexExecFlags)(flags & ~(RegexExecFlags::NotEndOfLine | RegexExecFlags::NotBeginOfLine)) |
+ ((flags & RegexExecFlags::NotEndOfLine) ? RegexExecFlags::NotBeginOfLine : RegexExecFlags::None) |
+ ((flags & RegexExecFlags::NotBeginOfLine) ? RegexExecFlags::NotEndOfLine : RegexExecFlags::None);
- const bool no_saves = (m_flags & RegexExecFlags::NoSaves);
+ const bool no_saves = (flags & RegexExecFlags::NoSaves);
Utf8It start{m_begin};
const bool* start_chars = m_program.start_chars ? m_program.start_chars->map : nullptr;
-
if (flags & RegexExecFlags::Search)
to_next_start(start, m_end, start_chars);
diff --git a/src/selectors.cc b/src/selectors.cc
index c7f237c2..0585c63c 100644
--- a/src/selectors.cc
+++ b/src/selectors.cc
@@ -881,7 +881,7 @@ Selection find_next_match(const Context& context, const Selection& sel, const Re
wrapped = false;
const bool found = (direction == MatchDirection::Forward) ?
find_next(buffer, utf8::next(pos, buffer.end()), matches, regex, wrapped)
- : find_prev(buffer, pos, matches, regex, wrapped);
+ : find_prev(buffer, utf8::previous(pos, buffer.begin()), matches, regex, wrapped);
if (not found or matches[0].first == buffer.end())
throw runtime_error(format("'{}': no matches found", regex.str()));