summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2012-11-19 14:19:41 +0100
committerMaxime Coste <frrrwww@gmail.com>2012-11-19 14:19:41 +0100
commitc636a291bdee0d57dbee074bd735bdc45306edab (patch)
treeb576abddd4790fcbb7e5c058fdb184acdd5f61f3 /src
parent22c545884fc9707720db4f7a6b69fbb027ad7699 (diff)
Add a regex filter
regex filter takes three arguments: <line_match> <insert_match> <replacement> <line_match> is checked from begining of line to point of insertion <insert_match> is checked on the inserted text (usually only one char) <replacement> is used to replace the inserted text, it can use $1..9 for captures in line_match, and $c to specify the cursor position. for example, ':addfilter regex .* \( ($c)' makes inserting an opening parens insert the closing one as well, keeping the insertion cursor in the right spot.
Diffstat (limited to 'src')
-rw-r--r--src/filters.cc53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/filters.cc b/src/filters.cc
index d66bf652..d9fab000 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -59,6 +59,58 @@ void expand_tabulations(Buffer& buffer, Selection& selection, String& content)
}
}
+struct RegexFilter
+{
+ RegexFilter(const String& line_match, const String& insert_match,
+ const String& replacement)
+ : m_line_match(line_match.c_str()), m_insert_match(insert_match.c_str()),
+ m_replacement(replacement.c_str()) {}
+
+ void operator() (Buffer& buffer, Selection& selection, String& content)
+ {
+ const auto& position = selection.last();
+ auto line_begin = buffer.iterator_at_line_begin(position);
+ boost::match_results<BufferIterator> results;
+ if (boost::regex_match(content.c_str(), m_insert_match) and
+ boost::regex_match(line_begin, position, results, m_line_match))
+ {
+ String suffix;
+ content = results.format(m_replacement.c_str());
+ auto it = std::find(content.begin(), content.end(), '$');
+ if (it != content.end())
+ {
+ ++it;
+ if (it != content.end() && *it == 'c')
+ {
+ String suffix(it+1, content.end());
+ content = String(content.begin(), it-1);
+
+ auto first = selection.first();
+ auto last = selection.last();
+ buffer.insert(position, suffix);
+ if (selection.first() == selection.last())
+ selection.first() -= suffix.length();
+ selection.last() -= suffix.length();
+ }
+ }
+ }
+ }
+
+private:
+ Regex m_line_match;
+ Regex m_insert_match;
+ String m_replacement;
+};
+
+FilterAndId regex_filter_factory(const FilterParameters& params)
+{
+ if (params.size() != 3)
+ throw runtime_error("wrong parameter count");
+
+ return FilterAndId{"re" + params[0] + "__" + params[1],
+ RegexFilter{params[0], params[1], params[2]}};
+}
+
template<void (*filter_func)(Buffer&, Selection&, String&)>
class SimpleFilterFactory
{
@@ -88,6 +140,7 @@ void register_filters()
registry.register_factory("preserve_indent", SimpleFilterFactory<preserve_indent>("preserve_indent"));
registry.register_factory("cleanup_whitespaces", SimpleFilterFactory<cleanup_whitespaces>("cleanup_whitespaces"));
registry.register_factory("expand_tabulations", SimpleFilterFactory<expand_tabulations>("expand_tabulations"));
+ registry.register_factory("regex", regex_filter_factory);
registry.register_factory("group", filter_group_factory);
}