From 1ca502d23de987de52eaf4ea698b6bd006a3e5bc Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 30 Aug 2012 21:14:28 +0200 Subject: [PATCH] More useable menu implementation on ncurses --- src/Makefile | 2 +- src/client.hh | 1 + src/commands.cc | 13 +++++-------- src/ncurses.cc | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/ncurses.hh | 2 ++ 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/Makefile b/src/Makefile index 49f09481..bdec018c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,7 +3,7 @@ objects := $(sources:.cc=.o) deps := $(addprefix ., $(sources:.cc=.d)) CXXFLAGS += -std=c++0x -g -LDFLAGS += -lncurses -lboost_regex +LDFLAGS += -lmenu -lncurses -lboost_regex kak : $(objects) $(CXX) $(LDFLAGS) $(CXXFLAGS) $(objects) -o $@ diff --git a/src/client.hh b/src/client.hh index 84adab4f..8b2d3444 100644 --- a/src/client.hh +++ b/src/client.hh @@ -23,6 +23,7 @@ public: virtual String prompt(const String& prompt, const Context& context, Completer completer = complete_nothing) = 0; virtual Key get_key() = 0; + virtual int menu(const memoryview& choices) = 0; }; struct prompt_aborted {}; diff --git a/src/commands.cc b/src/commands.cc index 2dbd8b45..4e09568a 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -699,6 +699,8 @@ public: bool has_key_left() const { return m_pos < m_keys.size(); } + int menu(const memoryview& choices) { return 0; } + private: const KeyList& m_keys; size_t m_pos; @@ -761,16 +763,11 @@ void menu(const CommandParameters& params, Context& context) return; } - std::ostringstream oss; + std::vector choices; for (int i = 0; i < count; i += 2) - { - oss << i/2 + 1 << "[" << parser[i] << "] "; - } - oss << "(empty cancels): "; + choices.push_back(parser[i]); - String choice = context.client().prompt(oss.str(), context, - complete_nothing); - int i = str_to_int(choice); + int i = context.client().menu(choices); if (i > 0 and i < (count / 2) + 1) CommandManager::instance().execute(parser[(i-1)*2+1], context); diff --git a/src/ncurses.cc b/src/ncurses.cc index 954246c3..cde33183 100644 --- a/src/ncurses.cc +++ b/src/ncurses.cc @@ -4,6 +4,7 @@ #include "register_manager.hh" #include +#include #include #define CTRL(x) x - 'a' + 1 @@ -316,4 +317,50 @@ void NCursesClient::print_status(const String& status) refresh(); } +int NCursesClient::menu(const memoryview& choices) +{ + std::vector items; + std::vector counts; + for (int i = 0; i < choices.size(); ++i) + counts.push_back(int_to_str(i+1)); + for (int i = 0; i < choices.size(); ++i) + items.push_back(new_item(counts[i].c_str(), choices[i].c_str())); + items.push_back(NULL); + MENU* menu = new_menu(&items[0]); + int max_x,max_y; + getmaxyx(stdscr, max_y, max_x); + int pos_y = max_y - std::min(10, (int)choices.size()) - 1; + set_menu_sub(menu, derwin(stdscr, max_y - pos_y - 1, max_x, pos_y, 0)); + post_menu(menu); + + int res = -1; + while (true) + { + int c = getch(); + if ('0' <= c and c <= '9') + { + res = c - '0'; + break; + } + if (c == KEY_DOWN or c == CTRL('n')) + menu_driver(menu, REQ_DOWN_ITEM); + if (c == KEY_UP or c == CTRL('p')) + menu_driver(menu, REQ_UP_ITEM); + if (c == 27) + break; + if (c == '\r') + { + res = item_index(current_item(menu)) + 1; + break; + } + } + + unpost_menu(menu); + for (auto item : items) + if (item) + free_item(item); + free_menu(menu); + return res; +} + } diff --git a/src/ncurses.hh b/src/ncurses.hh index 1a959ed0..36a2de81 100644 --- a/src/ncurses.hh +++ b/src/ncurses.hh @@ -20,6 +20,8 @@ public: String prompt(const String& prompt, const Context& context, Completer completer); Key get_key(); + + int menu(const memoryview& choices); }; }