summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-04-05 19:28:08 +0200
committerMaxime Coste <frrrwww@gmail.com>2013-04-05 19:28:08 +0200
commit1ab8120147b7e5a8dbcdd51f36e8b4d6de2f8567 (patch)
treebe0f71b50d5f889647718e5d1a95610388bec429 /src
parente3f097ad408c670eb3328475627bc0185e4e05d8 (diff)
refactor regex based selectors, move regex construction out of them
Diffstat (limited to 'src')
-rw-r--r--src/main.cc105
-rw-r--r--src/selectors.cc132
-rw-r--r--src/selectors.hh6
-rw-r--r--src/unit_tests.cc2
4 files changed, 116 insertions, 129 deletions
diff --git a/src/main.cc b/src/main.cc
index aa694a1a..aaa85d76 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -116,7 +116,7 @@ void do_replace_with_char(Context& context)
Editor& editor = context.editor();
SelectionList sels = editor.selections();
auto restore_sels = on_scope_end([&]{ editor.select(std::move(sels)); });
- editor.multi_select(std::bind(select_all_matches, _1, "."));
+ editor.multi_select(std::bind(select_all_matches, _1, Regex{"."}));
editor.insert(codepoint_to_str(key.key), InsertMode::Replace);
});
}
@@ -184,20 +184,25 @@ void do_search(Context& context)
if (event == PromptEvent::Abort)
return;
- String ex = str;
+ Regex ex{str};
if (event == PromptEvent::Validate)
{
- if (ex.empty())
- ex = RegisterManager::instance()['/'].values(context)[0];
+ if (str.empty())
+ ex = Regex{RegisterManager::instance()['/'].values(context)[0]};
else
- RegisterManager::instance()['/'] = ex;
+ RegisterManager::instance()['/'] = str;
context.push_jump();
}
- else if (ex.empty() or not context.options()["incsearch"].get<bool>())
+ else if (str.empty() or not context.options()["incsearch"].get<bool>())
return;
context.editor().select(std::bind(select_next_match<forward>, _1, ex), mode);
}
+ catch (boost::regex_error& err)
+ {
+ if (event == PromptEvent::Validate)
+ throw runtime_error("regex error: "_str + err.what());
+ }
catch (runtime_error&)
{
context.editor().select(selections);
@@ -206,25 +211,32 @@ void do_search(Context& context)
if (event == PromptEvent::Validate)
throw;
}
-
});
}
template<SelectMode mode, bool forward>
void do_search_next(Context& context)
{
- const String& ex = RegisterManager::instance()['/'].values(context)[0];
- if (not ex.empty())
+ const String& str = RegisterManager::instance()['/'].values(context)[0];
+ if (not str.empty())
{
- if (mode == SelectMode::Replace)
- context.push_jump();
- int count = context.numeric_param();
- do {
- context.editor().select(std::bind(select_next_match<forward>, _1, ex), mode);
- } while (--count > 0);
+ try
+ {
+ Regex ex{str};
+ if (mode == SelectMode::Replace)
+ context.push_jump();
+ int count = context.numeric_param();
+ do {
+ context.editor().select(std::bind(select_next_match<forward>, _1, ex), mode);
+ } while (--count > 0);
+ }
+ catch (boost::regex_error& err)
+ {
+ throw runtime_error("regex error: "_str + err.what());
+ }
}
else
- context.print_status({ "no search pattern", get_color("Error") });
+ throw runtime_error("no search pattern");
}
template<bool smart>
@@ -318,7 +330,16 @@ void regex_prompt(Context& context, const String prompt, T on_validate)
context.input_handler().prompt(prompt, get_color("Prompt"), complete_nothing,
[=](const String& str, PromptEvent event, Context& context) {
if (event == PromptEvent::Validate)
- on_validate(str, context);
+ {
+ try
+ {
+ on_validate(Regex{str}, context);
+ }
+ catch (boost::regex_error& err)
+ {
+ throw runtime_error("regex error: "_str + err.what());
+ }
+ }
else if (event == PromptEvent::Change)
{
const bool ok = Regex{str, boost::regex_constants::no_except}.status() == 0;
@@ -329,12 +350,11 @@ void regex_prompt(Context& context, const String prompt, T on_validate)
void do_select_regex(Context& context)
{
- regex_prompt(context, "select: ", [](const String& str, Context& context) {
- String ex = str;
+ regex_prompt(context, "select: ", [](Regex ex, Context& context) {
if (ex.empty())
- ex = RegisterManager::instance()['/'].values(context)[0];
+ ex = Regex{RegisterManager::instance()['/'].values(context)[0]};
else
- RegisterManager::instance()['/'] = ex;
+ RegisterManager::instance()['/'] = String{ex.str()};
if (not ex.empty())
context.editor().multi_select(std::bind(select_all_matches, _1, ex));
});
@@ -342,12 +362,11 @@ void do_select_regex(Context& context)
void do_split_regex(Context& context)
{
- regex_prompt(context, "split: ", [](const String& str, Context& context) {
- String ex = str;
+ regex_prompt(context, "split: ", [](Regex ex, Context& context) {
if (ex.empty())
- ex = RegisterManager::instance()['/'].values(context)[0];
+ ex = Regex{RegisterManager::instance()['/'].values(context)[0]};
else
- RegisterManager::instance()['/'] = ex;
+ RegisterManager::instance()['/'] = String{ex.str()};
if (not ex.empty())
context.editor().multi_select(std::bind(split_selection, _1, ex));
});
@@ -355,7 +374,7 @@ void do_split_regex(Context& context)
void do_split_lines(Context& context)
{
- context.editor().multi_select(std::bind(split_selection, _1, "^"));
+ context.editor().multi_select(std::bind(split_selection, _1, Regex{"^"}));
}
void do_join(Context& context)
@@ -367,7 +386,7 @@ void do_join(Context& context)
editor.select(select_to_eol, SelectMode::Extend);
editor.multi_select([](const Selection& sel)
{
- SelectionList res = select_all_matches(sel, "\n\\h*");
+ SelectionList res = select_all_matches(sel, Regex{"\n\\h*"});
// remove last end of line if selected
assert(std::is_sorted(res.begin(), res.end(),
[](const Selection& lhs, const Selection& rhs)
@@ -383,26 +402,18 @@ template<bool matching>
void do_keep(Context& context)
{
constexpr const char* prompt = matching ? "keep matching: " : "keep not matching: ";
- regex_prompt(context, prompt, [](const String& str, Context& context) {
- try
- {
- Regex re(str);
- Editor& editor = context.editor();
- SelectionList sels = editor.selections();
- SelectionList keep;
- for (auto& sel : sels)
- {
- if (boost::regex_search(sel.begin(), sel.end(), re) == matching)
- keep.push_back(sel);
- }
- if (keep.empty())
- throw runtime_error("no selections remaining");
- editor.select(std::move(keep));
- }
- catch (boost::regex_error& error)
+ regex_prompt(context, prompt, [](const Regex& ex, Context& context) {
+ Editor& editor = context.editor();
+ SelectionList sels = editor.selections();
+ SelectionList keep;
+ for (auto& sel : sels)
{
- throw runtime_error("regex_error: "_str + error.what());
+ if (boost::regex_search(sel.begin(), sel.end(), ex) == matching)
+ keep.push_back(sel);
}
+ if (keep.empty())
+ throw runtime_error("no selections remaining");
+ editor.select(std::move(keep));
});
}
@@ -415,7 +426,7 @@ void do_indent(Context& context)
DynamicSelectionList sels{editor.buffer(), editor.selections()};
auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); });
editor.select(select_whole_lines);
- editor.multi_select(std::bind(select_all_matches, _1, "^[^\n]"));
+ editor.multi_select(std::bind(select_all_matches, _1, Regex{"^[^\n]"}));
editor.insert(indent, InsertMode::Insert);
}
@@ -427,7 +438,7 @@ void do_deindent(Context& context)
auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); });
editor.select(select_whole_lines);
editor.multi_select(std::bind(select_all_matches, _1,
- "^\\h{1," + int_to_str(width) + "}"));
+ Regex{"^\\h{1," + int_to_str(width) + "}"}));
editor.erase();
}
diff --git a/src/selectors.cc b/src/selectors.cc
index 77102d59..7fa9bd56 100644
--- a/src/selectors.cc
+++ b/src/selectors.cc
@@ -419,104 +419,80 @@ bool find_match_in_buffer(const BufferIterator pos, MatchResults& matches,
template<bool forward>
-Selection select_next_match(const Selection& selection, const String& regex)
+Selection select_next_match(const Selection& selection, const Regex& regex)
{
- try
- {
- // regex matching do not use Utf8Iterator as boost::regex handle utf8
- // decoding itself
- BufferIterator begin = selection.last();
- BufferIterator end = begin;
- CaptureList captures;
-
- Regex ex{regex.begin(), regex.end()};
- MatchResults matches;
-
- if (find_match_in_buffer<forward>(utf8::next(begin), matches, ex))
- {
- begin = matches[0].first;
- end = matches[0].second;
- for (auto& match : matches)
- captures.push_back(String(match.first, match.second));
- }
- else
- throw runtime_error("'" + regex + "': no matches found");
+ // regex matching do not use Utf8Iterator as boost::regex handle utf8
+ // decoding itself
+ BufferIterator begin = selection.last();
+ BufferIterator end = begin;
+ CaptureList captures;
- if (begin == end)
- ++end;
+ MatchResults matches;
- end = utf8::previous(end);
- if (not forward)
- std::swap(begin, end);
- return Selection{begin, end, std::move(captures)};
- }
- catch (boost::regex_error& err)
+ if (find_match_in_buffer<forward>(utf8::next(begin), matches, regex))
{
- throw runtime_error(String("regex error: ") + err.what());
+ begin = matches[0].first;
+ end = matches[0].second;
+ for (auto& match : matches)
+ captures.push_back(String(match.first, match.second));
}
+ else
+ throw runtime_error("'" + regex.str() + "': no matches found");
+
+ if (begin == end)
+ ++end;
+
+ end = utf8::previous(end);
+ if (not forward)
+ std::swap(begin, end);
+ return Selection{begin, end, std::move(captures)};
}
-template Selection select_next_match<true>(const Selection&, const String&);
-template Selection select_next_match<false>(const Selection&, const String&);
+template Selection select_next_match<true>(const Selection&, const Regex&);
+template Selection select_next_match<false>(const Selection&, const Regex&);
-SelectionList select_all_matches(const Selection& selection, const String& regex)
+SelectionList select_all_matches(const Selection& selection, const Regex& regex)
{
- try
- {
- Regex ex(regex.begin(), regex.end());
- RegexIterator re_it(selection.begin(), selection.end(), ex);
- RegexIterator re_end;
+ RegexIterator re_it(selection.begin(), selection.end(), regex);
+ RegexIterator re_end;
- SelectionList result;
- for (; re_it != re_end; ++re_it)
- {
- BufferIterator begin = (*re_it)[0].first;
- BufferIterator end = (*re_it)[0].second;
+ SelectionList result;
+ for (; re_it != re_end; ++re_it)
+ {
+ BufferIterator begin = (*re_it)[0].first;
+ BufferIterator end = (*re_it)[0].second;
- if (begin == selection.end())
- continue;
+ if (begin == selection.end())
+ continue;
- CaptureList captures;
- for (auto& match : *re_it)
- captures.push_back(String(match.first, match.second));
+ CaptureList captures;
+ for (auto& match : *re_it)
+ captures.push_back(String(match.first, match.second));
- result.push_back(Selection(begin, begin == end ? end : utf8::previous(end),
- std::move(captures)));
- }
- return result;
- }
- catch (boost::regex_error& err)
- {
- throw runtime_error(String("regex error: ") + err.what());
+ result.push_back(Selection(begin, begin == end ? end : utf8::previous(end),
+ std::move(captures)));
}
+ return result;
}
SelectionList split_selection(const Selection& selection,
- const String& separator_regex)
+ const Regex& regex)
{
- try
- {
- Regex ex(separator_regex.begin(), separator_regex.end());
- RegexIterator re_it(selection.begin(), selection.end(), ex,
- boost::regex_constants::match_nosubs);
- RegexIterator re_end;
-
- SelectionList result;
- BufferIterator begin = selection.begin();
- for (; re_it != re_end; ++re_it)
- {
- BufferIterator end = (*re_it)[0].first;
+ RegexIterator re_it(selection.begin(), selection.end(), regex,
+ boost::regex_constants::match_nosubs);
+ RegexIterator re_end;
- result.push_back(Selection(begin, (begin == end) ? end : utf8::previous(end)));
- begin = (*re_it)[0].second;
- }
- result.push_back(Selection(begin, std::max(selection.first(),
- selection.last())));
- return result;
- }
- catch (boost::regex_error& err)
+ SelectionList result;
+ BufferIterator begin = selection.begin();
+ for (; re_it != re_end; ++re_it)
{
- throw runtime_error(String("regex error: ") + err.what());
+ BufferIterator end = (*re_it)[0].first;
+
+ result.push_back(Selection(begin, (begin == end) ? end : utf8::previous(end)));
+ begin = (*re_it)[0].second;
}
+ result.push_back(Selection(begin, std::max(selection.first(),
+ selection.last())));
+ return result;
}
}
diff --git a/src/selectors.hh b/src/selectors.hh
index a591fb4a..9c87c73c 100644
--- a/src/selectors.hh
+++ b/src/selectors.hh
@@ -31,13 +31,13 @@ Selection select_whole_lines(const Selection& selection);
Selection select_whole_buffer(const Selection& selection);
template<bool forward>
-Selection select_next_match(const Selection& selection, const String& regex);
+Selection select_next_match(const Selection& selection, const Regex& regex);
SelectionList select_all_matches(const Selection& selection,
- const String& regex);
+ const Regex& regex);
SelectionList split_selection(const Selection& selection,
- const String& separator_regex);
+ const Regex& separator_regex);
enum class SurroundFlags
{
diff --git a/src/unit_tests.cc b/src/unit_tests.cc
index 913693f2..b4bbead8 100644
--- a/src/unit_tests.cc
+++ b/src/unit_tests.cc
@@ -58,7 +58,7 @@ void test_editor()
{
scoped_edition edition{editor};
editor.select(select_whole_buffer);
- editor.multi_select(std::bind(select_all_matches, std::placeholders::_1, "\\n\\h*"));
+ editor.multi_select(std::bind(select_all_matches, std::placeholders::_1, Regex{"\\n\\h*"}));
for (auto& sel : editor.selections())
{
assert(*sel.begin() == '\n');