From 1bd5946d235a49dafa1b95b6006609a65a457231 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 4 Feb 2018 15:43:03 -0800 Subject: [PATCH] Add prompt layout caching to layout_cache_t --- src/fish_tests.cpp | 24 ++++++++++++++++++++++-- src/screen.cpp | 21 +++++++++++++++++++++ src/screen.h | 8 ++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index eacaed021..d11a33b47 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -4332,8 +4332,10 @@ void test_maybe() { do_test(m2.missing_or_empty()); } -void test_cached_esc_sequences() { +void test_layout_cache() { layout_cache_t seqs; + + // Verify escape code cache. do_test(seqs.find_escape_code(L"abc") == 0); seqs.add_escape_code(L"abc"); seqs.add_escape_code(L"abc"); @@ -4354,6 +4356,24 @@ void test_cached_esc_sequences() { seqs.clear(); do_test(seqs.esc_cache_size() == 0); do_test(seqs.find_escape_code(L"abcd") == 0); + + // Verify prompt 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, {i}); + do_test(seqs.find_prompt_layout(input)->line_count == 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))->line_count == i); + } + + seqs.add_prompt_layout(L"whatever", {100}); + do_test(!seqs.find_prompt_layout(std::to_wstring(expected_evictee))); + do_test(seqs.find_prompt_layout(L"whatever")->line_count == 100); } /// Main test. @@ -4452,7 +4472,7 @@ int main(int argc, char **argv) { if (should_test_function("string")) test_string(); if (should_test_function("illegal_command_exit_code")) test_illegal_command_exit_code(); if (should_test_function("maybe")) test_maybe(); - if (should_test_function("cached_esc_sequences")) test_cached_esc_sequences(); + if (should_test_function("layout_cache")) test_layout_cache(); // history_tests_t::test_history_speed(); say(L"Encountered %d errors in low-level tests", err_count); diff --git a/src/screen.cpp b/src/screen.cpp index a0ef2c51a..a63c48278 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -283,6 +283,27 @@ size_t escape_code_length(const wchar_t *code) { return esc_seq_len; } +maybe_t layout_cache_t::find_prompt_layout(const wcstring &input) { + auto start = prompt_cache_.begin(); + auto end = prompt_cache_.end(); + for (auto iter = start; iter != end; ++iter) { + if (iter->first == input) { + // Found it. Move it to the front if not already there. + if (iter != start) prompt_cache_.splice(start, prompt_cache_, iter); + return iter->second; + } + } + return none(); +} + +void layout_cache_t::add_prompt_layout(wcstring input, prompt_layout_t layout) { + assert(!find_prompt_layout(input) && "Should not have a prompt layout for this input"); + prompt_cache_.emplace_front(std::move(input), std::move(layout)); + if (prompt_cache_.size() > prompt_cache_max_size) { + prompt_cache_.pop_back(); + } +} + // These are used by `calc_prompt_layout()` to avoid redundant calculations. static const wchar_t *cached_left_prompt = wcsdup(L""); static const wchar_t *cached_right_prompt = wcsdup(L""); diff --git a/src/screen.h b/src/screen.h index cb3d0bd81..146f60a78 100644 --- a/src/screen.h +++ b/src/screen.h @@ -220,6 +220,8 @@ class layout_cache_t { std::list prompt_cache_; public: + static constexpr size_t prompt_cache_max_size = 8; + /// \return the size of the escape code cache. size_t esc_cache_size() const { return esc_cache_.size(); } @@ -246,6 +248,12 @@ class layout_cache_t { return 0; } + // Finds the layout for a prompt, promoting it to the front. Returns none() if not found. + maybe_t find_prompt_layout(const wcstring &input); + + // Adds a prompt layout for a given string. + void add_prompt_layout(wcstring input, prompt_layout_t layout); + void clear() { esc_cache_.clear(); prompt_cache_.clear();