Extract InputHandler from Client
This commit is contained in:
parent
fe55d51e9f
commit
ad275d1d1c
|
@ -6,6 +6,7 @@
|
|||
#include "file.hh"
|
||||
#include "utils.hh"
|
||||
#include "window.hh"
|
||||
#include "client.hh"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -40,19 +41,19 @@ Buffer::Buffer(String name, Flags flags, std::vector<String> lines,
|
|||
}
|
||||
|
||||
Editor editor_for_hooks(*this);
|
||||
Context context(editor_for_hooks);
|
||||
InputHandler hook_handler(editor_for_hooks);
|
||||
if (flags & Flags::File)
|
||||
{
|
||||
if (flags & Flags::New)
|
||||
m_hooks.run_hook("BufNew", m_name, context);
|
||||
m_hooks.run_hook("BufNew", m_name, hook_handler.context());
|
||||
else
|
||||
{
|
||||
kak_assert(m_fs_timestamp != InvalidTime);
|
||||
m_hooks.run_hook("BufOpen", m_name, context);
|
||||
m_hooks.run_hook("BufOpen", m_name, hook_handler.context());
|
||||
}
|
||||
}
|
||||
|
||||
m_hooks.run_hook("BufCreate", m_name, context);
|
||||
m_hooks.run_hook("BufCreate", m_name, hook_handler.context());
|
||||
|
||||
// now we may begin to record undo data
|
||||
m_flags = flags;
|
||||
|
@ -65,8 +66,8 @@ Buffer::~Buffer()
|
|||
{
|
||||
{
|
||||
Editor hook_editor{*this};
|
||||
Context hook_context{hook_editor};
|
||||
m_hooks.run_hook("BufClose", m_name, hook_context);
|
||||
InputHandler hook_handler(hook_editor);
|
||||
m_hooks.run_hook("BufClose", m_name, hook_handler.context());
|
||||
}
|
||||
|
||||
m_options.unregister_watcher(*this);
|
||||
|
@ -763,7 +764,7 @@ void Buffer::on_option_changed(const Option& option)
|
|||
{
|
||||
String desc = option.name() + "=" + option.get_as_string();
|
||||
Editor hook_editor{*this};
|
||||
Context hook_context{hook_editor};
|
||||
m_hooks.run_hook("BufSetOption", desc, hook_context);
|
||||
InputHandler hook_handler(hook_editor);
|
||||
m_hooks.run_hook("BufSetOption", desc, hook_handler.context());
|
||||
}
|
||||
}
|
||||
|
|
151
src/client.cc
151
src/client.cc
|
@ -22,26 +22,26 @@ namespace Kakoune
|
|||
class InputMode
|
||||
{
|
||||
public:
|
||||
InputMode(Client& client) : m_client(client) {}
|
||||
InputMode(InputHandler& input_handler) : m_input_handler(input_handler) {}
|
||||
virtual ~InputMode() {}
|
||||
InputMode(const InputMode&) = delete;
|
||||
InputMode& operator=(const InputMode&) = delete;
|
||||
|
||||
virtual void on_key(Key key) = 0;
|
||||
virtual void on_replaced() {}
|
||||
Context& context() const { return m_client.context(); }
|
||||
Context& context() const { return m_input_handler.context(); }
|
||||
|
||||
virtual String description() const = 0;
|
||||
|
||||
virtual KeymapMode keymap_mode() const = 0;
|
||||
|
||||
using Insertion = Client::Insertion;
|
||||
Insertion& last_insert() { return m_client.m_last_insert; }
|
||||
using Insertion = InputHandler::Insertion;
|
||||
Insertion& last_insert() { return m_input_handler.m_last_insert; }
|
||||
|
||||
protected:
|
||||
void reset_normal_mode();
|
||||
private:
|
||||
Client& m_client;
|
||||
InputHandler& m_input_handler;
|
||||
};
|
||||
|
||||
namespace InputModes
|
||||
|
@ -53,17 +53,18 @@ static constexpr std::chrono::milliseconds fs_check_timeout{500};
|
|||
class Normal : public InputMode
|
||||
{
|
||||
public:
|
||||
Normal(Client& client)
|
||||
: InputMode(client),
|
||||
Normal(InputHandler& input_handler)
|
||||
: InputMode(input_handler),
|
||||
m_idle_timer{Clock::now() + idle_timeout, [this](Timer& timer) {
|
||||
context().hooks().run_hook("NormalIdle", "", context());
|
||||
}},
|
||||
m_fs_check_timer{Clock::now() + fs_check_timeout, [this](Timer& timer) {
|
||||
if (not context().has_client())
|
||||
return;
|
||||
context().client().check_buffer_fs_timestamp();
|
||||
timer.set_next_date(Clock::now() + fs_check_timeout);
|
||||
}}
|
||||
{
|
||||
context().client().check_buffer_fs_timestamp();
|
||||
context().hooks().run_hook("NormalBegin", "", context());
|
||||
}
|
||||
|
||||
|
@ -179,12 +180,14 @@ private:
|
|||
class Menu : public InputMode
|
||||
{
|
||||
public:
|
||||
Menu(Client& client, memoryview<String> choices,
|
||||
Menu(InputHandler& input_handler, memoryview<String> choices,
|
||||
MenuCallback callback)
|
||||
: InputMode(client),
|
||||
: InputMode(input_handler),
|
||||
m_callback(callback), m_choices(choices.begin(), choices.end()),
|
||||
m_selected(m_choices.begin())
|
||||
{
|
||||
if (not context().has_ui())
|
||||
return;
|
||||
DisplayCoord menu_pos{ context().ui().dimensions().line, 0_char };
|
||||
context().ui().menu_show(choices, menu_pos, get_color("MenuForeground"),
|
||||
get_color("MenuBackground"), MenuStyle::Prompt);
|
||||
|
@ -198,6 +201,7 @@ public:
|
|||
|
||||
if (key == ctrl('m'))
|
||||
{
|
||||
if (context().has_ui())
|
||||
context().ui().menu_hide();
|
||||
context().print_status(DisplayLine{});
|
||||
reset_normal_mode();
|
||||
|
@ -216,6 +220,7 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
if (context().has_ui())
|
||||
context().ui().menu_hide();
|
||||
reset_normal_mode();
|
||||
int selected = m_selected - m_choices.begin();
|
||||
|
@ -281,6 +286,7 @@ private:
|
|||
{
|
||||
m_selected = it;
|
||||
int selected = m_selected - m_choices.begin();
|
||||
if (context().has_ui())
|
||||
context().ui().menu_select(selected);
|
||||
m_callback(selected, MenuEvent::Select, context());
|
||||
}
|
||||
|
@ -311,9 +317,9 @@ String common_prefix(memoryview<String> strings)
|
|||
class Prompt : public InputMode
|
||||
{
|
||||
public:
|
||||
Prompt(Client& client, const String& prompt,
|
||||
Prompt(InputHandler& input_handler, const String& prompt,
|
||||
ColorPair colors, Completer completer, PromptCallback callback)
|
||||
: InputMode(client), m_prompt(prompt), m_prompt_colors(colors),
|
||||
: InputMode(input_handler), m_prompt(prompt), m_prompt_colors(colors),
|
||||
m_completer(completer), m_callback(callback)
|
||||
{
|
||||
m_history_it = ms_history[m_prompt].end();
|
||||
|
@ -344,6 +350,7 @@ public:
|
|||
history.push_back(line);
|
||||
}
|
||||
context().print_status(DisplayLine{});
|
||||
if (context().has_ui())
|
||||
context().ui().menu_hide();
|
||||
reset_normal_mode();
|
||||
// call callback after reset_normal_mode so that callback
|
||||
|
@ -354,6 +361,7 @@ public:
|
|||
else if (key == Key::Escape or key == ctrl('c'))
|
||||
{
|
||||
context().print_status(DisplayLine{});
|
||||
if (context().has_ui())
|
||||
context().ui().menu_hide();
|
||||
reset_normal_mode();
|
||||
m_callback(line, PromptEvent::Abort, context());
|
||||
|
@ -432,6 +440,7 @@ public:
|
|||
m_current_completion = candidates.size()-1;
|
||||
|
||||
const String& completion = candidates[m_current_completion];
|
||||
if (context().has_ui())
|
||||
context().ui().menu_select(m_current_completion);
|
||||
|
||||
m_line_editor.insert_from(line.char_count_to(m_completions.start),
|
||||
|
@ -450,6 +459,7 @@ public:
|
|||
{
|
||||
m_line_editor.handle_key(key);
|
||||
m_current_completion = -1;
|
||||
if (context().has_ui())
|
||||
context().ui().menu_hide();
|
||||
showcompl = true;
|
||||
}
|
||||
|
@ -486,7 +496,7 @@ private:
|
|||
m_completions = m_completer(context(), CompletionFlags::Fast, line,
|
||||
line.byte_count_to(m_line_editor.cursor_pos()));
|
||||
CandidateList& candidates = m_completions.candidates;
|
||||
if (not candidates.empty())
|
||||
if (context().has_ui() and not candidates.empty())
|
||||
{
|
||||
DisplayCoord menu_pos{ context().ui().dimensions().line, 0_char };
|
||||
context().ui().menu_show(candidates, menu_pos, get_color("MenuForeground"),
|
||||
|
@ -522,8 +532,8 @@ std::unordered_map<String, std::vector<String>> Prompt::ms_history;
|
|||
class NextKey : public InputMode
|
||||
{
|
||||
public:
|
||||
NextKey(Client& client, KeyCallback callback)
|
||||
: InputMode(client), m_callback(callback) {}
|
||||
NextKey(InputHandler& input_handler, KeyCallback callback)
|
||||
: InputMode(input_handler), m_callback(callback) {}
|
||||
|
||||
void on_key(Key key) override
|
||||
{
|
||||
|
@ -592,6 +602,7 @@ public:
|
|||
m_completions.end = cursor_pos;
|
||||
m_completions.begin = buffer.advance(m_completions.end, -candidate.length());
|
||||
m_completions.timestamp = m_context.buffer().timestamp();
|
||||
if (m_context.has_ui())
|
||||
m_context.ui().menu_select(m_current_candidate);
|
||||
|
||||
// when we select a match, remove non displayed matches from the candidates
|
||||
|
@ -630,7 +641,6 @@ public:
|
|||
}
|
||||
if (not m_matching_candidates.empty())
|
||||
{
|
||||
m_context.ui().menu_hide();
|
||||
m_current_candidate = m_matching_candidates.size();
|
||||
m_completions.end = cursor;
|
||||
menu_show();
|
||||
|
@ -646,6 +656,7 @@ public:
|
|||
void reset()
|
||||
{
|
||||
m_completions = BufferCompletion{};
|
||||
if (m_context.has_ui())
|
||||
m_context.ui().menu_hide();
|
||||
}
|
||||
|
||||
|
@ -661,7 +672,6 @@ public:
|
|||
kak_assert(cursor_pos >= m_completions.begin);
|
||||
m_matching_candidates = m_completions.candidates;
|
||||
m_current_candidate = m_matching_candidates.size();
|
||||
m_context.ui().menu_hide();
|
||||
menu_show();
|
||||
m_matching_candidates.push_back(buffer.string(m_completions.begin, m_completions.end));
|
||||
return true;
|
||||
|
@ -814,6 +824,8 @@ private:
|
|||
|
||||
void menu_show()
|
||||
{
|
||||
if (m_context.has_ui())
|
||||
return;
|
||||
DisplayCoord menu_pos = m_context.window().display_position(m_completions.begin);
|
||||
m_context.ui().menu_show(m_matching_candidates, menu_pos,
|
||||
get_color("MenuForeground"),
|
||||
|
@ -850,8 +862,8 @@ private:
|
|||
class Insert : public InputMode
|
||||
{
|
||||
public:
|
||||
Insert(Client& client, InsertMode mode)
|
||||
: InputMode(client),
|
||||
Insert(InputHandler& input_handler, InsertMode mode)
|
||||
: InputMode(input_handler),
|
||||
m_insert_mode(mode),
|
||||
m_edition(context().editor()),
|
||||
m_completer(context()),
|
||||
|
@ -1088,31 +1100,31 @@ private:
|
|||
|
||||
void InputMode::reset_normal_mode()
|
||||
{
|
||||
m_client.reset_normal_mode();
|
||||
m_input_handler.reset_normal_mode();
|
||||
}
|
||||
|
||||
Client::Client(std::unique_ptr<UserInterface>&& ui, Editor& editor, String name)
|
||||
: m_ui(std::move(ui)), m_context(*this, editor), m_mode(new InputModes::Normal(*this)), m_name(name)
|
||||
InputHandler::InputHandler(Editor& editor)
|
||||
: m_mode(new InputModes::Normal(*this)),
|
||||
m_context(*this, editor)
|
||||
{
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
{
|
||||
}
|
||||
InputHandler::~InputHandler()
|
||||
{}
|
||||
|
||||
void Client::change_input_mode(InputMode* new_mode)
|
||||
void InputHandler::change_input_mode(InputMode* new_mode)
|
||||
{
|
||||
m_mode->on_replaced();
|
||||
m_mode_trash.emplace_back(std::move(m_mode));
|
||||
m_mode.reset(new_mode);
|
||||
}
|
||||
|
||||
void Client::insert(InsertMode mode)
|
||||
void InputHandler::insert(InsertMode mode)
|
||||
{
|
||||
change_input_mode(new InputModes::Insert(*this, mode));
|
||||
}
|
||||
|
||||
void Client::repeat_last_insert()
|
||||
void InputHandler::repeat_last_insert()
|
||||
{
|
||||
if (m_last_insert.second.empty())
|
||||
return;
|
||||
|
@ -1127,27 +1139,27 @@ void Client::repeat_last_insert()
|
|||
kak_assert(dynamic_cast<InputModes::Normal*>(m_mode.get()) != nullptr);
|
||||
}
|
||||
|
||||
void Client::prompt(const String& prompt, ColorPair prompt_colors,
|
||||
void InputHandler::prompt(const String& prompt, ColorPair prompt_colors,
|
||||
Completer completer, PromptCallback callback)
|
||||
{
|
||||
change_input_mode(new InputModes::Prompt(*this, prompt, prompt_colors,
|
||||
completer, callback));
|
||||
}
|
||||
|
||||
void Client::set_prompt_colors(ColorPair prompt_colors)
|
||||
void InputHandler::set_prompt_colors(ColorPair prompt_colors)
|
||||
{
|
||||
InputModes::Prompt* prompt = dynamic_cast<InputModes::Prompt*>(m_mode.get());
|
||||
if (prompt)
|
||||
prompt->set_prompt_colors(prompt_colors);
|
||||
}
|
||||
|
||||
void Client::menu(memoryview<String> choices,
|
||||
void InputHandler::menu(memoryview<String> choices,
|
||||
MenuCallback callback)
|
||||
{
|
||||
change_input_mode(new InputModes::Menu(*this, choices, callback));
|
||||
}
|
||||
|
||||
void Client::on_next_key(KeyCallback callback)
|
||||
void InputHandler::on_next_key(KeyCallback callback)
|
||||
{
|
||||
change_input_mode(new InputModes::NextKey(*this, callback));
|
||||
}
|
||||
|
@ -1157,17 +1169,7 @@ static bool is_valid(Key key)
|
|||
return key != Key::Invalid and key.key <= 0x10FFFF;
|
||||
}
|
||||
|
||||
void Client::handle_available_input()
|
||||
{
|
||||
while (m_ui->is_key_available())
|
||||
{
|
||||
handle_key(m_ui->get_key());
|
||||
m_mode_trash.clear();
|
||||
}
|
||||
m_context.window().forget_timestamp();
|
||||
}
|
||||
|
||||
void Client::handle_key(Key key)
|
||||
void InputHandler::handle_key(Key key)
|
||||
{
|
||||
if (is_valid(key))
|
||||
{
|
||||
|
@ -1189,29 +1191,59 @@ void Client::handle_key(Key key)
|
|||
}
|
||||
}
|
||||
|
||||
void Client::start_recording(char reg)
|
||||
void InputHandler::start_recording(char reg)
|
||||
{
|
||||
kak_assert(m_recording_reg == 0);
|
||||
m_recorded_keys = "";
|
||||
m_recording_reg = reg;
|
||||
}
|
||||
|
||||
bool Client::is_recording() const
|
||||
bool InputHandler::is_recording() const
|
||||
{
|
||||
return m_recording_reg != 0;
|
||||
}
|
||||
|
||||
void Client::stop_recording()
|
||||
void InputHandler::stop_recording()
|
||||
{
|
||||
kak_assert(m_recording_reg != 0);
|
||||
RegisterManager::instance()[m_recording_reg] = memoryview<String>(m_recorded_keys);
|
||||
m_recording_reg = 0;
|
||||
}
|
||||
|
||||
void InputHandler::reset_normal_mode()
|
||||
{
|
||||
change_input_mode(new InputModes::Normal(*this));
|
||||
}
|
||||
|
||||
void InputHandler::clear_mode_trash()
|
||||
{
|
||||
m_mode_trash.clear();
|
||||
}
|
||||
|
||||
Client::Client(std::unique_ptr<UserInterface>&& ui, Editor& editor, String name)
|
||||
: m_input_handler(editor), m_ui(std::move(ui)), m_name(name)
|
||||
{
|
||||
context().set_client(*this);
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
{
|
||||
}
|
||||
|
||||
void Client::handle_available_input()
|
||||
{
|
||||
while (m_ui->is_key_available())
|
||||
{
|
||||
m_input_handler.handle_key(m_ui->get_key());
|
||||
m_input_handler.clear_mode_trash();
|
||||
}
|
||||
context().window().forget_timestamp();
|
||||
}
|
||||
|
||||
void Client::print_status(DisplayLine status_line)
|
||||
{
|
||||
m_status_line = std::move(status_line);
|
||||
m_context.window().forget_timestamp();
|
||||
context().window().forget_timestamp();
|
||||
}
|
||||
|
||||
DisplayLine Client::generate_mode_line() const
|
||||
|
@ -1224,35 +1256,30 @@ DisplayLine Client::generate_mode_line() const
|
|||
<< " " << (int)pos.line+1 << ":" << (int)col+1;
|
||||
if (context().buffer().is_modified())
|
||||
oss << " [+]";
|
||||
if (is_recording())
|
||||
oss << " [recording (" << m_recording_reg << ")]";
|
||||
if (m_input_handler.is_recording())
|
||||
oss << " [recording (" << m_input_handler.recording_reg() << ")]";
|
||||
if (context().buffer().flags() & Buffer::Flags::New)
|
||||
oss << " [new file]";
|
||||
oss << " [" << m_mode->description() << "]" << " - " << name()
|
||||
oss << " [" << m_input_handler.mode().description() << "]" << " - " << name()
|
||||
<< "@[" << Server::instance().session() << "]";
|
||||
return { oss.str(), get_color("StatusLine") };
|
||||
}
|
||||
|
||||
void Client::redraw_ifn()
|
||||
{
|
||||
if (m_context.window().timestamp() != m_context.buffer().timestamp())
|
||||
if (context().window().timestamp() != context().buffer().timestamp())
|
||||
{
|
||||
DisplayCoord dimensions = m_context.ui().dimensions();
|
||||
DisplayCoord dimensions = context().ui().dimensions();
|
||||
if (dimensions == DisplayCoord{0,0})
|
||||
return;
|
||||
m_context.window().set_dimensions(dimensions);
|
||||
m_context.window().update_display_buffer();;
|
||||
context().window().set_dimensions(dimensions);
|
||||
context().window().update_display_buffer();;
|
||||
|
||||
m_context.ui().draw(m_context.window().display_buffer(),
|
||||
context().ui().draw(context().window().display_buffer(),
|
||||
m_status_line, generate_mode_line());
|
||||
}
|
||||
}
|
||||
|
||||
void Client::reset_normal_mode()
|
||||
{
|
||||
change_input_mode(new InputModes::Normal(*this));
|
||||
}
|
||||
|
||||
static void reload_buffer(Context& context, const String& filename)
|
||||
{
|
||||
DisplayCoord view_pos = context.window().position();
|
||||
|
@ -1270,7 +1297,7 @@ static void reload_buffer(Context& context, const String& filename)
|
|||
|
||||
void Client::check_buffer_fs_timestamp()
|
||||
{
|
||||
Buffer& buffer = m_context.buffer();
|
||||
Buffer& buffer = context().buffer();
|
||||
auto reload = context().options()["autoreload"].get<YesNoAsk>();
|
||||
if (not (buffer.flags() & Buffer::Flags::File) or reload == No)
|
||||
return;
|
||||
|
@ -1282,7 +1309,7 @@ void Client::check_buffer_fs_timestamp()
|
|||
if (reload == Ask)
|
||||
{
|
||||
print_status({"'" + buffer.display_name() + "' was modified externally, press r or y to reload, k or n to keep", get_color("Prompt")});
|
||||
on_next_key([this, ts, filename](Key key, Context& context) {
|
||||
m_input_handler.on_next_key([this, ts, filename](Key key, Context& context) {
|
||||
Buffer* buf = BufferManager::instance().get_buffer_ifp(filename);
|
||||
// buffer got deleted while waiting for the key, do nothing
|
||||
if (not buf)
|
||||
|
|
|
@ -35,11 +35,11 @@ using KeyCallback = std::function<void (Key, Context&)>;
|
|||
class InputMode;
|
||||
enum class InsertMode : unsigned;
|
||||
|
||||
class Client : public SafeCountable
|
||||
class InputHandler : public SafeCountable
|
||||
{
|
||||
public:
|
||||
Client(std::unique_ptr<UserInterface>&& ui, Editor& editor, String name);
|
||||
~Client();
|
||||
InputHandler(Editor& editor);
|
||||
~InputHandler();
|
||||
|
||||
// switch to insert mode
|
||||
void insert(InsertMode mode);
|
||||
|
@ -65,18 +65,46 @@ public:
|
|||
// if callback does not change the mode itself
|
||||
void on_next_key(KeyCallback callback);
|
||||
|
||||
|
||||
// handle all the keys currently available in the user interface
|
||||
void handle_available_input();
|
||||
// process the given key
|
||||
void handle_key(Key key);
|
||||
|
||||
void start_recording(char reg);
|
||||
bool is_recording() const;
|
||||
void stop_recording();
|
||||
char recording_reg() const { return m_recording_reg; }
|
||||
|
||||
void reset_normal_mode();
|
||||
|
||||
Context& context() { return m_context; }
|
||||
const Context& context() const { return m_context; }
|
||||
|
||||
const InputMode& mode() const { return *m_mode; }
|
||||
void clear_mode_trash();
|
||||
private:
|
||||
Context m_context;
|
||||
|
||||
friend class InputMode;
|
||||
std::unique_ptr<InputMode> m_mode;
|
||||
std::vector<std::unique_ptr<InputMode>> m_mode_trash;
|
||||
|
||||
void change_input_mode(InputMode* new_mode);
|
||||
|
||||
using Insertion = std::pair<InsertMode, std::vector<Key>>;
|
||||
Insertion m_last_insert = {InsertMode::Insert, {}};
|
||||
|
||||
char m_recording_reg = 0;
|
||||
String m_recorded_keys;
|
||||
};
|
||||
|
||||
class Client : public SafeCountable
|
||||
{
|
||||
public:
|
||||
Client(std::unique_ptr<UserInterface>&& ui, Editor& editor, String name);
|
||||
~Client();
|
||||
|
||||
// handle all the keys currently available in the user interface
|
||||
void handle_available_input();
|
||||
|
||||
const String& name() const { return m_name; }
|
||||
void set_name(String name) { m_name = std::move(name); }
|
||||
|
||||
|
@ -88,26 +116,18 @@ public:
|
|||
|
||||
void check_buffer_fs_timestamp();
|
||||
|
||||
void reset_normal_mode();
|
||||
Context& context() { return m_input_handler.context(); }
|
||||
const Context& context() const { return m_input_handler.context(); }
|
||||
|
||||
private:
|
||||
void change_input_mode(InputMode* new_mode);
|
||||
InputHandler m_input_handler;
|
||||
|
||||
DisplayLine generate_mode_line() const;
|
||||
|
||||
Context m_context;
|
||||
friend class InputMode;
|
||||
std::unique_ptr<UserInterface> m_ui;
|
||||
std::unique_ptr<InputMode> m_mode;
|
||||
std::vector<std::unique_ptr<InputMode>> m_mode_trash;
|
||||
|
||||
String m_name;
|
||||
DisplayLine m_status_line;
|
||||
|
||||
using Insertion = std::pair<InsertMode, std::vector<Key>>;
|
||||
Insertion m_last_insert = {InsertMode::Insert, {}};
|
||||
|
||||
char m_recording_reg = 0;
|
||||
String m_recorded_keys;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef client_manager_hh_INCLUDED
|
||||
#define client_manager_hh_INCLUDED
|
||||
|
||||
#include "context.hh"
|
||||
#include "client.hh"
|
||||
|
||||
namespace Kakoune
|
||||
|
|
|
@ -642,7 +642,7 @@ void menu(CommandParameters params, Context& context)
|
|||
select_cmds.push_back(parser[i+2]);
|
||||
}
|
||||
|
||||
context.client().menu(choices,
|
||||
context.input_handler().menu(choices,
|
||||
[=](int choice, MenuEvent event, Context& context) {
|
||||
if (event == MenuEvent::Validate and choice >= 0 and choice < commands.size())
|
||||
CommandManager::instance().execute(commands[choice], context);
|
||||
|
@ -801,7 +801,7 @@ void exec_keys(const KeyList& keys, Context& context)
|
|||
scoped_edition edition(context.editor());
|
||||
|
||||
for (auto& key : keys)
|
||||
context.client().handle_key(key);
|
||||
context.input_handler().handle_key(key);
|
||||
}
|
||||
|
||||
void register_commands()
|
||||
|
|
|
@ -9,11 +9,8 @@ namespace Kakoune
|
|||
|
||||
Context::Context() = default;
|
||||
|
||||
Context::Context(Editor& editor)
|
||||
: m_editor(&editor) {}
|
||||
|
||||
Context::Context(Client& client, Editor& editor)
|
||||
: m_client(&client), m_editor(&editor) {}
|
||||
Context::Context(InputHandler& input_handler, Editor& editor)
|
||||
: m_input_handler(&input_handler), m_editor(&editor) {}
|
||||
|
||||
Context::~Context() = default;
|
||||
|
||||
|
@ -43,10 +40,17 @@ bool Context::has_window() const
|
|||
return (bool)m_editor and dynamic_cast<Window*>(m_editor.get());
|
||||
}
|
||||
|
||||
InputHandler& Context::input_handler() const
|
||||
{
|
||||
if (not has_input_handler())
|
||||
throw runtime_error("no input handler in context");
|
||||
return *m_input_handler;
|
||||
}
|
||||
|
||||
Client& Context::client() const
|
||||
{
|
||||
if (not has_client())
|
||||
throw runtime_error("no input handler in context");
|
||||
throw runtime_error("no client in context");
|
||||
return *m_client;
|
||||
}
|
||||
|
||||
|
@ -54,7 +58,7 @@ UserInterface& Context::ui() const
|
|||
{
|
||||
if (not has_ui())
|
||||
throw runtime_error("no user interface in context");
|
||||
return m_client->ui();
|
||||
return client().ui();
|
||||
}
|
||||
|
||||
OptionManager& Context::options() const
|
||||
|
@ -84,6 +88,12 @@ KeymapManager& Context::keymaps() const
|
|||
return GlobalKeymaps::instance();
|
||||
}
|
||||
|
||||
void Context::set_client(Client& client)
|
||||
{
|
||||
kak_assert(not has_client());
|
||||
m_client.reset(&client);
|
||||
}
|
||||
|
||||
void Context::print_status(DisplayLine status) const
|
||||
{
|
||||
if (has_client())
|
||||
|
@ -162,8 +172,8 @@ void Context::change_editor(Editor& editor)
|
|||
window().set_dimensions(ui().dimensions());
|
||||
window().hooks().run_hook("WinDisplay", buffer().name(), *this);
|
||||
}
|
||||
if (has_client())
|
||||
client().reset_normal_mode();
|
||||
if (has_input_handler())
|
||||
input_handler().reset_normal_mode();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ class Editor;
|
|||
class Window;
|
||||
class Buffer;
|
||||
class Client;
|
||||
class InputHandler;
|
||||
class UserInterface;
|
||||
class DisplayLine;
|
||||
class KeymapManager;
|
||||
|
@ -24,8 +25,7 @@ class Context
|
|||
{
|
||||
public:
|
||||
Context();
|
||||
explicit Context(Editor& editor);
|
||||
Context(Client& client, Editor& editor);
|
||||
Context(InputHandler& input_handler, Editor& editor);
|
||||
~Context();
|
||||
|
||||
Context(const Context&) = delete;
|
||||
|
@ -43,11 +43,16 @@ public:
|
|||
Client& client() const;
|
||||
bool has_client() const { return (bool)m_client; }
|
||||
|
||||
InputHandler& input_handler() const;
|
||||
bool has_input_handler() const { return (bool)m_input_handler; }
|
||||
|
||||
UserInterface& ui() const;
|
||||
bool has_ui() const { return (bool)m_client; }
|
||||
bool has_ui() const { return has_client(); }
|
||||
|
||||
void change_editor(Editor& editor);
|
||||
|
||||
void set_client(Client& client);
|
||||
|
||||
OptionManager& options() const;
|
||||
HookManager& hooks() const;
|
||||
KeymapManager& keymaps() const;
|
||||
|
@ -61,6 +66,7 @@ public:
|
|||
|
||||
private:
|
||||
safe_ptr<Editor> m_editor;
|
||||
safe_ptr<InputHandler> m_input_handler;
|
||||
safe_ptr<Client> m_client;
|
||||
|
||||
using JumpList = std::vector<DynamicSelectionList>;
|
||||
|
|
|
@ -25,12 +25,12 @@ using namespace std::placeholders;
|
|||
template<InsertMode mode>
|
||||
void insert(Context& context, int)
|
||||
{
|
||||
context.client().insert(mode);
|
||||
context.input_handler().insert(mode);
|
||||
}
|
||||
|
||||
void repeat_insert(Context& context, int)
|
||||
{
|
||||
context.client().repeat_last_insert();
|
||||
context.input_handler().repeat_last_insert();
|
||||
}
|
||||
|
||||
bool show_auto_info_ifn(const String& title, const String& info,
|
||||
|
@ -50,7 +50,7 @@ void on_next_key_with_autoinfo(const Context& context, Cmd cmd,
|
|||
const String& title, const String& info)
|
||||
{
|
||||
const bool hide = show_auto_info_ifn(title, info, context);
|
||||
context.client().on_next_key([hide,cmd](Key key, Context& context) mutable {
|
||||
context.input_handler().on_next_key([hide,cmd](Key key, Context& context) mutable {
|
||||
if (hide)
|
||||
context.ui().info_hide();
|
||||
cmd(key, context);
|
||||
|
@ -247,7 +247,7 @@ void for_each_char(Context& context, int)
|
|||
|
||||
void command(Context& context, int)
|
||||
{
|
||||
context.client().prompt(
|
||||
context.input_handler().prompt(
|
||||
":", get_color("Prompt"),
|
||||
std::bind(&CommandManager::complete, &CommandManager::instance(), _1, _2, _3, _4),
|
||||
[](const String& cmdline, PromptEvent event, Context& context) {
|
||||
|
@ -258,7 +258,7 @@ void command(Context& context, int)
|
|||
|
||||
void pipe(Context& context, int)
|
||||
{
|
||||
context.client().prompt("pipe:", get_color("Prompt"), complete_nothing,
|
||||
context.input_handler().prompt("pipe:", get_color("Prompt"), complete_nothing,
|
||||
[](const String& cmdline, PromptEvent event, Context& context)
|
||||
{
|
||||
if (event != PromptEvent::Validate)
|
||||
|
@ -299,7 +299,7 @@ void search(Context& context, int)
|
|||
{
|
||||
const char* prompt = direction == Forward ? "search:" : "reverse search:";
|
||||
DynamicSelectionList selections{context.buffer(), context.editor().selections()};
|
||||
context.client().prompt(prompt, get_color("Prompt"), complete_nothing,
|
||||
context.input_handler().prompt(prompt, get_color("Prompt"), complete_nothing,
|
||||
[selections](const String& str, PromptEvent event, Context& context) {
|
||||
try
|
||||
{
|
||||
|
@ -309,7 +309,7 @@ void search(Context& context, int)
|
|||
return;
|
||||
|
||||
Regex ex{str};
|
||||
context.client().set_prompt_colors(get_color("Prompt"));
|
||||
context.input_handler().set_prompt_colors(get_color("Prompt"));
|
||||
if (event == PromptEvent::Validate)
|
||||
{
|
||||
if (str.empty())
|
||||
|
@ -328,7 +328,7 @@ void search(Context& context, int)
|
|||
if (event == PromptEvent::Validate)
|
||||
throw runtime_error("regex error: "_str + err.what());
|
||||
else
|
||||
context.client().set_prompt_colors(get_color("Error"));
|
||||
context.input_handler().set_prompt_colors(get_color("Error"));
|
||||
}
|
||||
catch (runtime_error&)
|
||||
{
|
||||
|
@ -449,7 +449,7 @@ void paste(Context& context, int)
|
|||
template<typename T>
|
||||
void regex_prompt(Context& context, const String prompt, T on_validate)
|
||||
{
|
||||
context.client().prompt(prompt, get_color("Prompt"), complete_nothing,
|
||||
context.input_handler().prompt(prompt, get_color("Prompt"), complete_nothing,
|
||||
[=](const String& str, PromptEvent event, Context& context) {
|
||||
if (event == PromptEvent::Validate)
|
||||
{
|
||||
|
@ -465,7 +465,7 @@ void regex_prompt(Context& context, const String prompt, T on_validate)
|
|||
else if (event == PromptEvent::Change)
|
||||
{
|
||||
const bool ok = Regex{str, boost::regex_constants::no_except}.status() == 0;
|
||||
context.client().set_prompt_colors(get_color(ok ? "Prompt" : "Error"));
|
||||
context.input_handler().set_prompt_colors(get_color(ok ? "Prompt" : "Error"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -755,13 +755,13 @@ void select_to_next_char(Context& context, int param)
|
|||
|
||||
void start_or_end_macro_recording(Context& context, int)
|
||||
{
|
||||
if (context.client().is_recording())
|
||||
context.client().stop_recording();
|
||||
if (context.input_handler().is_recording())
|
||||
context.input_handler().stop_recording();
|
||||
else
|
||||
on_next_key_with_autoinfo(context, [](Key key, Context& context) {
|
||||
if (key.modifiers == Key::Modifiers::None and
|
||||
key.key >= 'a' and key.key <= 'z')
|
||||
context.client().start_recording(key.key);
|
||||
context.input_handler().start_recording(key.key);
|
||||
}, "record macro", "enter macro name ");
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "context.hh"
|
||||
#include "highlighter.hh"
|
||||
#include "hook_manager.hh"
|
||||
#include "client.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
@ -22,8 +23,8 @@ Window::Window(Buffer& buffer)
|
|||
m_options(buffer.options()),
|
||||
m_keymaps(buffer.keymaps())
|
||||
{
|
||||
Context hook_context{*this};
|
||||
m_hooks.run_hook("WinCreate", buffer.name(), hook_context);
|
||||
InputHandler hook_handler{*this};
|
||||
m_hooks.run_hook("WinCreate", buffer.name(), hook_handler.context());
|
||||
m_options.register_watcher(*this);
|
||||
|
||||
m_builtin_highlighters.append({"tabulations", expand_tabulations});
|
||||
|
@ -36,8 +37,8 @@ Window::Window(Buffer& buffer)
|
|||
|
||||
Window::~Window()
|
||||
{
|
||||
Context hook_context{*this};
|
||||
m_hooks.run_hook("WinClose", buffer().name(), hook_context);
|
||||
InputHandler hook_handler{*this};
|
||||
m_hooks.run_hook("WinClose", buffer().name(), hook_handler.context());
|
||||
m_options.unregister_watcher(*this);
|
||||
}
|
||||
|
||||
|
@ -250,8 +251,8 @@ BufferCoord Window::offset_coord(BufferCoord coord, LineCount offset)
|
|||
void Window::on_option_changed(const Option& option)
|
||||
{
|
||||
String desc = option.name() + "=" + option.get_as_string();
|
||||
Context hook_context{*this};
|
||||
m_hooks.run_hook("WinSetOption", desc, hook_context);
|
||||
InputHandler hook_handler{*this};
|
||||
m_hooks.run_hook("WinSetOption", desc, hook_handler.context());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user