Merge branch 'master' into remove-buffer-change-listener

Conflicts:
	src/highlighters.cc
This commit is contained in:
Maxime Coste 2014-05-17 11:39:56 +01:00
commit 211b78f536
8 changed files with 146 additions and 52 deletions

View File

@ -2,6 +2,8 @@
#include "event_manager.hh" #include "event_manager.hh"
#include <sys/select.h>
namespace Kakoune namespace Kakoune
{ {
@ -27,9 +29,15 @@ Buffer* create_fifo_buffer(String name, int fd, bool scroll)
Buffer* buffer = new Buffer(std::move(name), Buffer::Flags::Fifo | Buffer::Flags::NoUndo); Buffer* buffer = new Buffer(std::move(name), Buffer::Flags::Fifo | Buffer::Flags::NoUndo);
auto watcher = new FDWatcher(fd, [buffer, scroll](FDWatcher& watcher) { auto watcher = new FDWatcher(fd, [buffer, scroll](FDWatcher& watcher) {
constexpr size_t buffer_size = 1024 * 16; constexpr size_t buffer_size = 2048;
char data[buffer_size]; char data[buffer_size];
ssize_t count = read(watcher.fd(), data, buffer_size); const int fifo = watcher.fd();
timeval tv{ 0, 0 };
fd_set rfds;
ssize_t count = 0;
do
{
count = read(fifo, data, buffer_size);
auto pos = buffer->end()-1; auto pos = buffer->end()-1;
bool prevent_scrolling = pos == buffer->begin() and not scroll; bool prevent_scrolling = pos == buffer->begin() and not scroll;
@ -45,12 +53,17 @@ Buffer* create_fifo_buffer(String name, int fd, bool scroll)
buffer->insert(buffer->end(), "\n"); buffer->insert(buffer->end(), "\n");
} }
FD_ZERO(&rfds);
FD_SET(fifo, &rfds);
}
while (count > 0 and select(fifo+1, &rfds, nullptr, nullptr, &tv) == 1);
if (count <= 0) if (count <= 0)
{ {
kak_assert(buffer->flags() & Buffer::Flags::Fifo); kak_assert(buffer->flags() & Buffer::Flags::Fifo);
buffer->flags() &= ~Buffer::Flags::Fifo; buffer->flags() &= ~Buffer::Flags::Fifo;
buffer->flags() &= ~Buffer::Flags::NoUndo; buffer->flags() &= ~Buffer::Flags::NoUndo;
close(watcher.fd()); close(fifo);
delete &watcher; delete &watcher;
} }
}); });

View File

@ -64,6 +64,7 @@ ColorRegistry::ColorRegistry()
{ "StatusCursor", { Colors::Black, Colors::Cyan } }, { "StatusCursor", { Colors::Black, Colors::Cyan } },
{ "Prompt", { Colors::Yellow, Colors::Default } }, { "Prompt", { Colors::Yellow, Colors::Default } },
{ "MatchingChar", { Colors::Default, Colors::Magenta } }, { "MatchingChar", { Colors::Default, Colors::Magenta } },
{ "Search", { Colors::Default, Colors::Magenta } },
} }
{} {}

View File

