Rework partial line display logic

Instead of highlighting full lines and then trim them to make them
fit in the window, highlight only the visible portion, and rely on
the compute_display_setup system introduced for wrapping to setup
our buffer range correctly
This commit is contained in:
Maxime Coste 2017-06-09 13:22:32 +01:00
parent e145d05e34
commit f310db639c
6 changed files with 58 additions and 57 deletions

View File

@ -53,7 +53,6 @@ void DisplayAtom::trim_begin(ColumnCount count)
count).coord(); count).coord();
else else
m_text = m_text.substr(count).str(); m_text = m_text.substr(count).str();
check_invariant();
} }
void DisplayAtom::trim_end(ColumnCount count) void DisplayAtom::trim_end(ColumnCount count)
@ -64,18 +63,6 @@ void DisplayAtom::trim_end(ColumnCount count)
-count).coord(); -count).coord();
else else
m_text = m_text.substr(0, m_text.column_length() - count).str(); m_text = m_text.substr(0, m_text.column_length() - count).str();
check_invariant();
}
void DisplayAtom::check_invariant() const
{
#ifdef KAK_DEBUG
if (has_buffer_range())
{
kak_assert(m_buffer->is_valid(m_range.begin));
kak_assert(m_buffer->is_valid(m_range.end));
}
#endif
} }
DisplayLine::DisplayLine(AtomList atoms) DisplayLine::DisplayLine(AtomList atoms)
@ -93,8 +80,6 @@ DisplayLine::iterator DisplayLine::split(iterator it, BufferCoord pos)
DisplayAtom atom = *it; DisplayAtom atom = *it;
atom.m_range.end = pos; atom.m_range.end = pos;
it->m_range.begin = pos; it->m_range.begin = pos;
atom.check_invariant();
it->check_invariant();
return m_atoms.insert(it, std::move(atom)); return m_atoms.insert(it, std::move(atom));
} }
@ -106,8 +91,6 @@ DisplayLine::iterator DisplayLine::split(iterator it, ColumnCount pos)
DisplayAtom atom(it->m_text.substr(0, pos).str()); DisplayAtom atom(it->m_text.substr(0, pos).str());
it->m_text = it->m_text.substr(pos).str(); it->m_text = it->m_text.substr(pos).str();
atom.check_invariant();
it->check_invariant();
return m_atoms.insert(it, std::move(atom)); return m_atoms.insert(it, std::move(atom));
} }
@ -174,7 +157,6 @@ void DisplayLine::optimize()
next_atom_it = m_atoms.erase(next_atom_it); next_atom_it = m_atoms.erase(next_atom_it);
else else
atom_it = next_atom_it++; atom_it = next_atom_it++;
atom_it->check_invariant();
} }
} }

View File

