Fix completion pager not rendering after <a-semicolon> in prompt
Usually, the prompt resets "m_line_changed" after invoking the change handler: if (m_line_changed) { m_callback(m_line_editor.line(), PromptEvent::Change, context()); m_line_changed = false; } but with prompt '' '' -on-change %{ execute-keys <a-semicolon>vl } -shell-script-candidates %{ seq 100 } the change handler pushes a normal mode with "<a-semicolon>" and then hands back control to the event loop. Later when the normal mode is popped we run "Prompt::on_enabled()" but don't actually redraw the completion pager. Since the <a-semicolon> excursion by definition did not change our prompt state, we don't need to recompute completions, only render them. Do that. This helps commands that use preview the selected completion via a "prompt -on-change" handler.
This commit is contained in:
parent
70e96c272e
commit
cac2a32ba2
|
@ -34,8 +34,8 @@ public:
|
||||||
void handle_key(Key key, bool synthesized) { RefPtr<InputMode> keep_alive{this}; on_key(key, synthesized); }
|
void handle_key(Key key, bool synthesized) { RefPtr<InputMode> keep_alive{this}; on_key(key, synthesized); }
|
||||||
virtual void paste(StringView content);
|
virtual void paste(StringView content);
|
||||||
|
|
||||||
virtual void on_enabled() {}
|
virtual void on_enabled(bool from_pop) {}
|
||||||
virtual void on_disabled(bool temporary) {}
|
virtual void on_disabled(bool from_push) {}
|
||||||
|
|
||||||
bool enabled() const { return &m_input_handler.current_mode() == this; }
|
bool enabled() const { return &m_input_handler.current_mode() == this; }
|
||||||
Context& context() const { return m_input_handler.context(); }
|
Context& context() const { return m_input_handler.context(); }
|
||||||
|
@ -227,7 +227,7 @@ public:
|
||||||
m_state(single_command ? State::SingleCommand : State::Normal)
|
m_state(single_command ? State::SingleCommand : State::Normal)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void on_enabled() override
|
void on_enabled(bool from_pop) override
|
||||||
{
|
{
|
||||||
if (m_state == State::PopOnEnabled)
|
if (m_state == State::PopOnEnabled)
|
||||||
return pop_mode();
|
return pop_mode();
|
||||||
|
@ -248,12 +248,12 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_disabled(bool temporary) override
|
void on_disabled(bool from_push) override
|
||||||
{
|
{
|
||||||
m_idle_timer.disable();
|
m_idle_timer.disable();
|
||||||
m_fs_check_timer.disable();
|
m_fs_check_timer.disable();
|
||||||
|
|
||||||
if (not temporary and m_hooks_disabled)
|
if (not from_push and m_hooks_disabled)
|
||||||
{
|
{
|
||||||
context().hooks_disabled().unset();
|
context().hooks_disabled().unset();
|
||||||
m_hooks_disabled = false;
|
m_hooks_disabled = false;
|
||||||
|
@ -1117,21 +1117,10 @@ private:
|
||||||
line.byte_count_to(m_line_editor.cursor_pos()));
|
line.byte_count_to(m_line_editor.cursor_pos()));
|
||||||
if (not context().has_client())
|
if (not context().has_client())
|
||||||
return;
|
return;
|
||||||
|
show_completions();
|
||||||
if (m_completions.candidates.empty())
|
|
||||||
return context().client().menu_hide();
|
|
||||||
|
|
||||||
Vector<DisplayLine> items;
|
|
||||||
for (auto& candidate : m_completions.candidates)
|
|
||||||
items.push_back({ candidate, {} });
|
|
||||||
|
|
||||||
const auto menu_style = (m_flags & PromptFlags::Search) ? MenuStyle::Search : MenuStyle::Prompt;
|
|
||||||
context().client().menu_show(std::move(items), {}, menu_style);
|
|
||||||
|
|
||||||
const bool menu = (bool)(m_completions.flags & Completions::Flags::Menu);
|
const bool menu = (bool)(m_completions.flags & Completions::Flags::Menu);
|
||||||
if (menu)
|
if (menu)
|
||||||
context().client().menu_select(0);
|
context().client().menu_select(0);
|
||||||
|
|
||||||
auto prefix = line.substr(m_completions.start, m_completions.end - m_completions.start);
|
auto prefix = line.substr(m_completions.start, m_completions.end - m_completions.start);
|
||||||
if (not menu and not contains(m_completions.candidates, prefix))
|
if (not menu and not contains(m_completions.candidates, prefix))
|
||||||
{
|
{
|
||||||
|
@ -1144,6 +1133,19 @@ private:
|
||||||
} catch (runtime_error&) {}
|
} catch (runtime_error&) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void show_completions()
|
||||||
|
{
|
||||||
|
if (m_completions.candidates.empty())
|
||||||
|
return context().client().menu_hide();
|
||||||
|
|
||||||
|
Vector<DisplayLine> items;
|
||||||
|
for (auto& candidate : m_completions.candidates)
|
||||||
|
items.push_back({ candidate, {} });
|
||||||
|
|
||||||
|
const auto menu_style = (m_flags & PromptFlags::Search) ? MenuStyle::Search : MenuStyle::Prompt;
|
||||||
|
context().client().menu_show(std::move(items), {}, menu_style);
|
||||||
|
}
|
||||||
|
|
||||||
void clear_completions()
|
void clear_completions()
|
||||||
{
|
{
|
||||||
m_current_completion = -1;
|
m_current_completion = -1;
|
||||||
|
@ -1163,18 +1165,31 @@ private:
|
||||||
context().print_status(display_line);
|
context().print_status(display_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_enabled() override
|
void on_enabled(bool from_pop) override
|
||||||
{
|
{
|
||||||
display();
|
display();
|
||||||
m_line_changed = true;
|
if (from_pop)
|
||||||
|
{
|
||||||
|
if (context().has_client())
|
||||||
|
{
|
||||||
|
show_completions();
|
||||||
|
const bool menu = (bool)(m_completions.flags & Completions::Flags::Menu);
|
||||||
|
if (m_current_completion != -1)
|
||||||
|
context().client().menu_select(m_current_completion);
|
||||||
|
else if (menu)
|
||||||
|
context().client().menu_select(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_line_changed = true;
|
||||||
|
|
||||||
if (not (context().flags() & Context::Flags::Draft))
|
if (not (context().flags() & Context::Flags::Draft))
|
||||||
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
|
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_disabled(bool temporary) override
|
void on_disabled(bool from_push) override
|
||||||
{
|
{
|
||||||
if (not temporary)
|
if (not from_push)
|
||||||
context().print_status({});
|
context().print_status({});
|
||||||
|
|
||||||
m_idle_timer.disable();
|
m_idle_timer.disable();
|
||||||
|
@ -1274,17 +1289,17 @@ public:
|
||||||
prepare(mode, count);
|
prepare(mode, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_enabled() override
|
void on_enabled(bool from_pop) override
|
||||||
{
|
{
|
||||||
if (not (context().flags() & Context::Flags::Draft))
|
if (not (context().flags() & Context::Flags::Draft))
|
||||||
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
|
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_disabled(bool temporary) override
|
void on_disabled(bool from_push) override
|
||||||
{
|
{
|
||||||
m_idle_timer.disable();
|
m_idle_timer.disable();
|
||||||
|
|
||||||
if (not temporary)
|
if (not from_push)
|
||||||
{
|
{
|
||||||
last_insert().recording.unset();
|
last_insert().recording.unset();
|
||||||
|
|
||||||
|
@ -1625,7 +1640,7 @@ InputHandler::InputHandler(SelectionList selections, Context::Flags flags, Strin
|
||||||
: m_context(*this, std::move(selections), flags, std::move(name))
|
: m_context(*this, std::move(selections), flags, std::move(name))
|
||||||
{
|
{
|
||||||
m_mode_stack.emplace_back(new InputModes::Normal(*this));
|
m_mode_stack.emplace_back(new InputModes::Normal(*this));
|
||||||
current_mode().on_enabled();
|
current_mode().on_enabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
InputHandler::~InputHandler() = default;
|
InputHandler::~InputHandler() = default;
|
||||||
|
@ -1636,7 +1651,7 @@ void InputHandler::push_mode(InputMode* new_mode)
|
||||||
|
|
||||||
current_mode().on_disabled(true);
|
current_mode().on_disabled(true);
|
||||||
m_mode_stack.emplace_back(new_mode);
|
m_mode_stack.emplace_back(new_mode);
|
||||||
new_mode->on_enabled();
|
new_mode->on_enabled(false);
|
||||||
|
|
||||||
context().hooks().run_hook(Hook::ModeChange, format("push:{}:{}", prev_name, new_mode->name()), context());
|
context().hooks().run_hook(Hook::ModeChange, format("push:{}:{}", prev_name, new_mode->name()), context());
|
||||||
}
|
}
|
||||||
|
@ -1651,7 +1666,7 @@ void InputHandler::pop_mode(InputMode* mode)
|
||||||
|
|
||||||
current_mode().on_disabled(false);
|
current_mode().on_disabled(false);
|
||||||
m_mode_stack.pop_back();
|
m_mode_stack.pop_back();
|
||||||
current_mode().on_enabled();
|
current_mode().on_enabled(true);
|
||||||
|
|
||||||
context().hooks().run_hook(Hook::ModeChange, format("pop:{}:{}", prev_name, current_mode().name()), context());
|
context().hooks().run_hook(Hook::ModeChange, format("pop:{}:{}", prev_name, current_mode().name()), context());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user