@ -333,7 +333,7 @@ const CommandDesc force_delbuf_cmd = {
single_optional_name_param, single_optional_name_param,
CommandFlags::None, CommandFlags::None,
buffer_completer, buffer_completer,
delete_buffer<false> delete_buffer<true>
}; };
const CommandDesc namebuf_cmd = { const CommandDesc namebuf_cmd = {

View File

@ -12,14 +12,17 @@ struct LineAndColumn
LineType line; LineType line;
ColumnType column; ColumnType column;
[[gnu::always_inline]]
constexpr LineAndColumn(LineType line = 0, ColumnType column = 0) constexpr LineAndColumn(LineType line = 0, ColumnType column = 0)
: line(line), column(column) {} : line(line), column(column) {}
[[gnu::always_inline]]
constexpr EffectiveType operator+(EffectiveType other) const constexpr EffectiveType operator+(EffectiveType other) const
{ {
return EffectiveType(line + other.line, column + other.column); return EffectiveType(line + other.line, column + other.column);
} }
[[gnu::always_inline]]
EffectiveType& operator+=(EffectiveType other) EffectiveType& operator+=(EffectiveType other)
{ {
line += other.line; line += other.line;
@ -27,11 +30,13 @@ struct LineAndColumn
return *static_cast<EffectiveType*>(this); return *static_cast<EffectiveType*>(this);
} }
[[gnu::always_inline]]
constexpr EffectiveType operator-(EffectiveType other) const constexpr EffectiveType operator-(EffectiveType other) const
{ {
return EffectiveType(line - other.line, column - other.column); return EffectiveType(line - other.line, column - other.column);
} }
[[gnu::always_inline]]
EffectiveType& operator-=(EffectiveType other) EffectiveType& operator-=(EffectiveType other)
{ {
line -= other.line; line -= other.line;
@ -39,35 +44,41 @@ struct LineAndColumn
return *static_cast<EffectiveType*>(this); return *static_cast<EffectiveType*>(this);
} }
[[gnu::always_inline]]
constexpr bool operator< (EffectiveType other) const constexpr bool operator< (EffectiveType other) const
{ {
return (line != other.line) ? line < other.line return (line != other.line) ? line < other.line
: column < other.column; : column < other.column;
} }
[[gnu::always_inline]]
constexpr bool operator<= (EffectiveType other) const constexpr bool operator<= (EffectiveType other) const
{ {
return (line != other.line) ? line < other.line return (line != other.line) ? line < other.line
: column <= other.column; : column <= other.column;
} }
[[gnu::always_inline]]
constexpr bool operator> (EffectiveType other) const constexpr bool operator> (EffectiveType other) const
{ {
return (line != other.line) ? line > other.line return (line != other.line) ? line > other.line
: column > other.column; : column > other.column;
} }
[[gnu::always_inline]]
constexpr bool operator>= (EffectiveType other) const constexpr bool operator>= (EffectiveType other) const
{ {
return (line != other.line) ? line > other.line return (line != other.line) ? line > other.line
: column >= other.column; : column >= other.column;
} }
[[gnu::always_inline]]
constexpr bool operator== (EffectiveType other) const constexpr bool operator== (EffectiveType other) const
{ {
return line == other.line and column == other.column; return line == other.line and column == other.column;
} }
[[gnu::always_inline]]
constexpr bool operator!= (EffectiveType other) const constexpr bool operator!= (EffectiveType other) const
{ {
return line != other.line or column != other.column; return line != other.line or column != other.column;
@ -76,12 +87,14 @@ struct LineAndColumn
struct ByteCoord : LineAndColumn<ByteCoord, LineCount, ByteCount> struct ByteCoord : LineAndColumn<ByteCoord, LineCount, ByteCount>
{ {
[[gnu::always_inline]]
constexpr ByteCoord(LineCount line = 0, ByteCount column = 0) constexpr ByteCoord(LineCount line = 0, ByteCount column = 0)
: LineAndColumn(line, column) {} : LineAndColumn(line, column) {}
}; };
struct CharCoord : LineAndColumn<CharCoord, LineCount, CharCount> struct CharCoord : LineAndColumn<CharCoord, LineCount, CharCount>
{ {
[[gnu::always_inline]]
constexpr CharCoord(LineCount line = 0, CharCount column = 0) constexpr CharCoord(LineCount line = 0, CharCount column = 0)
: LineAndColumn(line, column) {} : LineAndColumn(line, column) {}
}; };

View File

@ -37,18 +37,25 @@ public:
: m_type(Text), m_text(std::move(str)), colors(colors), attribute(attribute) : m_type(Text), m_text(std::move(str)), colors(colors), attribute(attribute)
{ check_invariant(); } { check_invariant(); }
String content() const StringView content() const
{ {
switch (m_type) switch (m_type)
{ {
case BufferRange: case BufferRange:
return m_buffer->string(m_begin, m_end); {
auto& line = (*m_buffer)[m_begin.line];
if (m_begin.line == m_end.line)
return line.substr(m_begin.column, m_end.column - m_begin.column);
else if (m_begin.line+1 == m_end.line and m_end.column == 0)
return line.substr(m_begin.column);
break;
}
case Text: case Text:
case ReplacedBufferRange: case ReplacedBufferRange:
return m_text; return m_text;
} }
kak_assert(false); kak_assert(false);
return 0; return {};
} }
CharCount length() const CharCount length() const

View File

@ -195,7 +195,7 @@ public:
private: private:
struct Cache struct Cache
{ {
BufferRange m_range; std::pair<LineCount, LineCount> m_range;
size_t m_timestamp = 0; size_t m_timestamp = 0;
std::vector<std::vector<std::pair<ByteCoord, ByteCoord>>> m_matches; std::vector<std::vector<std::pair<ByteCoord, ByteCoord>>> m_matches;
}; };
@ -208,18 +208,21 @@ private:
{ {
Cache& cache = m_cache.get(buffer); Cache& cache = m_cache.get(buffer);
LineCount first_line = range.first.line;
LineCount last_line = std::min(buffer.line_count()-1, range.second.line);
if (buffer.timestamp() == cache.m_timestamp and if (buffer.timestamp() == cache.m_timestamp and
range.first >= cache.m_range.first and first_line >= cache.m_range.first and
range.second <= cache.m_range.second) last_line <= cache.m_range.second)
return cache; return cache;
cache.m_range.first = buffer.clamp({range.first.line - 10, 0}); cache.m_range.first = std::max(0_line, first_line - 10);
cache.m_range.second = buffer.next(buffer.clamp({range.second.line + 10, INT_MAX})); cache.m_range.second = std::min(buffer.line_count()-1, last_line+10);
cache.m_timestamp = buffer.timestamp(); cache.m_timestamp = buffer.timestamp();
cache.m_matches.clear(); cache.m_matches.clear();
RegexIterator re_it{buffer.iterator_at(cache.m_range.first), RegexIterator re_it{buffer.iterator_at(cache.m_range.first),
buffer.iterator_at(cache.m_range.second), m_regex}; buffer.iterator_at(cache.m_range.second+1), m_regex};
RegexIterator re_end; RegexIterator re_end;
for (; re_it != re_end; ++re_it) for (; re_it != re_end; ++re_it)
{ {
@ -266,12 +269,14 @@ HighlighterAndId colorize_regex_factory(HighlighterParameters params)
} }
} }
template<typename RegexGetter> template<typename RegexGetter, typename ColorGetter>
class DynamicRegexHighlighter class DynamicRegexHighlighter
{ {
public: public:
DynamicRegexHighlighter(const ColorSpec& colors, RegexGetter getter) DynamicRegexHighlighter(RegexGetter regex_getter, ColorGetter color_getter)
: m_regex_getter(getter), m_colors(colors), m_colorizer(Regex(), m_colors) {} : m_regex_getter(std::move(regex_getter)),
m_color_getter(std::move(color_getter)),
m_colorizer(Regex(), ColorSpec{}) {}
void operator()(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer) void operator()(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer)
{ {
@ -279,40 +284,56 @@ public:
return; return;
Regex regex = m_regex_getter(context); Regex regex = m_regex_getter(context);
if (regex != m_last_regex) ColorSpec color = m_color_getter(context);
if (regex != m_last_regex or color != m_last_color)
{ {
m_last_regex = regex; m_last_regex = regex;
m_last_color = color;
if (not m_last_regex.empty()) if (not m_last_regex.empty())
m_colorizer = RegexColorizer{m_last_regex, m_colors}; m_colorizer = RegexColorizer{m_last_regex, color};
} }
if (not m_last_regex.empty()) if (not m_last_regex.empty() and not m_last_color.empty())
m_colorizer(context, flags, display_buffer); m_colorizer(context, flags, display_buffer);
} }
private: private:
Regex m_last_regex; Regex m_last_regex;
ColorSpec m_colors;
RegexColorizer m_colorizer;
RegexGetter m_regex_getter; RegexGetter m_regex_getter;
ColorSpec m_last_color;
ColorGetter m_color_getter;
RegexColorizer m_colorizer;
}; };
template<typename RegexGetter, typename ColorGetter>
DynamicRegexHighlighter<RegexGetter, ColorGetter>
make_dynamic_regex_highlighter(RegexGetter regex_getter, ColorGetter color_getter)
{
return DynamicRegexHighlighter<RegexGetter, ColorGetter>(
std::move(regex_getter), std::move(color_getter));
}
HighlighterAndId highlight_search_factory(HighlighterParameters params) HighlighterAndId highlight_search_factory(HighlighterParameters params)
{ {
if (params.size() != 1) if (params.size() != 0)
throw runtime_error("wrong parameter count"); throw runtime_error("wrong parameter count");
try auto get_color = [](const Context& context){
{ return ColorSpec{ { 0, &Kakoune::get_color("Search") } };
ColorSpec colors { { 0, &get_color(params[0]) } }; };
auto get_regex = [](const Context&){ auto get_regex = [](const Context&){
auto s = RegisterManager::instance()['/'].values(Context{}); auto s = RegisterManager::instance()['/'].values(Context{});
try
{
return s.empty() ? Regex{} : Regex{s[0].begin(), s[0].end()}; return s.empty() ? Regex{} : Regex{s[0].begin(), s[0].end()};
};
return {"hlsearch", DynamicRegexHighlighter<decltype(get_regex)>{colors, get_regex}};
} }
catch (boost::regex_error& err) catch (boost::regex_error& err)
{ {
throw runtime_error(String("regex error: ") + err.what()); return Regex{};
} }
};
return {"hlsearch", make_dynamic_regex_highlighter(get_regex, get_color)};
} }
HighlighterAndId highlight_regex_option_factory(HighlighterParameters params) HighlighterAndId highlight_regex_option_factory(HighlighterParameters params)
@ -320,13 +341,19 @@ HighlighterAndId highlight_regex_option_factory(HighlighterParameters params)
if (params.size() != 2) if (params.size() != 2)
throw runtime_error("wrong parameter count"); throw runtime_error("wrong parameter count");
ColorSpec colors { { 0, &get_color(params[1]) } }; const ColorPair& color = get_color(params[1]);
auto get_color = [&](const Context&){
return ColorSpec{ { 0, &color } };
};
String option_name = params[0]; String option_name = params[0];
// verify option type now // verify option type now
GlobalOptions::instance()[option_name].get<Regex>(); GlobalOptions::instance()[option_name].get<Regex>();
auto get_regex = [option_name](const Context& context){ return context.options()[option_name].get<Regex>(); }; auto get_regex = [option_name](const Context& context){
return {"hloption_" + option_name, DynamicRegexHighlighter<decltype(get_regex)>{colors, get_regex}}; return context.options()[option_name].get<Regex>();
};
return {"hloption_" + option_name, make_dynamic_regex_highlighter(get_regex, get_color)};
} }
void expand_tabulations(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer) void expand_tabulations(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer)
@ -470,7 +497,7 @@ void show_matching_char(const Context& context, HighlightFlags flags, DisplayBuf
return false; return false;
return true; return true;
}); });
if (it != end) if (it != end or (*end == pair.first and level == 1))
highlight_range(display_buffer, it.coord(), (it+1).coord(), false, highlight_range(display_buffer, it.coord(), (it+1).coord(), false,
[&](DisplayAtom& atom) { atom.colors = colors; }); [&](DisplayAtom& atom) { atom.colors = colors; });
break; break;