@ -31,12 +31,10 @@ public:
enum Type { Range, ReplacedRange, Text }; enum Type { Range, ReplacedRange, Text };
DisplayAtom(const Buffer& buffer, BufferCoord begin, BufferCoord end) DisplayAtom(const Buffer& buffer, BufferCoord begin, BufferCoord end)
: m_type(Range), m_buffer(&buffer), m_range{begin, end} : m_type(Range), m_buffer(&buffer), m_range{begin, end} {}
{ check_invariant(); }
DisplayAtom(String str, Face face = Face{}) DisplayAtom(String str, Face face = Face{})
: m_type(Text), m_text(std::move(str)), face(face) : m_type(Text), m_text(std::move(str)), face(face) {}
{ check_invariant(); }
StringView content() const; StringView content() const;
ColumnCount length() const; ColumnCount length() const;
@ -72,8 +70,6 @@ public:
void trim_begin(ColumnCount count); void trim_begin(ColumnCount count);
void trim_end(ColumnCount count); void trim_end(ColumnCount count);
void check_invariant() const;
bool operator==(const DisplayAtom& other) const bool operator==(const DisplayAtom& other) const
{ {
return face == other.face and type() == other.type() and return face == other.face and type() == other.type() and

View File

@ -880,10 +880,16 @@ struct WrapHighlighter : Highlighter
const ColumnCount m_max_width; const ColumnCount m_max_width;
}; };
void expand_tabulations(const Context& context, HighlightPass, DisplayBuffer& display_buffer, BufferRange) struct TabulationHighlighter : Highlighter
{
TabulationHighlighter() : Highlighter{HighlightPass::Move} {}
void do_highlight(const Context& context, HighlightPass,
DisplayBuffer& display_buffer, BufferRange) override
{ {
const ColumnCount tabstop = context.options()["tabstop"].get<int>(); const ColumnCount tabstop = context.options()["tabstop"].get<int>();
auto& buffer = context.buffer(); auto& buffer = context.buffer();
auto win_column = context.window().position().column;
for (auto& line : display_buffer.lines()) for (auto& line : display_buffer.lines())
{ {
for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it) for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it)
@ -902,12 +908,10 @@ void expand_tabulations(const Context& context, HighlightPass, DisplayBuffer& di
if (it+1 != end) if (it+1 != end)
atom_it = line.split(atom_it, (it+1).coord()); atom_it = line.split(atom_it, (it+1).coord());
ColumnCount column = get_column(buffer, tabstop, it.coord()); const ColumnCount column = get_column(buffer, tabstop, it.coord());
ColumnCount count = tabstop - (column % tabstop); const ColumnCount count = tabstop - (column % tabstop) -
String padding; std::max(win_column - column, 0_col);
for (int i = 0; i < count; ++i) atom_it->replace(String{' ', count});
padding += ' ';
atom_it->replace(padding);
break; break;
} }
} }
@ -915,6 +919,25 @@ void expand_tabulations(const Context& context, HighlightPass, DisplayBuffer& di
} }
} }
void do_compute_display_setup(const Context& context, HighlightPass, DisplaySetup& setup) override
{
auto& buffer = context.buffer();
// Ensure that a cursor on a tab character makes the full tab character visible
auto cursor = context.selections().main().cursor();
if (buffer.byte_at(cursor) != '\t')
return;
const ColumnCount tabstop = context.options()["tabstop"].get<int>();
const ColumnCount column = get_column(buffer, tabstop, cursor);
const ColumnCount width = tabstop - (column % tabstop);
const ColumnCount win_end = setup.window_pos.column + setup.window_range.column;
const ColumnCount offset = std::max(column + width - win_end, 0_col);
setup.window_pos.column += offset;
setup.cursor_pos.column -= offset;
}
};
void show_whitespaces(const Context& context, HighlightPass, DisplayBuffer& display_buffer, BufferRange, void show_whitespaces(const Context& context, HighlightPass, DisplayBuffer& display_buffer, BufferRange,
StringView tab, StringView tabpad, StringView tab, StringView tabpad,
StringView spc, StringView lf, StringView nbsp) StringView spc, StringView lf, StringView nbsp)
@ -1935,7 +1958,7 @@ private:
void setup_builtin_highlighters(HighlighterGroup& group) void setup_builtin_highlighters(HighlighterGroup& group)
{ {
group.add_child({"tabulations"_str, make_highlighter(expand_tabulations)}); group.add_child({"tabulations"_str, make_unique<TabulationHighlighter>()});
group.add_child({"unprintable"_str, make_highlighter(expand_unprintable)}); group.add_child({"unprintable"_str, make_highlighter(expand_unprintable)});
group.add_child({"selections"_str, make_highlighter(highlight_selections)}); group.add_child({"selections"_str, make_highlighter(highlight_selections)});
} }

View File

