Add support for explicit menu selection from the UI
the JsonUI now supports a "menu_select(int)" RPC call that should trigger explicit selection of the provided item index. As discussed for issue #2019.
This commit is contained in:
parent
c2637f08d9
commit
7325ad216c
|
@ -60,3 +60,4 @@ The requests that the json ui can interpret on stdin are:
|
||||||
* mouse(String type, int line, int column): mouse event, type
|
* mouse(String type, int line, int column): mouse event, type
|
||||||
can be: 'move', 'press', 'release', 'wheel_up', 'wheel_down',
|
can be: 'move', 'press', 'release', 'wheel_up', 'wheel_down',
|
||||||
line, column is the cursor position.
|
line, column is the cursor position.
|
||||||
|
* menu_select(int index): explicit select of given menu entry
|
||||||
|
|
|
@ -837,9 +837,8 @@ public:
|
||||||
m_refresh_completion_pending = true;
|
m_refresh_completion_pending = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key == Key::Tab or key == shift(Key::Tab)) // tab completion
|
else if (key == Key::Tab or key == shift(Key::Tab) or key.modifiers == Key::Modifiers::MenuSelect) // completion
|
||||||
{
|
{
|
||||||
const bool reverse = (key == shift(Key::Tab));
|
|
||||||
CandidateList& candidates = m_completions.candidates;
|
CandidateList& candidates = m_completions.candidates;
|
||||||
// first try, we need to ask our completer for completions
|
// first try, we need to ask our completer for completions
|
||||||
if (candidates.empty())
|
if (candidates.empty())
|
||||||
|
@ -853,7 +852,10 @@ public:
|
||||||
if (candidates.empty())
|
if (candidates.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (not reverse and ++m_current_completion >= candidates.size())
|
const bool reverse = (key == shift(Key::Tab));
|
||||||
|
if (key.modifiers == Key::Modifiers::MenuSelect)
|
||||||
|
m_current_completion = clamp<int>(key.key, 0, candidates.size() - 1);
|
||||||
|
else if (not reverse and ++m_current_completion >= candidates.size())
|
||||||
m_current_completion = 0;
|
m_current_completion = 0;
|
||||||
else if (reverse and --m_current_completion < 0)
|
else if (reverse and --m_current_completion < 0)
|
||||||
m_current_completion = candidates.size()-1;
|
m_current_completion = candidates.size()-1;
|
||||||
|
@ -1222,13 +1224,19 @@ public:
|
||||||
else if (key == ctrl('n'))
|
else if (key == ctrl('n'))
|
||||||
{
|
{
|
||||||
last_insert().keys.pop_back();
|
last_insert().keys.pop_back();
|
||||||
m_completer.select(1, last_insert().keys);
|
m_completer.select(1, true, last_insert().keys);
|
||||||
update_completions = false;
|
update_completions = false;
|
||||||
}
|
}
|
||||||
else if (key == ctrl('p'))
|
else if (key == ctrl('p'))
|
||||||
{
|
{
|
||||||
last_insert().keys.pop_back();
|
last_insert().keys.pop_back();
|
||||||
m_completer.select(-1, last_insert().keys);
|
m_completer.select(-1, true, last_insert().keys);
|
||||||
|
update_completions = false;
|
||||||
|
}
|
||||||
|
else if (key.modifiers == Key::Modifiers::MenuSelect)
|
||||||
|
{
|
||||||
|
last_insert().keys.pop_back();
|
||||||
|
m_completer.select(key.key, false, last_insert().keys);
|
||||||
update_completions = false;
|
update_completions = false;
|
||||||
}
|
}
|
||||||
else if (key == ctrl('x'))
|
else if (key == ctrl('x'))
|
||||||
|
|
|
@ -407,13 +407,13 @@ InsertCompleter::~InsertCompleter()
|
||||||
m_options.unregister_watcher(*this);
|
m_options.unregister_watcher(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertCompleter::select(int offset, Vector<Key>& keystrokes)
|
void InsertCompleter::select(int index, bool relative, Vector<Key>& keystrokes)
|
||||||
{
|
{
|
||||||
if (not setup_ifn())
|
if (not setup_ifn())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& buffer = m_context.buffer();
|
auto& buffer = m_context.buffer();
|
||||||
m_current_candidate = (m_current_candidate + offset) % (int)m_completions.candidates.size();
|
m_current_candidate = (relative ? m_current_candidate + index : index) % (int)m_completions.candidates.size();
|
||||||
if (m_current_candidate < 0)
|
if (m_current_candidate < 0)
|
||||||
m_current_candidate += m_completions.candidates.size();
|
m_current_candidate += m_completions.candidates.size();
|
||||||
const InsertCompletion::Candidate& candidate = m_completions.candidates[m_current_candidate];
|
const InsertCompletion::Candidate& candidate = m_completions.candidates[m_current_candidate];
|
||||||
|
|
|
@ -82,7 +82,7 @@ public:
|
||||||
InsertCompleter& operator=(const InsertCompleter&) = delete;
|
InsertCompleter& operator=(const InsertCompleter&) = delete;
|
||||||
~InsertCompleter();
|
~InsertCompleter();
|
||||||
|
|
||||||
void select(int offset, Vector<Key>& keystrokes);
|
void select(int index, bool relative, Vector<Key>& keystrokes);
|
||||||
void update();
|
void update();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
|
|
@ -410,6 +410,12 @@ void JsonUI::eval_json(const Value& json)
|
||||||
else
|
else
|
||||||
throw runtime_error(format("invalid mouse event type: {}", type));
|
throw runtime_error(format("invalid mouse event type: {}", type));
|
||||||
}
|
}
|
||||||
|
else if (method == "menu_select")
|
||||||
|
{
|
||||||
|
if (params.size() != 1)
|
||||||
|
throw runtime_error("menu_select needs the item index");
|
||||||
|
m_on_key({Key::Modifiers::MenuSelect, (Codepoint)params[0].as<int>()});
|
||||||
|
}
|
||||||
else if (method == "resize")
|
else if (method == "resize")
|
||||||
{
|
{
|
||||||
if (params.size() != 2)
|
if (params.size() != 2)
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct Key
|
||||||
MouseWheelDown | MouseWheelUp,
|
MouseWheelDown | MouseWheelUp,
|
||||||
|
|
||||||
Resize = 1 << 8,
|
Resize = 1 << 8,
|
||||||
|
MenuSelect = 1 << 9,
|
||||||
};
|
};
|
||||||
enum NamedKey : Codepoint
|
enum NamedKey : Codepoint
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user