extract Client virtual methods to a UserInterface class

This commit is contained in:
Maxime Coste 2012-09-24 19:24:27 +02:00
parent 0380c999c3
commit a312ce6dc2
8 changed files with 86 additions and 45 deletions

View File

@ -62,12 +62,12 @@ public:
: Client::Mode(client), : Client::Mode(client),
m_callback(callback), m_choice_count(choices.size()), m_selected(0) m_callback(callback), m_choice_count(choices.size()), m_selected(0)
{ {
client.menu_show(choices); client.m_ui->menu_show(choices);
} }
~MenuMode() ~MenuMode()
{ {
m_client.menu_hide(); m_client.m_ui->menu_hide();
} }
void on_key(const Key& key, Context& context) override void on_key(const Key& key, Context& context) override
@ -79,7 +79,7 @@ public:
{ {
if (++m_selected >= m_choice_count) if (++m_selected >= m_choice_count)
m_selected = 0; m_selected = 0;
m_client.menu_select(m_selected); m_client.m_ui->menu_select(m_selected);
} }
if (key == Key::Up or if (key == Key::Up or
key == Key::BackTab or key == Key::BackTab or
@ -88,7 +88,7 @@ public:
{ {
if (--m_selected < 0) if (--m_selected < 0)
m_selected = m_choice_count-1; m_selected = m_choice_count-1;
m_client.menu_select(m_selected); m_client.m_ui->menu_select(m_selected);
} }
if (key == Key(Key::Modifiers::Control, 'm')) if (key == Key(Key::Modifiers::Control, 'm'))
{ {
@ -105,7 +105,7 @@ public:
if (key.modifiers == Key::Modifiers::None and if (key.modifiers == Key::Modifiers::None and
key.key >= '0' and key.key <= '9') key.key >= '0' and key.key <= '9')
{ {
m_client.menu_hide(); m_client.m_ui->menu_hide();
// save callback as reset_normal_mode will delete this // save callback as reset_normal_mode will delete this
MenuCallback callback = std::move(m_callback); MenuCallback callback = std::move(m_callback);
m_client.reset_normal_mode(); m_client.reset_normal_mode();
@ -133,7 +133,7 @@ public:
~PromptMode() ~PromptMode()
{ {
m_client.menu_hide(); m_client.m_ui->menu_hide();
} }
void on_key(const Key& key, Context& context) override void on_key(const Key& key, Context& context) override
@ -226,14 +226,14 @@ public:
--m_cursor_pos; --m_cursor_pos;
} }
m_client.menu_hide(); m_client.m_ui->menu_hide();
m_current_completion = -1; m_current_completion = -1;
} }
else if (key == Key(Key::Modifiers::Control, 'r')) else if (key == Key(Key::Modifiers::Control, 'r'))
{ {
Key k = m_client.get_key(); Key k = m_client.m_ui->get_key();
String reg = RegisterManager::instance()[k.key].values(context)[0]; String reg = RegisterManager::instance()[k.key].values(context)[0];
m_client.menu_hide(); m_client.m_ui->menu_hide();
m_current_completion = -1; m_current_completion = -1;
m_result = m_result.substr(0, m_cursor_pos) + reg m_result = m_result.substr(0, m_cursor_pos) + reg
+ m_result.substr(m_cursor_pos, String::npos); + m_result.substr(m_cursor_pos, String::npos);
@ -251,8 +251,8 @@ public:
if (candidates.empty()) if (candidates.empty())
return; return;
m_client.menu_hide(); m_client.m_ui->menu_hide();
m_client.menu_show(candidates); m_client.m_ui->menu_show(candidates);
String prefix = m_result.substr(m_completions.start, String prefix = m_result.substr(m_completions.start,
m_completions.end - m_completions.start); m_completions.end - m_completions.start);
if (not contains(candidates, prefix)) if (not contains(candidates, prefix))
@ -265,14 +265,14 @@ public:
m_current_completion = candidates.size()-1; m_current_completion = candidates.size()-1;
const String& completion = candidates[m_current_completion]; const String& completion = candidates[m_current_completion];
m_client.menu_select(m_current_completion); m_client.m_ui->menu_select(m_current_completion);
m_result = m_result.substr(0, m_completions.start) + completion m_result = m_result.substr(0, m_completions.start) + completion
+ m_result.substr(m_cursor_pos); + m_result.substr(m_cursor_pos);
m_cursor_pos = m_completions.start + completion.length(); m_cursor_pos = m_completions.start + completion.length();
} }
else else
{ {
m_client.menu_hide(); m_client.m_ui->menu_hide();
m_current_completion = -1; m_current_completion = -1;
m_result = m_result.substr(0, m_cursor_pos) + key.key + m_result.substr(m_cursor_pos, String::npos); m_result = m_result.substr(0, m_cursor_pos) + key.key + m_result.substr(m_cursor_pos, String::npos);
++m_cursor_pos; ++m_cursor_pos;
@ -381,8 +381,9 @@ private:
IncrementalInserter m_inserter; IncrementalInserter m_inserter;
}; };
Client::Client() Client::Client(UserInterface* ui)
: m_mode(new NormalMode(*this)), : m_mode(new NormalMode(*this)),
m_ui(ui),
m_last_insert(IncrementalInserter::Mode::Insert, {}) m_last_insert(IncrementalInserter::Mode::Insert, {})
{ {
} }
@ -430,10 +431,21 @@ void Client::on_next_key(KeyCallback callback)
void Client::handle_next_input(Context& context) void Client::handle_next_input(Context& context)
{ {
m_mode->on_key(get_key(), context); m_mode->on_key(m_ui->get_key(), context);
context.draw_ifn(); context.draw_ifn();
} }
void Client::print_status(const String& status, CharCount cursor_pos)
{
m_ui->print_status(status, cursor_pos);
}
void Client::draw_window(Window& window)
{
m_ui->draw_window(window);
}
void Client::reset_normal_mode() void Client::reset_normal_mode()
{ {
m_mode.reset(new NormalMode(*this)); m_mode.reset(new NormalMode(*this));

View File

@ -5,7 +5,8 @@
#include "completion.hh" #include "completion.hh"
#include "utils.hh" #include "utils.hh"
#include "string.hh" #include "string.hh"
#include "editor.hh" #include "window.hh"
#include "user_interface.hh"
namespace Kakoune namespace Kakoune
{ {
@ -21,11 +22,8 @@ using KeyCallback = std::function<void (const Key&, Context&)>;
class Client : public SafeCountable class Client : public SafeCountable
{ {
public: public:
Client(); Client(UserInterface* ui);
virtual ~Client(); ~Client();
virtual void draw_window(Window& window) = 0;
virtual void print_status(const String& status,
CharCount cursor_pos = -1) = 0;
void insert(Editor& editor, IncrementalInserter::Mode mode); void insert(Editor& editor, IncrementalInserter::Mode mode);
void repeat_last_insert(Editor& editor, Context& context); void repeat_last_insert(Editor& editor, Context& context);
@ -36,19 +34,19 @@ public:
void menu(const memoryview<String>& choices, void menu(const memoryview<String>& choices,
MenuCallback callback); MenuCallback callback);
void print_status(const String& status, CharCount cursor_pos = -1);
void draw_window(Window& window);
void on_next_key(KeyCallback callback); void on_next_key(KeyCallback callback);
void handle_next_input(Context& context); void handle_next_input(Context& context);
private: private:
virtual void menu_show(const memoryview<String>& choices) = 0;
virtual void menu_select(int selected) = 0;
virtual void menu_hide() = 0;
virtual Key get_key() = 0;
void reset_normal_mode(); void reset_normal_mode();
std::pair<IncrementalInserter::Mode, std::vector<Key>> m_last_insert; std::pair<IncrementalInserter::Mode, std::vector<Key>> m_last_insert;
std::unique_ptr<UserInterface> m_ui;
class Mode; class Mode;
std::unique_ptr<Mode> m_mode; std::unique_ptr<Mode> m_mode;

View File

@ -649,10 +649,10 @@ private:
char m_name; char m_name;
}; };
class BatchClient : public Client class BatchUI : public UserInterface
{ {
public: public:
BatchClient(const KeyList& keys) BatchUI(const KeyList& keys)
: m_keys(keys), m_pos(0) : m_keys(keys), m_pos(0)
{ {
} }
@ -680,7 +680,8 @@ private:
void exec_keys(const KeyList& keys, Context& context) void exec_keys(const KeyList& keys, Context& context)
{ {
BatchClient batch_client(keys); BatchUI* batch_ui = new BatchUI(keys);
Client batch_client(batch_ui);
RegisterRestorer quote('"', context); RegisterRestorer quote('"', context);
RegisterRestorer slash('/', context); RegisterRestorer slash('/', context);
@ -689,7 +690,7 @@ void exec_keys(const KeyList& keys, Context& context)
Context new_context(batch_client); Context new_context(batch_client);
new_context.change_editor(context.editor()); new_context.change_editor(context.editor());
while (batch_client.has_key_left()) while (batch_ui->has_key_left())
batch_client.handle_next_input(new_context); batch_client.handle_next_input(new_context);
} }

View File

@ -7,6 +7,8 @@
namespace Kakoune namespace Kakoune
{ {
// A Context is provided to all commands, it permits
// to access a client, window, editor or buffer if available.
struct Context struct Context
{ {
Context() {} Context() {}

View File

@ -475,7 +475,7 @@ int main(int argc, char* argv[])
try try
{ {
NCursesClient client; Client client(new NCursesUI());
Context context(client); Context context(client);
try try

View File

@ -70,7 +70,7 @@ static void set_color(Color fg_color, Color bg_color)
} }
NCursesClient::NCursesClient() NCursesUI::NCursesUI()
: m_menu(nullptr) : m_menu(nullptr)
{ {
// setlocale(LC_ALL, ""); // setlocale(LC_ALL, "");
@ -89,12 +89,12 @@ NCursesClient::NCursesClient()
m_menu_bg = get_color_pair(Color::Cyan, Color::Blue); m_menu_bg = get_color_pair(Color::Cyan, Color::Blue);
} }
NCursesClient::~NCursesClient() NCursesUI::~NCursesUI()
{ {
endwin(); endwin();
} }
void NCursesClient::draw_window(Window& window) void NCursesUI::draw_window(Window& window)
{ {
int max_x,max_y; int max_x,max_y;
getmaxyx(stdscr, max_y, max_x); getmaxyx(stdscr, max_y, max_x);
@ -164,7 +164,7 @@ void NCursesClient::draw_window(Window& window)
refresh(); refresh();
} }
Key NCursesClient::get_key() Key NCursesUI::get_key()
{ {
const int c = getch(); const int c = getch();
@ -196,7 +196,7 @@ Key NCursesClient::get_key()
return c; return c;
} }
void NCursesClient::print_status(const String& status, CharCount cursor_pos) void NCursesUI::print_status(const String& status, CharCount cursor_pos)
{ {
int x,y; int x,y;
getmaxyx(stdscr, y, x); getmaxyx(stdscr, y, x);
@ -222,7 +222,7 @@ void NCursesClient::print_status(const String& status, CharCount cursor_pos)
refresh(); refresh();
} }
void NCursesClient::menu_show(const memoryview<String>& choices) void NCursesUI::menu_show(const memoryview<String>& choices)
{ {
assert(m_menu == nullptr); assert(m_menu == nullptr);
m_choices = std::vector<String>(choices.begin(), choices.end()); m_choices = std::vector<String>(choices.begin(), choices.end());
@ -252,7 +252,7 @@ void NCursesClient::menu_show(const memoryview<String>& choices)
refresh(); refresh();
} }
void NCursesClient::menu_select(int selected) void NCursesUI::menu_select(int selected)
{ {
// last item in m_items is the nullptr, hence the - 1 // last item in m_items is the nullptr, hence the - 1
if (selected >= 0 and selected < m_items.size() - 1) if (selected >= 0 and selected < m_items.size() - 1)
@ -265,7 +265,7 @@ void NCursesClient::menu_select(int selected)
refresh(); refresh();
} }
void NCursesClient::menu_hide() void NCursesUI::menu_hide()
{ {
if (not m_menu) if (not m_menu)
return; return;

View File

@ -4,19 +4,19 @@
#include <ncurses.h> #include <ncurses.h>
#include <menu.h> #include <menu.h>
#include "client.hh" #include "user_interface.hh"
namespace Kakoune namespace Kakoune
{ {
class NCursesClient : public Client class NCursesUI : public UserInterface
{ {
public: public:
NCursesClient(); NCursesUI();
~NCursesClient(); ~NCursesUI();
NCursesClient(const NCursesClient&) = delete; NCursesUI(const NCursesUI&) = delete;
NCursesClient& operator=(const NCursesClient&) = delete; NCursesUI& operator=(const NCursesUI&) = delete;
void draw_window(Window& window) override; void draw_window(Window& window) override;
void print_status(const String& status, CharCount cursor_pos) override; void print_status(const String& status, CharCount cursor_pos) override;

28
src/user_interface.hh Normal file
View File

@ -0,0 +1,28 @@
#ifndef user_interface_hh_INCLUDED
#define user_interface_hh_INCLUDED
#include "memoryview.hh"
#include "keys.hh"
#include "units.hh"
namespace Kakoune
{
class String;
class Window;
class UserInterface
{
public:
virtual ~UserInterface() {}
virtual void print_status(const String& status, CharCount cursor_pos) = 0;
virtual void menu_show(const memoryview<String>& choices) = 0;
virtual void menu_select(int selected) = 0;
virtual void menu_hide() = 0;
virtual void draw_window(Window& window) = 0;
virtual Key get_key() = 0;
};
}
#endif // user_interface_hh_INCLUDED