Skip to content

Commit

Permalink
Restore diff based terminal output optimization when synchronized
Browse files Browse the repository at this point in the history
terminal_synchronized ui_option now also controls this behaviour,
update out of date documentation for ui_options as well.

As discussed in #4317
  • Loading branch information
mawww committed Sep 26, 2021
1 parent 1456431 commit 3acf85f
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 25 deletions.
9 changes: 3 additions & 6 deletions doc/pages/options.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,6 @@ are exclusively available to built-in options.
*terminal_enable_mouse*:::
boolean option that enables mouse support

*terminal_change_colors*:::
boolean option that can disable color palette changing if the
terminfo enables it but the terminal does not support it.

*terminal_shift_function_key*:::
Function key from which shifted function key start, if the
terminal sends F13 for <s-F1>, this should be set to 12.
Expand All @@ -367,8 +363,9 @@ are exclusively available to built-in options.
padding line (defaults to *false*)

*terminal_synchronized*:::
if *yes* or *true*, emit iterm2 synchronized output escape sequences
during redraw to reduce flickering (defaults to *false*)
if *yes* or *true*, emit synchronized output escape sequences and
reduce terminal output with sequences that could trigger flickering
if unsynchronized (defaults to *false*)

[[startup-info]]
*startup_info_version* `int`::
Expand Down
6 changes: 4 additions & 2 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,11 @@ void register_options()
" terminal_status_on_top bool\n"
" terminal_set_title bool\n"
" terminal_enable_mouse bool\n"
" terminal_change_colors bool\n"
" terminal_synchronized bool\n"
" terminal_wheel_scroll_amount int\n"
" terminal_shift_function_key int\n",
" terminal_shift_function_key int\n"
" terminal_padding_char codepoint\n"
" terminal_padding_fill bool\n",
UserInterface::Options{});
reg.declare_option("modelinefmt", "format string used to generate the modeline",
"%val{bufname} %val{cursor_line}:%val{cursor_char_column} {{context_info}} {{mode_info}} - %val{client}@[%val{session}]"_str);
Expand Down
86 changes: 69 additions & 17 deletions src/terminal_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,6 @@ void TerminalUI::Screen::output(bool force, bool synchronized, Writer& writer)
if (not lines)
return;

// iTerm2 "begin synchronized update" sequence
if (synchronized)
writer.write("\033[?2026h");

if (force)
{
std::fill_n(hashes.get(), (size_t)size.line, 0);
Expand All @@ -299,17 +295,9 @@ void TerminalUI::Screen::output(bool force, bool synchronized, Writer& writer)
return (hash_value(line.atoms) << 1) | 1; // ensure non-zero
};

for (int line = 0; line < (int)size.line; ++line)
{
auto hash = hash_line(lines[line]);
if (hash == hashes[line])
continue;
hashes[line] = hash;

format_with(writer, "\033[{}H", line + 1);

auto output_line = [&](const Line& line) {
ColumnCount pending_move = 0;
for (auto& [text, skip, face] : lines[line].atoms)
for (auto& [text, skip, face] : line.atoms)
{
if (text.empty() and skip == 0)
continue;
Expand All @@ -329,11 +317,75 @@ void TerminalUI::Screen::output(bool force, bool synchronized, Writer& writer)
else if (skip > 0)
writer.write(String{' ', skip});
}
}
};

// iTerm2 "end synchronized update" sequence
if (synchronized)
writer.write("\033[?2026l");
{
writer.write("\033[?2026h"); // begin synchronized update

struct Change { int keep; int add; int del; };
Vector<Change> changes{Change{}};
auto new_hashes = ArrayView{lines.get(), (size_t)size.line} | transform(hash_line);
for_each_diff(hashes.get(), (int)size.line,
new_hashes.begin(), (int)size.line,
[&changes](DiffOp op, int len) mutable {
switch (op)
{
case DiffOp::Keep:
changes.push_back({len, 0, 0});
break;
case DiffOp::Add:
changes.back().add += len;
break;
case DiffOp::Remove:
changes.back().del += len;
break;
}
});
std::copy(new_hashes.begin(), new_hashes.end(), hashes.get());

int line = 0;
for (auto& change : changes)
{
line += change.keep;
if (int del = change.del - change.add; del > 0)
{
format_with(writer, "\033[{}H\033[{}M", line + 1, del);
line -= del;
}
line += change.del;
}

line = 0;
for (auto& change : changes)
{
line += change.keep;
for (int i = 0; i < change.add; ++i)
{
if (int add = change.add - change.del; i == 0 and add > 0)
format_with(writer, "\033[{}H\033[{}L", line + 1, add);
else
format_with(writer, "\033[{}H", line + 1);

output_line(lines[line++]);
}
}

writer.write("\033[?2026l"); // end synchronized update
}
else
{
for (int line = 0; line < (int)size.line; ++line)
{
auto hash = hash_line(lines[line]);
if (hash == hashes[line])
continue;
hashes[line] = hash;

format_with(writer, "\033[{}H", line + 1);
output_line(lines[line]);
}
}
}

constexpr int TerminalUI::default_shift_function_key;
Expand Down

0 comments on commit 3acf85f

Please sign in to comment.