From 7325ad216cbecb0d14fdee40cef7cca3e39f8513 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 3 May 2018 22:22:12 +1000 Subject: [PATCH] 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. --- doc/json_ui.asciidoc | 1 + src/input_handler.cc | 18 +++++++++++++----- src/insert_completer.cc | 4 ++-- src/insert_completer.hh | 2 +- src/json_ui.cc | 6 ++++++ src/keys.hh | 1 + 6 files changed, 24 insertions(+), 8 deletions(-) diff --git a/doc/json_ui.asciidoc b/doc/json_ui.asciidoc index 61407a62..7a93a41d 100644 --- a/doc/json_ui.asciidoc +++ b/doc/json_ui.asciidoc @@ -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 can be: 'move', 'press', 'release', 'wheel_up', 'wheel_down', line, column is the cursor position. +* menu_select(int index): explicit select of given menu entry diff --git a/src/input_handler.cc b/src/input_handler.cc index 9e4a8b50..ff6e126f 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -837,9 +837,8 @@ public: 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; // first try, we need to ask our completer for completions if (candidates.empty()) @@ -853,7 +852,10 @@ public: if (candidates.empty()) 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(key.key, 0, candidates.size() - 1); + else if (not reverse and ++m_current_completion >= candidates.size()) m_current_completion = 0; else if (reverse and --m_current_completion < 0) m_current_completion = candidates.size()-1; @@ -1222,13 +1224,19 @@ public: else if (key == ctrl('n')) { 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 == ctrl('p')) { 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; } else if (key == ctrl('x')) diff --git a/src/insert_completer.cc b/src/insert_completer.cc index 19fcaa87..42e9642e 100644 --- a/src/insert_completer.cc +++ b/src/insert_completer.cc @@ -407,13 +407,13 @@ InsertCompleter::~InsertCompleter() m_options.unregister_watcher(*this); } -void InsertCompleter::select(int offset, Vector& keystrokes) +void InsertCompleter::select(int index, bool relative, Vector& keystrokes) { if (not setup_ifn()) return; 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) m_current_candidate += m_completions.candidates.size(); const InsertCompletion::Candidate& candidate = m_completions.candidates[m_current_candidate]; diff --git a/src/insert_completer.hh b/src/insert_completer.hh index 15244bf1..7e79bd09 100644 --- a/src/insert_completer.hh +++ b/src/insert_completer.hh @@ -82,7 +82,7 @@ public: InsertCompleter& operator=(const InsertCompleter&) = delete; ~InsertCompleter(); - void select(int offset, Vector& keystrokes); + void select(int index, bool relative, Vector& keystrokes); void update(); void reset(); diff --git a/src/json_ui.cc b/src/json_ui.cc index 8629395d..67970a35 100644 --- a/src/json_ui.cc +++ b/src/json_ui.cc @@ -410,6 +410,12 @@ void JsonUI::eval_json(const Value& json) else 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()}); + } else if (method == "resize") { if (params.size() != 2) diff --git a/src/keys.hh b/src/keys.hh index 9b632dcb..fa9549b8 100644 --- a/src/keys.hh +++ b/src/keys.hh @@ -30,6 +30,7 @@ struct Key MouseWheelDown | MouseWheelUp, Resize = 1 << 8, + MenuSelect = 1 << 9, }; enum NamedKey : Codepoint {