@ -122,12 +122,15 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context)
kak_assert(&buffer() == &context.buffer()); kak_assert(&buffer() == &context.buffer());
compute_display_setup(context); compute_display_setup(context);
const int tabstop = context.options()["tabstop"].get<int>();
for (LineCount line = 0; line < m_range.line; ++line) for (LineCount line = 0; line < m_range.line; ++line)
{ {
LineCount buffer_line = m_position.line + line; LineCount buffer_line = m_position.line + line;
if (buffer_line >= buffer().line_count()) if (buffer_line >= buffer().line_count())
break; break;
lines.emplace_back(AtomList{ {buffer(), buffer_line, buffer_line+1} }); auto beg_byte = get_byte_to_column(buffer(), tabstop, {buffer_line, m_position.column});
auto end_byte = get_byte_to_column(buffer(), tabstop, {buffer_line, m_position.column + m_range.column});
lines.emplace_back(AtomList{ {buffer(), {buffer_line, beg_byte}, {buffer_line, end_byte}} });
} }
m_display_buffer.compute_range(); m_display_buffer.compute_range();
@ -137,9 +140,6 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context)
for (auto pass : { HighlightPass::Wrap, HighlightPass::Move, HighlightPass::Colorize }) for (auto pass : { HighlightPass::Wrap, HighlightPass::Move, HighlightPass::Colorize })
m_builtin_highlighters.highlight(context, pass, m_display_buffer, range); m_builtin_highlighters.highlight(context, pass, m_display_buffer, range);
// cut the start of the line before m_position.column
for (auto& line : lines)
line.trim(m_position.column, m_dimensions.column, true);
m_display_buffer.optimize(); m_display_buffer.optimize();
m_last_setup = build_setup(context); m_last_setup = build_setup(context);

View File

@ -1,6 +1,6 @@
{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "23456789012345678901234567890123456789012345678901234567890123456789012345678901" }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "234567890123456789012345678901234567890123456789012345678901234567890123456" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "black", "bg": "white", "attributes": [] }, "contents": " " }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "90" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "7890\u000a" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] } { "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "90123456789012345678901234567890123456789012345678901234567890123456789012345678" }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "90123456789012345678901234567890123456789012345678901234567890123456" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "black", "bg": "white", "attributes": [] }, "contents": " " }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "90" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "7890\u000a" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] }
{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] } { "jsonrpc": "2.0", "method": "menu_hide", "params": [] }
{ "jsonrpc": "2.0", "method": "info_hide", "params": [] } { "jsonrpc": "2.0", "method": "info_hide", "params": [] }
{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 2:78 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - unnamed0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] } { "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 2:78 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - unnamed0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] }
{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 1, "column": 79 }] } { "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 1, "column": 72 }] }
{ "jsonrpc": "2.0", "method": "refresh", "params": [true] } { "jsonrpc": "2.0", "method": "refresh", "params": [true] }

View File

@ -1,4 +1,4 @@
{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "attributes": [] }, "contents": "\"" }, { "face": { "fg": "green", "bg": "default", "attributes": [] }, "contents": "abcdefgh\"" }, { "face": { "fg": "yellow", "bg": "default", "attributes": [] }, "contents": " hehe " }, { "face": { "fg": "red", "bg": "default", "attributes": [] }, "contents": "${ youhou{hihi} }" }, { "face": { "fg": "yellow", "bg": "default", "attributes": [] }, "contents": "\u000a" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] } { "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "attributes": [] }, "contents": "\"" }, { "face": { "fg": "green", "bg": "default", "attributes": [] }, "contents": "abcdefgh\"" }, { "face": { "fg": "yellow", "bg": "default", "attributes": [] }, "contents": " hehe " }, { "face": { "fg": "red", "bg": "default", "attributes": [] }, "contents": "${ youhou{hihi} }" }, { "face": { "fg": "yellow", "bg": "default", "attributes": [] }, "contents": "\u000a" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] }
{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] } { "jsonrpc": "2.0", "method": "menu_hide", "params": [] }
{ "jsonrpc": "2.0", "method": "info_hide", "params": [] } { "jsonrpc": "2.0", "method": "info_hide", "params": [] }
{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - unnamed0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] } { "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - unnamed0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] }