From 96a50e9b7dbb591e3dfccca26b2f0eaf0dbc65bc Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 31 Aug 2012 14:14:16 +0200 Subject: [PATCH] NCurses: use menu for tab completion --- src/client.hh | 1 + src/ncurses.cc | 33 +++++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/client.hh b/src/client.hh index 83c6651cb..ea2d6e0a7 100644 --- a/src/client.hh +++ b/src/client.hh @@ -15,6 +15,7 @@ class Context; enum class MenuCommand { + SelectFirst, SelectPrev, SelectNext, Close, diff --git a/src/ncurses.cc b/src/ncurses.cc index 6809c3dd2..a2e273cc9 100644 --- a/src/ncurses.cc +++ b/src/ncurses.cc @@ -245,12 +245,14 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet --cursor_pos; } + menu_ctrl(MenuCommand::Close); current_completion = -1; break; case CTRL('r'): { c = getch(); String reg = RegisterManager::instance()[c].values(context)[0]; + menu_ctrl(MenuCommand::Close); current_completion = -1; result = result.substr(0, cursor_pos) + reg + result.substr(cursor_pos, String::npos); cursor_pos += reg.length(); @@ -266,9 +268,13 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet if (completions.candidates.empty()) break; + menu_ctrl(MenuCommand::Close); + show_menu(completions.candidates); text_before_completion = result.substr(completions.start, completions.end - completions.start); } + else + menu_ctrl(MenuCommand::SelectNext); ++current_completion; String completion; @@ -281,6 +287,7 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet { current_completion = 0; completion = completions.candidates[0]; + menu_ctrl(MenuCommand::SelectFirst); } } else @@ -292,6 +299,7 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet break; } default: + menu_ctrl(MenuCommand::Close); current_completion = -1; result = result.substr(0, cursor_pos) + (char)c + result.substr(cursor_pos, String::npos); ++cursor_pos; @@ -303,6 +311,7 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet move(max_y - 1, (int)(text.length() + cursor_pos)); refresh(); } + menu_ctrl(MenuCommand::Close); return result; } @@ -322,14 +331,25 @@ void NCursesClient::show_menu(const memoryview& choices) m_choices = std::vector(choices.begin(), choices.end()); for (int i = 0; i < m_choices.size(); ++i) m_counts.push_back(int_to_str(i+1)); + CharCount longest = 0; for (int i = 0; i < m_choices.size(); ++i) + { m_items.push_back(new_item(m_counts[i].c_str(), m_choices[i].c_str())); + longest = std::max(longest, m_choices[i].length()); + } m_items.push_back(NULL); - m_menu = new_menu(&m_items[0]); + longest += m_counts.back().length() + 2; + int max_x,max_y; getmaxyx(stdscr, max_y, max_x); - int pos_y = max_y - std::min(10, (int)m_choices.size()) - 1; + + int columns = max_x / (int)longest; + int lines = std::min(10, (int)ceilf((float)m_choices.size()/columns)); + + m_menu = new_menu(&m_items[0]); + int pos_y = max_y - lines - 1; set_menu_sub(m_menu, derwin(stdscr, max_y - pos_y - 1, max_x, pos_y, 0)); + set_menu_format(m_menu, lines, columns); post_menu(m_menu); } @@ -337,14 +357,19 @@ void NCursesClient::menu_ctrl(MenuCommand command) { switch(command) { + case MenuCommand::SelectFirst: + menu_driver(m_menu, REQ_FIRST_ITEM); + break; case MenuCommand::SelectNext: - menu_driver(m_menu, REQ_DOWN_ITEM); + menu_driver(m_menu, REQ_NEXT_ITEM); break; case MenuCommand::SelectPrev: - menu_driver(m_menu, REQ_UP_ITEM); + menu_driver(m_menu, REQ_PREV_ITEM); break; case MenuCommand::Close: { + if (not m_menu) + break; unpost_menu(m_menu); free_menu(m_menu); for (auto item : m_items)