From c636a291bdee0d57dbee074bd735bdc45306edab Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 19 Nov 2012 14:19:41 +0100 Subject: [PATCH] Add a regex filter regex filter takes three arguments: is checked from begining of line to point of insertion is checked on the inserted text (usually only one char) 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. --- src/filters.cc | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) 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 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 class SimpleFilterFactory { @@ -88,6 +140,7 @@ void register_filters() registry.register_factory("preserve_indent", SimpleFilterFactory("preserve_indent")); registry.register_factory("cleanup_whitespaces", SimpleFilterFactory("cleanup_whitespaces")); registry.register_factory("expand_tabulations", SimpleFilterFactory("expand_tabulations")); + registry.register_factory("regex", regex_filter_factory); registry.register_factory("group", filter_group_factory); }