Extract InputHandler from Client

This commit is contained in:
Maxime Coste 2013-11-14 18:09:15 +00:00
parent fe55d51e9f
commit ad275d1d1c
9 changed files with 198 additions and 134 deletions

View File

@ -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());
}
}

View File

@ -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)

View File

@ -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;
};
}

View File

@ -1,7 +1,6 @@
#ifndef client_manager_hh_INCLUDED
#define client_manager_hh_INCLUDED
#include "context.hh"
#include "client.hh"
namespace Kakoune

View File

@ -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()

View File

@ -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();
}
}

View File

@ -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>;

View File

@ -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 ");
}

View File

@ -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());
}
}