NCurses: use menu for tab completion

This commit is contained in:
Maxime Coste 2012-08-31 14:14:16 +02:00
parent 51e80558d9
commit 96a50e9b7d
2 changed files with 30 additions and 4 deletions

View File

@ -15,6 +15,7 @@ class Context;
enum class MenuCommand enum class MenuCommand
{ {
SelectFirst,
SelectPrev, SelectPrev,
SelectNext, SelectNext,
Close, Close,

View File

@ -245,12 +245,14 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet
--cursor_pos; --cursor_pos;
} }
menu_ctrl(MenuCommand::Close);
current_completion = -1; current_completion = -1;
break; break;
case CTRL('r'): case CTRL('r'):
{ {
c = getch(); c = getch();
String reg = RegisterManager::instance()[c].values(context)[0]; String reg = RegisterManager::instance()[c].values(context)[0];
menu_ctrl(MenuCommand::Close);
current_completion = -1; current_completion = -1;
result = result.substr(0, cursor_pos) + reg + result.substr(cursor_pos, String::npos); result = result.substr(0, cursor_pos) + reg + result.substr(cursor_pos, String::npos);
cursor_pos += reg.length(); cursor_pos += reg.length();
@ -266,9 +268,13 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet
if (completions.candidates.empty()) if (completions.candidates.empty())
break; break;
menu_ctrl(MenuCommand::Close);
show_menu(completions.candidates);
text_before_completion = result.substr(completions.start, text_before_completion = result.substr(completions.start,
completions.end - completions.start); completions.end - completions.start);
} }
else
menu_ctrl(MenuCommand::SelectNext);
++current_completion; ++current_completion;
String completion; String completion;
@ -281,6 +287,7 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet
{ {
current_completion = 0; current_completion = 0;
completion = completions.candidates[0]; completion = completions.candidates[0];
menu_ctrl(MenuCommand::SelectFirst);
} }
} }
else else
@ -292,6 +299,7 @@ String NCursesClient::prompt(const String& text, const Context& context, Complet
break; break;
} }
default: default:
menu_ctrl(MenuCommand::Close);
current_completion = -1; current_completion = -1;
result = result.substr(0, cursor_pos) + (char)c + result.substr(cursor_pos, String::npos); result = result.substr(0, cursor_pos) + (char)c + result.substr(cursor_pos, String::npos);
++cursor_pos; ++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)); move(max_y - 1, (int)(text.length() + cursor_pos));
refresh(); refresh();
} }
menu_ctrl(MenuCommand::Close);
return result; return result;
} }
@ -322,14 +331,25 @@ void NCursesClient::show_menu(const memoryview<String>& choices)
m_choices = std::vector<String>(choices.begin(), choices.end()); m_choices = std::vector<String>(choices.begin(), choices.end());
for (int i = 0; i < m_choices.size(); ++i) for (int i = 0; i < m_choices.size(); ++i)
m_counts.push_back(int_to_str(i+1)); m_counts.push_back(int_to_str(i+1));
CharCount longest = 0;
for (int i = 0; i < m_choices.size(); ++i) 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())); 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_items.push_back(NULL);
m_menu = new_menu(&m_items[0]); longest += m_counts.back().length() + 2;
int max_x,max_y; int max_x,max_y;
getmaxyx(stdscr, max_y, max_x); 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_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); post_menu(m_menu);
} }
@ -337,14 +357,19 @@ void NCursesClient::menu_ctrl(MenuCommand command)
{ {
switch(command) switch(command)
{ {
case MenuCommand::SelectFirst:
menu_driver(m_menu, REQ_FIRST_ITEM);
break;
case MenuCommand::SelectNext: case MenuCommand::SelectNext:
menu_driver(m_menu, REQ_DOWN_ITEM); menu_driver(m_menu, REQ_NEXT_ITEM);
break; break;
case MenuCommand::SelectPrev: case MenuCommand::SelectPrev:
menu_driver(m_menu, REQ_UP_ITEM); menu_driver(m_menu, REQ_PREV_ITEM);
break; break;
case MenuCommand::Close: case MenuCommand::Close:
{ {
if (not m_menu)
break;
unpost_menu(m_menu); unpost_menu(m_menu);
free_menu(m_menu); free_menu(m_menu);
for (auto item : m_items) for (auto item : m_items)