Wrap: Add -indent switch support that wraps preserving line indent
This commit is contained in:
parent
6bc408e9b9
commit
6f2088cbc4
|
@ -94,6 +94,9 @@ add-highlighter window regex //\h*(TODO:)[^\n]* 0:cyan 1:yellow,red
|
||||||
*-word*:::
|
*-word*:::
|
||||||
wrap at word boundaries instead of codepoint boundaries.
|
wrap at word boundaries instead of codepoint boundaries.
|
||||||
|
|
||||||
|
*-indent*:::
|
||||||
|
preserve line indent when wrapping.
|
||||||
|
|
||||||
*-width <max_width>*:::
|
*-width <max_width>*:::
|
||||||
wrap text at *max_width* if the window is wider.
|
wrap text at *max_width* if the window is wider.
|
||||||
|
|
||||||
|
|
|
@ -654,8 +654,9 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params)
|
||||||
|
|
||||||
struct WrapHighlighter : Highlighter
|
struct WrapHighlighter : Highlighter
|
||||||
{
|
{
|
||||||
WrapHighlighter(ColumnCount max_width, bool word_wrap)
|
WrapHighlighter(ColumnCount max_width, bool word_wrap, bool preserve_indent)
|
||||||
: Highlighter{HighlightPass::Wrap}, m_max_width{max_width}, m_word_wrap{word_wrap} {}
|
: Highlighter{HighlightPass::Wrap}, m_max_width{max_width},
|
||||||
|
m_word_wrap{word_wrap}, m_preserve_indent{preserve_indent} {}
|
||||||
|
|
||||||
void do_highlight(const Context& context, HighlightPass pass,
|
void do_highlight(const Context& context, HighlightPass pass,
|
||||||
DisplayBuffer& display_buffer, BufferRange) override
|
DisplayBuffer& display_buffer, BufferRange) override
|
||||||
|
@ -673,6 +674,9 @@ struct WrapHighlighter : Highlighter
|
||||||
{
|
{
|
||||||
const LineCount buf_line = it->range().begin.line;
|
const LineCount buf_line = it->range().begin.line;
|
||||||
const ByteCount line_length = buffer[buf_line].length();
|
const ByteCount line_length = buffer[buf_line].length();
|
||||||
|
ColumnCount indent = m_preserve_indent ? line_indent(buffer, tabstop, buf_line) : 0_col;
|
||||||
|
if (indent >= wrap_column) // do not preserve indent when its bigger than wrap column
|
||||||
|
indent = 0;
|
||||||
|
|
||||||
auto coord = next_split_coord(buffer, wrap_column, tabstop, buf_line);
|
auto coord = next_split_coord(buffer, wrap_column, tabstop, buf_line);
|
||||||
if (buffer.is_valid(coord) and not buffer.is_end(coord))
|
if (buffer.is_valid(coord) and not buffer.is_end(coord))
|
||||||
|
@ -695,9 +699,12 @@ struct WrapHighlighter : Highlighter
|
||||||
DisplayLine new_line{ AtomList{ atom_it, line.end() } };
|
DisplayLine new_line{ AtomList{ atom_it, line.end() } };
|
||||||
line.erase(atom_it, line.end());
|
line.erase(atom_it, line.end());
|
||||||
|
|
||||||
|
if (indent != 0)
|
||||||
|
new_line.insert(new_line.begin(), DisplayAtom{String{' ', indent}});
|
||||||
|
|
||||||
if (it+1 - display_buffer.lines().begin() == win_height)
|
if (it+1 - display_buffer.lines().begin() == win_height)
|
||||||
{
|
{
|
||||||
if (cursor >= new_line.begin()->begin()) // strip first lines if cursor is not visible
|
if (cursor >= new_line.range().begin) // strip first lines if cursor is not visible
|
||||||
{
|
{
|
||||||
display_buffer.lines().erase(display_buffer.lines().begin(), display_buffer.lines().begin()+1);
|
display_buffer.lines().erase(display_buffer.lines().begin(), display_buffer.lines().begin()+1);
|
||||||
--it;
|
--it;
|
||||||
|
@ -710,7 +717,7 @@ struct WrapHighlighter : Highlighter
|
||||||
}
|
}
|
||||||
it = display_buffer.lines().insert(it+1, new_line);
|
it = display_buffer.lines().insert(it+1, new_line);
|
||||||
|
|
||||||
coord = next_split_coord(buffer, wrap_column, tabstop, coord);
|
coord = next_split_coord(buffer, wrap_column - indent, tabstop, coord);
|
||||||
atom_it = it->begin();
|
atom_it = it->begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -727,13 +734,14 @@ struct WrapHighlighter : Highlighter
|
||||||
const auto& cursor = context.selections().main().cursor();
|
const auto& cursor = context.selections().main().cursor();
|
||||||
const int tabstop = context.options()["tabstop"].get<int>();
|
const int tabstop = context.options()["tabstop"].get<int>();
|
||||||
|
|
||||||
auto line_wrap_count = [&](LineCount line) {
|
auto line_wrap_count = [&](LineCount line, ColumnCount indent) {
|
||||||
LineCount count = 0;
|
LineCount count = 0;
|
||||||
BufferCoord coord{line};
|
BufferCoord coord{line};
|
||||||
const ByteCount line_length = buffer[line].length();
|
const ByteCount line_length = buffer[line].length();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
coord = next_split_coord(buffer, wrap_column, tabstop, coord);
|
coord = next_split_coord(buffer, wrap_column - (coord.column == 0 ? 0_col : indent),
|
||||||
|
tabstop, coord);
|
||||||
if (coord.column == line_length)
|
if (coord.column == line_length)
|
||||||
break;
|
break;
|
||||||
++count;
|
++count;
|
||||||
|
@ -756,7 +764,11 @@ struct WrapHighlighter : Highlighter
|
||||||
if (buf_line >= buffer.line_count())
|
if (buf_line >= buffer.line_count())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const auto wrap_count = line_wrap_count(buf_line);
|
ColumnCount indent = m_preserve_indent ? line_indent(buffer, tabstop, buf_line) : 0_col;
|
||||||
|
if (indent >= wrap_column) // do not preserve indent when its bigger than wrap column
|
||||||
|
indent = 0;
|
||||||
|
|
||||||
|
const auto wrap_count = line_wrap_count(buf_line, indent);
|
||||||
setup.window_range.line -= wrap_count;
|
setup.window_range.line -= wrap_count;
|
||||||
|
|
||||||
if (win_line < setup.cursor_pos.line)
|
if (win_line < setup.cursor_pos.line)
|
||||||
|
@ -767,10 +779,14 @@ struct WrapHighlighter : Highlighter
|
||||||
BufferCoord coord{buf_line};
|
BufferCoord coord{buf_line};
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
auto split_coord = next_split_coord(buffer, wrap_column, tabstop, coord);
|
auto split_coord = next_split_coord(buffer, wrap_column - (coord.column == 0 ? 0_col : indent),
|
||||||
|
tabstop, coord);
|
||||||
if (split_coord.column > cursor.column)
|
if (split_coord.column > cursor.column)
|
||||||
{
|
{
|
||||||
setup.cursor_pos.column = get_column(buffer, tabstop, cursor) - get_column(buffer, tabstop, coord);
|
setup.cursor_pos.column = get_column(buffer, tabstop, cursor) - get_column(buffer, tabstop, coord);
|
||||||
|
if (coord.column != 0)
|
||||||
|
setup.cursor_pos.column += indent;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++setup.cursor_pos.line;
|
++setup.cursor_pos.line;
|
||||||
|
@ -786,7 +802,7 @@ struct WrapHighlighter : Highlighter
|
||||||
while (setup.window_pos.line < cursor.line and
|
while (setup.window_pos.line < cursor.line and
|
||||||
setup.cursor_pos.line >= win_height - setup.scroll_offset.line)
|
setup.cursor_pos.line >= win_height - setup.scroll_offset.line)
|
||||||
{
|
{
|
||||||
auto removed_lines = 1 + line_wrap_count(setup.window_pos.line++);
|
auto removed_lines = 1 + line_wrap_count(setup.window_pos.line++, indent);
|
||||||
setup.cursor_pos.line -= removed_lines;
|
setup.cursor_pos.line -= removed_lines;
|
||||||
win_line -= removed_lines;
|
win_line -= removed_lines;
|
||||||
// removed one line from the range, added removed_lines potential ones
|
// removed one line from the range, added removed_lines potential ones
|
||||||
|
@ -807,6 +823,9 @@ struct WrapHighlighter : Highlighter
|
||||||
auto column = get_column(buffer, tabstop, coord);
|
auto column = get_column(buffer, tabstop, coord);
|
||||||
auto col = get_byte_to_column(
|
auto col = get_byte_to_column(
|
||||||
buffer, tabstop, {coord.line, column + wrap_column});
|
buffer, tabstop, {coord.line, column + wrap_column});
|
||||||
|
if (col == coord.column) // Can happen if we try to wrap on a tab char
|
||||||
|
col = buffer.char_next(coord).column;
|
||||||
|
|
||||||
BufferCoord split_coord{coord.line, col};
|
BufferCoord split_coord{coord.line, col};
|
||||||
|
|
||||||
if (m_word_wrap)
|
if (m_word_wrap)
|
||||||
|
@ -823,10 +842,20 @@ struct WrapHighlighter : Highlighter
|
||||||
return split_coord;
|
return split_coord;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ColumnCount line_indent(const Buffer& buffer, int tabstop, LineCount line) const
|
||||||
|
{
|
||||||
|
StringView l = buffer[line];
|
||||||
|
auto col = 0_byte;
|
||||||
|
while (is_horizontal_blank(l[col]))
|
||||||
|
++col;
|
||||||
|
return get_column(buffer, tabstop, {line, col});
|
||||||
|
}
|
||||||
|
|
||||||
static HighlighterAndId create(HighlighterParameters params)
|
static HighlighterAndId create(HighlighterParameters params)
|
||||||
{
|
{
|
||||||
static const ParameterDesc param_desc{
|
static const ParameterDesc param_desc{
|
||||||
{ { "word", { false, "" } },
|
{ { "word", { false, "" } },
|
||||||
|
{ "indent", { false, "" } },
|
||||||
{ "width", { true, "" } } },
|
{ "width", { true, "" } } },
|
||||||
ParameterDesc::Flags::None, 0, 0
|
ParameterDesc::Flags::None, 0, 0
|
||||||
};
|
};
|
||||||
|
@ -836,10 +865,12 @@ struct WrapHighlighter : Highlighter
|
||||||
if (auto width = parser.get_switch("width"))
|
if (auto width = parser.get_switch("width"))
|
||||||
max_width = str_to_int(*width);
|
max_width = str_to_int(*width);
|
||||||
|
|
||||||
return {"wrap", std::make_unique<WrapHighlighter>(max_width, (bool)parser.get_switch("word"))};
|
return {"wrap", std::make_unique<WrapHighlighter>(max_width, (bool)parser.get_switch("word"),
|
||||||
|
(bool)parser.get_switch("indent"))};
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool m_word_wrap;
|
const bool m_word_wrap;
|
||||||
|
const bool m_preserve_indent;
|
||||||
const ColumnCount m_max_width;
|
const ColumnCount m_max_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user