View File

@ -241,8 +241,10 @@ void NCursesUI::draw_line(const DisplayLine& line, CharCount col_index) const
set_color(stdscr, atom.colors); set_color(stdscr, atom.colors);
String atom_content = atom.content(); StringView content = atom.content();
StringView content = atom_content; if (content.empty())
continue;
if (content[content.length()-1] == '\n' and if (content[content.length()-1] == '\n' and
content.char_length() - 1 < m_dimensions.column - col_index) content.char_length() - 1 < m_dimensions.column - col_index)
{ {

View File

@ -10,6 +10,7 @@ template<typename RealType, typename ValueType = int>
class StronglyTypedNumber class StronglyTypedNumber
{ {
public: public:
[[gnu::always_inline]]
explicit constexpr StronglyTypedNumber(ValueType value) explicit constexpr StronglyTypedNumber(ValueType value)
: m_value(value) : m_value(value)
{ {
@ -17,72 +18,96 @@ public:
"RealType is not derived from StronglyTypedNumber"); "RealType is not derived from StronglyTypedNumber");
} }
[[gnu::always_inline]]
constexpr RealType operator+(RealType other) const constexpr RealType operator+(RealType other) const
{ return RealType(m_value + other.m_value); } { return RealType(m_value + other.m_value); }
[[gnu::always_inline]]
constexpr RealType operator-(RealType other) const constexpr RealType operator-(RealType other) const
{ return RealType(m_value - other.m_value); } { return RealType(m_value - other.m_value); }
[[gnu::always_inline]]
constexpr RealType operator*(RealType other) const constexpr RealType operator*(RealType other) const
{ return RealType(m_value * other.m_value); } { return RealType(m_value * other.m_value); }
[[gnu::always_inline]]
constexpr RealType operator/(RealType other) const constexpr RealType operator/(RealType other) const
{ return RealType(m_value / other.m_value); } { return RealType(m_value / other.m_value); }
[[gnu::always_inline]]
RealType& operator+=(RealType other) RealType& operator+=(RealType other)
{ m_value += other.m_value; return static_cast<RealType&>(*this); } { m_value += other.m_value; return static_cast<RealType&>(*this); }
[[gnu::always_inline]]
RealType& operator-=(RealType other) RealType& operator-=(RealType other)
{ m_value -= other.m_value; return static_cast<RealType&>(*this); } { m_value -= other.m_value; return static_cast<RealType&>(*this); }
[[gnu::always_inline]]
RealType& operator*=(RealType other) RealType& operator*=(RealType other)
{ m_value *= other.m_value; return static_cast<RealType&>(*this); } { m_value *= other.m_value; return static_cast<RealType&>(*this); }
[[gnu::always_inline]]
RealType& operator/=(RealType other) RealType& operator/=(RealType other)
{ m_value /= other.m_value; return static_cast<RealType&>(*this); } { m_value /= other.m_value; return static_cast<RealType&>(*this); }
[[gnu::always_inline]]
RealType& operator++() RealType& operator++()
{ ++m_value; return static_cast<RealType&>(*this); } { ++m_value; return static_cast<RealType&>(*this); }
[[gnu::always_inline]]
RealType& operator--() RealType& operator--()
{ --m_value; return static_cast<RealType&>(*this); } { --m_value; return static_cast<RealType&>(*this); }
[[gnu::always_inline]]
RealType operator++(int) RealType operator++(int)
{ RealType backup(static_cast<RealType&>(*this)); ++m_value; return backup; } { RealType backup(static_cast<RealType&>(*this)); ++m_value; return backup; }
[[gnu::always_inline]]
RealType operator--(int) RealType operator--(int)
{ RealType backup(static_cast<RealType&>(*this)); --m_value; return backup; } { RealType backup(static_cast<RealType&>(*this)); --m_value; return backup; }
[[gnu::always_inline]]
constexpr RealType operator-() const { return RealType(-m_value); } constexpr RealType operator-() const { return RealType(-m_value); }
[[gnu::always_inline]]
constexpr RealType operator%(RealType other) const constexpr RealType operator%(RealType other) const
{ return RealType(m_value % other.m_value); } { return RealType(m_value % other.m_value); }
[[gnu::always_inline]]
RealType& operator%=(RealType other) RealType& operator%=(RealType other)
{ m_value %= other.m_value; return static_cast<RealType&>(*this); } { m_value %= other.m_value; return static_cast<RealType&>(*this); }
[[gnu::always_inline]]
constexpr bool operator==(RealType other) const constexpr bool operator==(RealType other) const
{ return m_value == other.m_value; } { return m_value == other.m_value; }
[[gnu::always_inline]]
constexpr bool operator!=(RealType other) const constexpr bool operator!=(RealType other) const
{ return m_value != other.m_value; } { return m_value != other.m_value; }
[[gnu::always_inline]]
constexpr bool operator<(RealType other) const constexpr bool operator<(RealType other) const
{ return m_value < other.m_value; } { return m_value < other.m_value; }
[[gnu::always_inline]]
constexpr bool operator<=(RealType other) const constexpr bool operator<=(RealType other) const
{ return m_value <= other.m_value; } { return m_value <= other.m_value; }
[[gnu::always_inline]]
constexpr bool operator>(RealType other) const constexpr bool operator>(RealType other) const
{ return m_value > other.m_value; } { return m_value > other.m_value; }
[[gnu::always_inline]]
constexpr bool operator>=(RealType other) const constexpr bool operator>=(RealType other) const
{ return m_value >= other.m_value; } { return m_value >= other.m_value; }
[[gnu::always_inline]]
constexpr bool operator!() const constexpr bool operator!() const
{ return !m_value; } { return !m_value; }
[[gnu::always_inline]]
explicit constexpr operator ValueType() const { return m_value; } explicit constexpr operator ValueType() const { return m_value; }
[[gnu::always_inline]]
explicit constexpr operator bool() const { return m_value; } explicit constexpr operator bool() const { return m_value; }
private: private:
ValueType m_value; ValueType m_value;
@ -90,9 +115,11 @@ private:
struct LineCount : public StronglyTypedNumber<LineCount, int> struct LineCount : public StronglyTypedNumber<LineCount, int>
{ {
[[gnu::always_inline]]
constexpr LineCount(int value = 0) : StronglyTypedNumber<LineCount>(value) {} constexpr LineCount(int value = 0) : StronglyTypedNumber<LineCount>(value) {}
}; };
[[gnu::always_inline]]
inline constexpr LineCount operator"" _line(unsigned long long int value) inline constexpr LineCount operator"" _line(unsigned long long int value)
{ {
return LineCount(value); return LineCount(value);
@ -100,9 +127,11 @@ inline constexpr LineCount operator"" _line(unsigned long long int value)
struct ByteCount : public StronglyTypedNumber<ByteCount, int> struct ByteCount : public StronglyTypedNumber<ByteCount, int>
{ {
[[gnu::always_inline]]
constexpr ByteCount(int value = 0) : StronglyTypedNumber<ByteCount>(value) {} constexpr ByteCount(int value = 0) : StronglyTypedNumber<ByteCount>(value) {}
}; };
[[gnu::always_inline]]
inline constexpr ByteCount operator"" _byte(unsigned long long int value) inline constexpr ByteCount operator"" _byte(unsigned long long int value)
{ {
return ByteCount(value); return ByteCount(value);
@ -110,9 +139,11 @@ inline constexpr ByteCount operator"" _byte(unsigned long long int value)
struct CharCount : public StronglyTypedNumber<CharCount, int> struct CharCount : public StronglyTypedNumber<CharCount, int>
{ {
[[gnu::always_inline]]
constexpr CharCount(int value = 0) : StronglyTypedNumber<CharCount>(value) {} constexpr CharCount(int value = 0) : StronglyTypedNumber<CharCount>(value) {}
}; };
[[gnu::always_inline]]
inline constexpr CharCount operator"" _char(unsigned long long int value) inline constexpr CharCount operator"" _char(unsigned long long int value)
{ {
return CharCount(value); return CharCount(value);