kakoune/src/filters.cc

145 lines
4.6 KiB
C++
Raw Normal View History

#include "filters.hh"
2013-04-09 20:05:40 +02:00
#include "buffer.hh"
2012-11-23 18:35:05 +01:00
#include "selection.hh"
namespace Kakoune
{
void preserve_indent(Buffer& buffer, Selection& selection, String& content)
{
if (content == "\n")
{
BufferCoord line_begin{selection.last().line, 0};
2013-05-27 19:20:59 +02:00
auto first_non_white = buffer.iterator_at(line_begin);
2013-01-04 18:39:13 +01:00
while ((*first_non_white == '\t' or *first_non_white == ' ') and
2013-06-04 18:53:56 +02:00
first_non_white != buffer.end())
2013-01-04 18:39:13 +01:00
++first_non_white;
content += buffer.string(line_begin, first_non_white.coord());
}
}
void cleanup_whitespaces(Buffer& buffer, Selection& selection, String& content)
{
2013-05-27 19:20:59 +02:00
const auto position = buffer.iterator_at(selection.last());
2013-06-04 18:53:56 +02:00
if (content[0] == '\n' and position != buffer.begin())
{
2013-05-27 19:20:59 +02:00
auto whitespace_start = position-1;
while ((*whitespace_start == ' ' or *whitespace_start == '\t') and
2013-06-04 18:53:56 +02:00
whitespace_start != buffer.begin())
--whitespace_start;
++whitespace_start;
2013-05-27 19:20:59 +02:00
if (whitespace_start != position)
buffer.erase(whitespace_start.coord(), position.coord());
}
}
void expand_tabulations(Buffer& buffer, Selection& selection, String& content)
{
const int tabstop = buffer.options()["tabstop"].get<int>();
if (content == "\t")
{
int column = 0;
2013-05-27 19:20:59 +02:00
const auto position = buffer.iterator_at(selection.last());
2013-06-04 14:17:11 +02:00
for (auto it = buffer.iterator_at(selection.last().line);
2013-05-27 19:20:59 +02:00
it != position; ++it)
{
2013-05-27 19:20:59 +02:00
kak_assert(*it != '\n');
if (*it == '\t')
column += tabstop - (column % tabstop);
else
++column;
}
2013-05-27 19:20:59 +02:00
CharCount count = tabstop - (column % tabstop);
content = String(' ', count);
}
}
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)
{
2013-05-27 19:20:59 +02:00
const auto position = buffer.iterator_at(selection.last());
2013-06-04 14:17:11 +02:00
auto line_begin = buffer.iterator_at(selection.last().line);
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))
{
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(last, suffix);
if (first == last)
first = buffer.advance(first, -suffix.length());
last = buffer.advance(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
{
public:
SimpleFilterFactory(const String& id) : m_id(id) {}
FilterAndId operator()(const FilterParameters& params) const
{
return FilterAndId(m_id, FilterFunc(filter_func));
}
private:
String m_id;
};
FilterAndId filter_group_factory(const FilterParameters& params)
{
if (params.size() != 1)
throw runtime_error("wrong parameter count");
return FilterAndId(params[0], FilterGroup());
}
void register_filters()
{
FilterRegistry& registry = FilterRegistry::instance();
registry.register_func("preserve_indent", SimpleFilterFactory<preserve_indent>("preserve_indent"));
registry.register_func("cleanup_whitespaces", SimpleFilterFactory<cleanup_whitespaces>("cleanup_whitespaces"));
registry.register_func("expand_tabulations", SimpleFilterFactory<expand_tabulations>("expand_tabulations"));
registry.register_func("regex", regex_filter_factory);
registry.register_func("group", filter_group_factory);
}
}