Revert "Stop caching line breaks in the prompt calculation"
This reverts commit a2ff32d9043a87cb74016181637d3e744017bb4f. Per comments on the commit, the original code had correct handling of line breaks inside escapes.
This commit is contained in:
parent
80618599f9
commit
17fc542082
@ -5732,19 +5732,19 @@ void test_layout_cache() {
|
||||
for (size_t i = 0; i < layout_cache_t::prompt_cache_max_size; i++) {
|
||||
wcstring input = std::to_wstring(i);
|
||||
do_test(!seqs.find_prompt_layout(input));
|
||||
seqs.add_prompt_layout({input, huge, input, {i, 0, 0}});
|
||||
do_test(seqs.find_prompt_layout(input)->layout.line_count == i);
|
||||
seqs.add_prompt_layout({input, huge, input, {{}, i, 0}});
|
||||
do_test(seqs.find_prompt_layout(input)->layout.max_line_width == i);
|
||||
}
|
||||
|
||||
size_t expected_evictee = 3;
|
||||
for (size_t i = 0; i < layout_cache_t::prompt_cache_max_size; i++) {
|
||||
if (i != expected_evictee)
|
||||
do_test(seqs.find_prompt_layout(std::to_wstring(i))->layout.line_count == i);
|
||||
do_test(seqs.find_prompt_layout(std::to_wstring(i))->layout.max_line_width == i);
|
||||
}
|
||||
|
||||
seqs.add_prompt_layout({L"whatever", huge, L"whatever", {100, 0, 0}});
|
||||
seqs.add_prompt_layout({L"whatever", huge, L"whatever", {{}, 100, 0}});
|
||||
do_test(!seqs.find_prompt_layout(std::to_wstring(expected_evictee)));
|
||||
do_test(seqs.find_prompt_layout(L"whatever", huge)->layout.line_count == 100);
|
||||
do_test(seqs.find_prompt_layout(L"whatever", huge)->layout.max_line_width == 100);
|
||||
}
|
||||
|
||||
void test_prompt_truncation() {
|
||||
@ -5754,7 +5754,16 @@ void test_prompt_truncation() {
|
||||
|
||||
/// Helper to return 'layout' formatted as a string for easy comparison.
|
||||
auto format_layout = [&] {
|
||||
return format_string(L"%lu,%lu,%lu", (unsigned long)layout.line_count,
|
||||
wcstring line_breaks = L"";
|
||||
bool first = true;
|
||||
for (const size_t line_break : layout.line_breaks) {
|
||||
if (!first) {
|
||||
line_breaks.push_back(L',');
|
||||
}
|
||||
line_breaks.append(format_string(L"%lu", (unsigned long)line_break));
|
||||
first = false;
|
||||
}
|
||||
return format_string(L"[%ls],%lu,%lu", line_breaks.c_str(),
|
||||
(unsigned long)layout.max_line_width,
|
||||
(unsigned long)layout.last_line_width);
|
||||
};
|
||||
@ -5766,12 +5775,22 @@ void test_prompt_truncation() {
|
||||
|
||||
// No truncation.
|
||||
layout = cache.calc_prompt_layout(L"abcd", &trunc);
|
||||
do_test(format_layout() == L"1,4,4");
|
||||
do_test(format_layout() == L"[],4,4");
|
||||
do_test(trunc == L"abcd");
|
||||
|
||||
// Line break calculation.
|
||||
layout = cache.calc_prompt_layout(join({
|
||||
L"0123456789ABCDEF", //
|
||||
L"012345", //
|
||||
L"0123456789abcdef", //
|
||||
L"xyz" //
|
||||
}),
|
||||
&trunc, 80);
|
||||
do_test(format_layout() == L"[16,23,40],16,3");
|
||||
|
||||
// Basic truncation.
|
||||
layout = cache.calc_prompt_layout(L"0123456789ABCDEF", &trunc, 8);
|
||||
do_test(format_layout() == L"1,8,8");
|
||||
do_test(format_layout() == L"[],8,8");
|
||||
do_test(trunc == ellipsis + L"9ABCDEF");
|
||||
|
||||
// Multiline truncation.
|
||||
@ -5782,24 +5801,24 @@ void test_prompt_truncation() {
|
||||
L"xyz" //
|
||||
}),
|
||||
&trunc, 8);
|
||||
do_test(format_layout() == L"4,8,3");
|
||||
do_test(format_layout() == L"[8,15,24],8,3");
|
||||
do_test(trunc == join({ellipsis + L"9ABCDEF", L"012345", ellipsis + L"9abcdef", L"xyz"}));
|
||||
|
||||
// Escape sequences are not truncated.
|
||||
layout =
|
||||
cache.calc_prompt_layout(L"\x1B]50;CurrentDir=test/foo\x07NOT_PART_OF_SEQUENCE", &trunc, 4);
|
||||
do_test(format_layout() == L"1,4,4");
|
||||
do_test(format_layout() == L"[],4,4");
|
||||
do_test(trunc == ellipsis + L"\x1B]50;CurrentDir=test/foo\x07NCE");
|
||||
|
||||
// Newlines in escape sequences are skipped.
|
||||
layout = cache.calc_prompt_layout(L"\x1B]50;CurrentDir=\ntest/foo\x07NOT_PART_OF_SEQUENCE",
|
||||
&trunc, 4);
|
||||
do_test(format_layout() == L"1,4,4");
|
||||
do_test(format_layout() == L"[],4,4");
|
||||
do_test(trunc == ellipsis + L"\x1B]50;CurrentDir=\ntest/foo\x07NCE");
|
||||
|
||||
// We will truncate down to one character if we have to.
|
||||
layout = cache.calc_prompt_layout(L"Yay", &trunc, 1);
|
||||
do_test(format_layout() == L"1,1,1");
|
||||
do_test(format_layout() == L"[],1,1");
|
||||
do_test(trunc == ellipsis);
|
||||
}
|
||||
|
||||
|
@ -368,7 +368,7 @@ prompt_layout_t layout_cache_t::calc_prompt_layout(const wcstring &prompt_str,
|
||||
size_t prompt_len = prompt_str.size();
|
||||
const wchar_t *prompt = prompt_str.c_str();
|
||||
|
||||
prompt_layout_t layout{1, 0, 0};
|
||||
prompt_layout_t layout = {{}, 0, 0};
|
||||
wcstring trunc_prompt;
|
||||
|
||||
size_t run_start = 0;
|
||||
@ -390,7 +390,7 @@ prompt_layout_t layout_cache_t::calc_prompt_layout(const wcstring &prompt_str,
|
||||
wchar_t endc = prompt[run_end];
|
||||
if (endc) {
|
||||
if (endc == L'\n' || endc == L'\f') {
|
||||
layout.line_count += 1;
|
||||
layout.line_breaks.push_back(trunc_prompt.size());
|
||||
}
|
||||
trunc_prompt.push_back(endc);
|
||||
run_start = run_end + 1;
|
||||
@ -408,10 +408,10 @@ prompt_layout_t layout_cache_t::calc_prompt_layout(const wcstring &prompt_str,
|
||||
static size_t calc_prompt_lines(const wcstring &prompt) {
|
||||
// Hack for the common case where there's no newline at all. I don't know if a newline can
|
||||
// appear in an escape sequence, so if we detect a newline we have to defer to
|
||||
// calc_prompt_layout.
|
||||
// calc_prompt_width_and_lines.
|
||||
size_t result = 1;
|
||||
if (prompt.find_first_of(L"\n\f") != wcstring::npos) {
|
||||
result = layout_cache_t::shared.calc_prompt_layout(prompt).line_count;
|
||||
result = layout_cache_t::shared.calc_prompt_layout(prompt).line_breaks.size() + 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -737,19 +737,15 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
||||
// Output the left prompt if it has changed.
|
||||
if (left_prompt != scr->actual_left_prompt) {
|
||||
s_move(scr, 0, 0);
|
||||
wcstring::const_iterator line_start = left_prompt.begin();
|
||||
while (line_start < left_prompt.end()) {
|
||||
auto line_end = std::find_if(line_start, left_prompt.end(), is_run_terminator);
|
||||
s_write_str(scr, wcstring(line_start, line_end).c_str());
|
||||
if (line_end != left_prompt.end()) {
|
||||
// Embedded run terminator. Emit clr_eol before the line break.
|
||||
// TODO: we should be skipping line terminators inside escape sequences.
|
||||
if (clr_eol) s_write_mbs(scr, clr_eol);
|
||||
scr->outp().push_back(*line_end);
|
||||
++line_end;
|
||||
size_t start = 0;
|
||||
for (const size_t line_break : left_prompt_layout.line_breaks) {
|
||||
s_write_str(scr, left_prompt.substr(start, line_break - start).c_str());
|
||||
if (clr_eol) {
|
||||
s_write_mbs(scr, clr_eol);
|
||||
}
|
||||
line_start = line_end;
|
||||
start = line_break;
|
||||
}
|
||||
s_write_str(scr, left_prompt.c_str() + start);
|
||||
scr->actual_left_prompt = left_prompt;
|
||||
scr->actual.cursor.x = static_cast<int>(left_prompt_width);
|
||||
}
|
||||
|
@ -213,9 +213,9 @@ void screen_force_clear_to_end();
|
||||
|
||||
// Information about the layout of a prompt.
|
||||
struct prompt_layout_t {
|
||||
size_t line_count; // number of line breaks when rendering the prompt
|
||||
size_t max_line_width; // width of the longest line
|
||||
size_t last_line_width; // width of the last line
|
||||
std::vector<size_t> line_breaks; // line breaks when rendering the prompt
|
||||
size_t max_line_width; // width of the longest line
|
||||
size_t last_line_width; // width of the last line
|
||||
};
|
||||
|
||||
// Maintain a mapping of escape sequences to their widths for fast lookup.
|
||||
|
Loading…
x
Reference in New Issue
Block a user