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:
Maxime Coste 2018-05-03 22:22:12 +10:00
parent c2637f08d9
commit 7325ad216c
6 changed files with 24 additions and 8 deletions

View File

@ -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

View File

@ -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'))

View File

@ -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];

View File

@ -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();

View File

@ -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)

View File

@ -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
{ {