Store HistoryRegisters with most recent entry in front

Closes #3105
This commit is contained in:
Maxime Coste 2022-06-05 09:19:05 +10:00
parent 2d8456db10
commit b5e565bd6a
3 changed files with 24 additions and 46 deletions

View File

@ -752,7 +752,7 @@ public:
m_empty_text{std::move(emptystr)}, m_empty_text{std::move(emptystr)},
m_line_editor{context().faces()}, m_flags(flags), m_line_editor{context().faces()}, m_flags(flags),
m_history{RegisterManager::instance()[history_register]}, m_history{RegisterManager::instance()[history_register]},
m_current_history{m_history.get(context()).size()}, m_current_history{-1},
m_auto_complete{context().options()["autocomplete"].get<AutoComplete>() & AutoComplete::Prompt}, m_auto_complete{context().options()["autocomplete"].get<AutoComplete>() & AutoComplete::Prompt},
m_idle_timer{TimePoint::max(), context().flags() & Context::Flags::Draft ? m_idle_timer{TimePoint::max(), context().flags() & Context::Flags::Draft ?
Timer::Callback{} : [this](Timer&) { Timer::Callback{} : [this](Timer&) {
@ -861,48 +861,28 @@ public:
} }
else if (key == Key::Up or key == ctrl('p')) else if (key == Key::Up or key == ctrl('p'))
{ {
if (m_current_history != 0) auto history = m_history.get(context());
m_current_history = std::min(static_cast<int>(history.size()) - 1, m_current_history);
if (m_current_history == -1)
m_prefix = line;
auto next = find_if(history.subrange(m_current_history + 1), [this](StringView s) { return prefix_match(s, m_prefix); });
if (next != history.end())
{ {
auto history = m_history.get(context()); m_current_history = next - history.begin();
// The history register might have been mutated in the mean time m_line_editor.reset(*next, m_empty_text);
m_current_history = std::min(history.size(), m_current_history);
if (m_current_history == history.size())
m_prefix = line;
auto index = m_current_history;
// search for the previous history entry matching typed prefix
do
{
--index;
if (prefix_match(history[index], m_prefix))
{
m_current_history = index;
m_line_editor.reset(history[index], m_empty_text);
break;
}
} while (index != 0);
clear_completions();
m_refresh_completion_pending = true;
} }
clear_completions();
m_refresh_completion_pending = true;
} }
else if (key == Key::Down or key == ctrl('n')) // next else if (key == Key::Down or key == ctrl('n')) // next
{ {
auto history = m_history.get(context()); auto history = m_history.get(context());
// The history register might have been mutated in the mean time m_current_history = std::min(static_cast<int>(history.size()) - 1, m_current_history);
m_current_history = std::min(history.size(), m_current_history); if (m_current_history >= 0)
if (m_current_history < history.size())
{ {
// search for the next history entry matching typed prefix auto next = find_if(history.subrange(0, m_current_history) | reverse(), [this](StringView s) { return prefix_match(s, m_prefix); });
++m_current_history; m_current_history = history.rend() - next - 1;
while (m_current_history != history.size() and m_line_editor.reset(next != history.rend() ? *next : m_prefix, m_empty_text);
not prefix_match(history[m_current_history], m_prefix))
++m_current_history;
if (m_current_history != history.size())
m_line_editor.reset(history[m_current_history], m_empty_text);
else
m_line_editor.reset(m_prefix, m_empty_text);
clear_completions(); clear_completions();
m_refresh_completion_pending = true; m_refresh_completion_pending = true;
} }
@ -1162,7 +1142,7 @@ private:
bool m_line_changed = false; bool m_line_changed = false;
PromptFlags m_flags; PromptFlags m_flags;
Register& m_history; Register& m_history;
size_t m_current_history; int m_current_history;
bool m_auto_complete; bool m_auto_complete;
bool m_refresh_completion_pending = true; bool m_refresh_completion_pending = true;
Timer m_idle_timer; Timer m_idle_timer;

View File

@ -941,7 +941,7 @@ template<SelectMode mode, RegexMode regex_mode>
void search_next(Context& context, NormalParams params) void search_next(Context& context, NormalParams params)
{ {
const char reg = to_lower(params.reg ? params.reg : '/'); const char reg = to_lower(params.reg ? params.reg : '/');
StringView str = RegisterManager::instance()[reg].get(context).back(); StringView str = RegisterManager::instance()[reg].get(context).front();
if (not str.empty()) if (not str.empty())
{ {
Regex regex{str, direction_flags(regex_mode)}; Regex regex{str, direction_flags(regex_mode)};

View File

@ -40,16 +40,14 @@ void HistoryRegister::set(Context& context, ConstArrayView<String> values, bool
return; return;
} }
for (auto& entry : values) for (auto&& entry : values | reverse())
{ {
m_content.erase(std::remove(m_content.begin(), m_content.end(), entry), m_content.erase(std::remove(m_content.begin(), m_content.end(), entry), m_content.end());
m_content.end()); m_content.insert(m_content.begin(), entry);
m_content.push_back(entry);
} }
const size_t current_size = m_content.size(); if (m_content.size() > size_limit)
if (current_size > size_limit) m_content.erase(m_content.end() - (m_content.size() - size_limit), m_content.end());
m_content.erase(m_content.begin(), m_content.begin() + (current_size - size_limit));
if (not m_disable_modified_hook) if (not m_disable_modified_hook)
context.hooks().run_hook(Hook::RegisterModified, m_name, context); context.hooks().run_hook(Hook::RegisterModified, m_name, context);
@ -57,7 +55,7 @@ void HistoryRegister::set(Context& context, ConstArrayView<String> values, bool
const String& HistoryRegister::get_main(const Context&, size_t) const String& HistoryRegister::get_main(const Context&, size_t)
{ {
return m_content.empty() ? String::ms_empty : m_content.back(); return m_content.empty() ? String::ms_empty : m_content.front();
} }
static const HashMap<String, Codepoint> reg_names = { static const HashMap<String, Codepoint> reg_names = {