Get rid of Editor for good
ClientManager now stores only the free windows, clients take ownership of its own.
This commit is contained in:
parent
cb324a4b88
commit
c0973075fa
|
@ -786,8 +786,7 @@ void Buffer::on_option_changed(const Option& option)
|
||||||
|
|
||||||
void Buffer::run_hook_in_own_context(const String& hook_name, const String& param)
|
void Buffer::run_hook_in_own_context(const String& hook_name, const String& param)
|
||||||
{
|
{
|
||||||
Editor hook_editor{*this};
|
InputHandler hook_handler(*this, SelectionList{ {} });
|
||||||
InputHandler hook_handler(hook_editor);
|
|
||||||
m_hooks.run_hook(hook_name, param, hook_handler.context());
|
m_hooks.run_hook(hook_name, param, hook_handler.context());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -268,13 +268,13 @@ struct BufferListenerRegisterFuncs
|
||||||
class BufferChangeListener_AutoRegister
|
class BufferChangeListener_AutoRegister
|
||||||
: public BufferChangeListener,
|
: public BufferChangeListener,
|
||||||
public AutoRegister<BufferChangeListener_AutoRegister,
|
public AutoRegister<BufferChangeListener_AutoRegister,
|
||||||
BufferListenerRegisterFuncs, const Buffer>
|
BufferListenerRegisterFuncs, Buffer>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BufferChangeListener_AutoRegister(const Buffer& buffer)
|
BufferChangeListener_AutoRegister(Buffer& buffer)
|
||||||
: AutoRegister(buffer) {}
|
: AutoRegister(buffer) {}
|
||||||
|
|
||||||
const Buffer& buffer() const { return registry(); }
|
Buffer& buffer() const { return registry(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "color_registry.hh"
|
#include "color_registry.hh"
|
||||||
#include "context.hh"
|
#include "context.hh"
|
||||||
#include "editor.hh"
|
|
||||||
#include "buffer_manager.hh"
|
#include "buffer_manager.hh"
|
||||||
#include "user_interface.hh"
|
#include "user_interface.hh"
|
||||||
#include "file.hh"
|
#include "file.hh"
|
||||||
|
@ -13,10 +12,14 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
Client::Client(std::unique_ptr<UserInterface>&& ui, Editor& editor, String name)
|
Client::Client(std::unique_ptr<UserInterface>&& ui,
|
||||||
: m_input_handler(editor, std::move(name)), m_ui(std::move(ui))
|
std::unique_ptr<Window>&& window,
|
||||||
|
SelectionList selections, String name)
|
||||||
|
: m_ui{std::move(ui)}, m_window{std::move(window)},
|
||||||
|
m_input_handler{m_window->buffer(), std::move(selections), std::move(name)}
|
||||||
{
|
{
|
||||||
context().set_client(*this);
|
context().set_client(*this);
|
||||||
|
context().set_window(*m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
|
@ -58,6 +61,15 @@ DisplayLine Client::generate_mode_line() const
|
||||||
return { oss.str(), get_color("StatusLine") };
|
return { oss.str(), get_color("StatusLine") };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::change_buffer(Buffer& buffer)
|
||||||
|
{
|
||||||
|
ClientManager::instance().add_free_window(std::move(m_window), std::move(context().selections()));
|
||||||
|
std::tie(m_window, context().m_selections) = ClientManager::instance().get_free_window(buffer);
|
||||||
|
context().set_window(*m_window);
|
||||||
|
m_window->set_dimensions(ui().dimensions());
|
||||||
|
m_window->hooks().run_hook("WinDisplay", buffer.name(), context());
|
||||||
|
}
|
||||||
|
|
||||||
void Client::redraw_ifn()
|
void Client::redraw_ifn()
|
||||||
{
|
{
|
||||||
if (context().window().timestamp() != context().buffer().timestamp())
|
if (context().window().timestamp() != context().buffer().timestamp())
|
||||||
|
@ -80,10 +92,9 @@ static void reload_buffer(Context& context, const String& filename)
|
||||||
Buffer* buf = create_buffer_from_file(filename);
|
Buffer* buf = create_buffer_from_file(filename);
|
||||||
if (not buf)
|
if (not buf)
|
||||||
return;
|
return;
|
||||||
Window& win = ClientManager::instance().get_unused_window_for_buffer(*buf);
|
context.change_buffer(*buf);
|
||||||
win.selections() = SelectionList{cursor_pos};
|
context.selections() = SelectionList{cursor_pos};
|
||||||
win.set_position(view_pos);
|
context.window().set_position(view_pos);
|
||||||
context.change_editor(win);
|
|
||||||
context.print_status({ "'" + buf->display_name() + "' reloaded",
|
context.print_status({ "'" + buf->display_name() + "' reloaded",
|
||||||
get_color("Information") });
|
get_color("Information") });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#ifndef client_hh_INCLUDED
|
#ifndef client_hh_INCLUDED
|
||||||
#define client_hh_INCLUDED
|
#define client_hh_INCLUDED
|
||||||
|
|
||||||
#include "editor.hh"
|
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
#include "display_buffer.hh"
|
#include "display_buffer.hh"
|
||||||
|
@ -11,11 +10,14 @@ namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
class UserInterface;
|
class UserInterface;
|
||||||
|
class Window;
|
||||||
|
|
||||||
class Client : public SafeCountable
|
class Client : public SafeCountable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Client(std::unique_ptr<UserInterface>&& ui, Editor& editor, String name);
|
Client(std::unique_ptr<UserInterface>&& ui,
|
||||||
|
std::unique_ptr<Window>&& window,
|
||||||
|
SelectionList selections, String name);
|
||||||
~Client();
|
~Client();
|
||||||
|
|
||||||
// handle all the keys currently available in the user interface
|
// handle all the keys currently available in the user interface
|
||||||
|
@ -26,18 +28,22 @@ public:
|
||||||
void redraw_ifn();
|
void redraw_ifn();
|
||||||
|
|
||||||
UserInterface& ui() const { return *m_ui; }
|
UserInterface& ui() const { return *m_ui; }
|
||||||
|
Window& window() const { return *m_window; }
|
||||||
|
|
||||||
void check_buffer_fs_timestamp();
|
void check_buffer_fs_timestamp();
|
||||||
|
|
||||||
Context& context() { return m_input_handler.context(); }
|
Context& context() { return m_input_handler.context(); }
|
||||||
const Context& context() const { return m_input_handler.context(); }
|
const Context& context() const { return m_input_handler.context(); }
|
||||||
|
|
||||||
private:
|
void change_buffer(Buffer& buffer);
|
||||||
InputHandler m_input_handler;
|
|
||||||
|
|
||||||
|
private:
|
||||||
DisplayLine generate_mode_line() const;
|
DisplayLine generate_mode_line() const;
|
||||||
|
|
||||||
std::unique_ptr<UserInterface> m_ui;
|
std::unique_ptr<UserInterface> m_ui;
|
||||||
|
std::unique_ptr<Window> m_window;
|
||||||
|
|
||||||
|
InputHandler m_input_handler;
|
||||||
|
|
||||||
DisplayLine m_status_line;
|
DisplayLine m_status_line;
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,8 +28,9 @@ Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
|
||||||
const String& init_commands)
|
const String& init_commands)
|
||||||
{
|
{
|
||||||
Buffer& buffer = **BufferManager::instance().begin();
|
Buffer& buffer = **BufferManager::instance().begin();
|
||||||
Client* client = new Client{std::move(ui), get_unused_window_for_buffer(buffer),
|
WindowAndSelections ws = get_free_window(buffer);
|
||||||
generate_name()};
|
Client* client = new Client{std::move(ui), std::move(std::get<0>(ws)),
|
||||||
|
std::move(std::get<1>(ws)), generate_name()};
|
||||||
m_clients.emplace_back(client);
|
m_clients.emplace_back(client);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -80,24 +81,27 @@ void ClientManager::remove_client(Client& client)
|
||||||
kak_assert(false);
|
kak_assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Window& ClientManager::get_unused_window_for_buffer(Buffer& buffer)
|
WindowAndSelections ClientManager::get_free_window(Buffer& buffer)
|
||||||
{
|
{
|
||||||
for (auto& w : m_windows)
|
for (auto it = m_free_windows.begin(), end = m_free_windows.end();
|
||||||
|
it != end; ++it)
|
||||||
{
|
{
|
||||||
if (&w->buffer() != &buffer)
|
auto& w = std::get<0>(*it);
|
||||||
continue;
|
if (&w->buffer() == &buffer)
|
||||||
|
|
||||||
auto it = std::find_if(m_clients.begin(), m_clients.end(),
|
|
||||||
[&](const std::unique_ptr<Client>& client)
|
|
||||||
{ return &client->context().window() == w.get(); });
|
|
||||||
if (it == m_clients.end())
|
|
||||||
{
|
{
|
||||||
w->forget_timestamp();
|
w->forget_timestamp();
|
||||||
return *w;
|
WindowAndSelections res = std::move(*it);
|
||||||
|
m_free_windows.erase(it);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_windows.emplace_back(new Window(buffer));
|
return WindowAndSelections{ std::unique_ptr<Window>{new Window{buffer}}, DynamicSelectionList{buffer, { Selection{ {}, {} } } } };
|
||||||
return *m_windows.back();
|
}
|
||||||
|
|
||||||
|
void ClientManager::add_free_window(std::unique_ptr<Window>&& window, SelectionList selections)
|
||||||
|
{
|
||||||
|
Buffer& buffer = window->buffer();
|
||||||
|
m_free_windows.emplace_back(std::move(window), DynamicSelectionList{ buffer, std::move(selections) });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)
|
void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)
|
||||||
|
@ -120,16 +124,15 @@ void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)
|
||||||
{
|
{
|
||||||
if (buf != &buffer)
|
if (buf != &buffer)
|
||||||
{
|
{
|
||||||
Window& w = get_unused_window_for_buffer(*buf);
|
client->context().change_buffer(*buf);
|
||||||
client->context().change_editor(w);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto end = std::remove_if(m_windows.begin(), m_windows.end(),
|
auto end = std::remove_if(m_free_windows.begin(), m_free_windows.end(),
|
||||||
[&buffer](const std::unique_ptr<Window>& w)
|
[&buffer](const WindowAndSelections& ws)
|
||||||
{ return &w->buffer() == &buffer; });
|
{ return &std::get<0>(ws)->buffer() == &buffer; });
|
||||||
m_windows.erase(end, m_windows.end());
|
m_free_windows.erase(end, m_free_windows.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientManager::validate_client_name(const String& name) const
|
bool ClientManager::validate_client_name(const String& name) const
|
||||||
|
|
|
@ -8,6 +8,9 @@ namespace Kakoune
|
||||||
|
|
||||||
struct client_removed{};
|
struct client_removed{};
|
||||||
|
|
||||||
|
using WindowAndSelections = std::tuple<std::unique_ptr<Window>,
|
||||||
|
DynamicSelectionList>;
|
||||||
|
|
||||||
class ClientManager : public Singleton<ClientManager>
|
class ClientManager : public Singleton<ClientManager>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -20,9 +23,11 @@ public:
|
||||||
bool empty() const { return m_clients.empty(); }
|
bool empty() const { return m_clients.empty(); }
|
||||||
size_t count() const { return m_clients.size(); }
|
size_t count() const { return m_clients.size(); }
|
||||||
|
|
||||||
Window& get_unused_window_for_buffer(Buffer& buffer);
|
|
||||||
void ensure_no_client_uses_buffer(Buffer& buffer);
|
void ensure_no_client_uses_buffer(Buffer& buffer);
|
||||||
|
|
||||||
|
WindowAndSelections get_free_window(Buffer& buffer);
|
||||||
|
void add_free_window(std::unique_ptr<Window>&& window, SelectionList selections);
|
||||||
|
|
||||||
void redraw_clients() const;
|
void redraw_clients() const;
|
||||||
|
|
||||||
Client* get_client_ifp(const String& name);
|
Client* get_client_ifp(const String& name);
|
||||||
|
@ -34,7 +39,7 @@ private:
|
||||||
String generate_name() const;
|
String generate_name() const;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Client>> m_clients;
|
std::vector<std::unique_ptr<Client>> m_clients;
|
||||||
std::vector<std::unique_ptr<Window>> m_windows;
|
std::vector<WindowAndSelections> m_free_windows;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,10 +116,7 @@ void edit(CommandParameters params, Context& context)
|
||||||
context.push_jump();
|
context.push_jump();
|
||||||
|
|
||||||
if (buffer != &context.buffer())
|
if (buffer != &context.buffer())
|
||||||
{
|
context.change_buffer(*buffer);
|
||||||
auto& manager = ClientManager::instance();
|
|
||||||
context.change_editor(manager.get_unused_window_for_buffer(*buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param_count > 1 and not parser[1].empty())
|
if (param_count > 1 and not parser[1].empty())
|
||||||
{
|
{
|
||||||
|
@ -210,8 +207,7 @@ void show_buffer(CommandParameters params, Context& context)
|
||||||
if (&buffer != &context.buffer())
|
if (&buffer != &context.buffer())
|
||||||
{
|
{
|
||||||
context.push_jump();
|
context.push_jump();
|
||||||
auto& manager = ClientManager::instance();
|
context.change_buffer(buffer);
|
||||||
context.change_editor(manager.get_unused_window_for_buffer(buffer));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,9 +564,7 @@ void context_wrap(CommandParameters params, Context& context, Func func)
|
||||||
|
|
||||||
if (parser.has_option("draft"))
|
if (parser.has_option("draft"))
|
||||||
{
|
{
|
||||||
InputHandler input_handler(real_context->editor(), real_context->name());
|
InputHandler input_handler(real_context->buffer(), real_context->selections(), real_context->name());
|
||||||
DynamicSelectionList sels{real_context->buffer(), real_context->selections()};
|
|
||||||
auto restore_sels = on_scope_end([&]{ real_context->selections() = std::move(sels); });
|
|
||||||
|
|
||||||
// We do not want this draft context to commit undo groups if the real one is
|
// We do not want this draft context to commit undo groups if the real one is
|
||||||
// going to commit the whole thing later
|
// going to commit the whole thing later
|
||||||
|
@ -579,6 +573,7 @@ void context_wrap(CommandParameters params, Context& context, Func func)
|
||||||
|
|
||||||
if (parser.has_option("itersel"))
|
if (parser.has_option("itersel"))
|
||||||
{
|
{
|
||||||
|
DynamicSelectionList sels{real_context->buffer(), real_context->selections()};
|
||||||
for (auto& sel : sels)
|
for (auto& sel : sels)
|
||||||
{
|
{
|
||||||
input_handler.context().selections() = sel;
|
input_handler.context().selections() = sel;
|
||||||
|
|
|
@ -8,41 +8,24 @@ namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
Context::Context() = default;
|
Context::Context() = default;
|
||||||
|
|
||||||
Context::Context(InputHandler& input_handler, Editor& editor, String name)
|
|
||||||
: m_input_handler(&input_handler), m_editor(&editor),
|
|
||||||
m_name(std::move(name)) {}
|
|
||||||
|
|
||||||
Context::Context(Editor& editor, String name)
|
|
||||||
: m_editor(&editor),
|
|
||||||
m_name(std::move(name)) {}
|
|
||||||
|
|
||||||
Context::~Context() = default;
|
Context::~Context() = default;
|
||||||
|
|
||||||
|
Context::Context(InputHandler& input_handler, Buffer& buffer, SelectionList selections, String name)
|
||||||
|
: m_input_handler{&input_handler}, m_selections{{buffer, std::move(selections)}},
|
||||||
|
m_name(std::move(name)) {}
|
||||||
|
|
||||||
Buffer& Context::buffer() const
|
Buffer& Context::buffer() const
|
||||||
{
|
{
|
||||||
if (not has_buffer())
|
if (not has_buffer())
|
||||||
throw runtime_error("no buffer in context");
|
throw runtime_error("no buffer in context");
|
||||||
return m_editor->buffer();
|
return (*m_selections).registry();
|
||||||
}
|
|
||||||
|
|
||||||
Editor& Context::editor() const
|
|
||||||
{
|
|
||||||
if (not has_editor())
|
|
||||||
throw runtime_error("no editor in context");
|
|
||||||
return *m_editor.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window& Context::window() const
|
Window& Context::window() const
|
||||||
{
|
{
|
||||||
if (not has_window())
|
if (not has_window())
|
||||||
throw runtime_error("no window in context");
|
throw runtime_error("no window in context");
|
||||||
return *dynamic_cast<Window*>(m_editor.get());
|
return *m_window;
|
||||||
}
|
|
||||||
|
|
||||||
bool Context::has_window() const
|
|
||||||
{
|
|
||||||
return (bool)m_editor and dynamic_cast<Window*>(m_editor.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputHandler& Context::input_handler() const
|
InputHandler& Context::input_handler() const
|
||||||
|
@ -99,6 +82,12 @@ void Context::set_client(Client& client)
|
||||||
m_client.reset(&client);
|
m_client.reset(&client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::set_window(Window& window)
|
||||||
|
{
|
||||||
|
kak_assert(&window.buffer() == &buffer());
|
||||||
|
m_window.reset(&window);
|
||||||
|
}
|
||||||
|
|
||||||
void Context::print_status(DisplayLine status) const
|
void Context::print_status(DisplayLine status) const
|
||||||
{
|
{
|
||||||
if (has_client())
|
if (has_client())
|
||||||
|
@ -111,14 +100,14 @@ void Context::push_jump()
|
||||||
if (m_current_jump != m_jump_list.end())
|
if (m_current_jump != m_jump_list.end())
|
||||||
{
|
{
|
||||||
auto begin = m_current_jump;
|
auto begin = m_current_jump;
|
||||||
if (&editor().buffer() != &begin->buffer() or
|
if (&buffer() != &begin->buffer() or
|
||||||
(const SelectionList&)(*begin) != jump)
|
(const SelectionList&)(*begin) != jump)
|
||||||
++begin;
|
++begin;
|
||||||
m_jump_list.erase(begin, m_jump_list.end());
|
m_jump_list.erase(begin, m_jump_list.end());
|
||||||
}
|
}
|
||||||
m_jump_list.erase(std::remove(begin(m_jump_list), end(m_jump_list), jump),
|
m_jump_list.erase(std::remove(begin(m_jump_list), end(m_jump_list), jump),
|
||||||
end(m_jump_list));
|
end(m_jump_list));
|
||||||
m_jump_list.push_back({editor().buffer(), jump});
|
m_jump_list.push_back({buffer(), jump});
|
||||||
m_current_jump = m_jump_list.end();
|
m_current_jump = m_jump_list.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,27 +157,29 @@ void Context::forget_jumps_to_buffer(Buffer& buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::change_editor(Editor& editor)
|
void Context::change_buffer(Buffer& buffer)
|
||||||
{
|
{
|
||||||
m_editor.reset(&editor);
|
m_window.reset();
|
||||||
if (has_window())
|
if (has_client())
|
||||||
{
|
client().change_buffer(buffer);
|
||||||
if (has_ui())
|
else
|
||||||
window().set_dimensions(ui().dimensions());
|
m_selections = DynamicSelectionList{ buffer };
|
||||||
window().hooks().run_hook("WinDisplay", buffer().name(), *this);
|
|
||||||
}
|
|
||||||
if (has_input_handler())
|
if (has_input_handler())
|
||||||
input_handler().reset_normal_mode();
|
input_handler().reset_normal_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionList& Context::selections()
|
SelectionList& Context::selections()
|
||||||
{
|
{
|
||||||
return editor().selections();
|
if (not m_selections)
|
||||||
|
throw runtime_error("no selections in context");
|
||||||
|
return *m_selections;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SelectionList& Context::selections() const
|
const SelectionList& Context::selections() const
|
||||||
{
|
{
|
||||||
return editor().selections();
|
if (not m_selections)
|
||||||
|
throw runtime_error("no selections in context");
|
||||||
|
return *m_selections;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<String> Context::selections_content() const
|
std::vector<String> Context::selections_content() const
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "dynamic_selection_list.hh"
|
#include "dynamic_selection_list.hh"
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -25,21 +27,17 @@ class Context
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Context();
|
Context();
|
||||||
Context(InputHandler& input_handler, Editor& editor, String name = "");
|
Context(InputHandler& input_handler, Buffer& buffer, SelectionList selections, String name = "");
|
||||||
Context(Editor& editor, String name = "");
|
|
||||||
~Context();
|
~Context();
|
||||||
|
|
||||||
Context(const Context&) = delete;
|
Context(const Context&) = delete;
|
||||||
Context& operator=(const Context&) = delete;
|
Context& operator=(const Context&) = delete;
|
||||||
|
|
||||||
Buffer& buffer() const;
|
Buffer& buffer() const;
|
||||||
bool has_buffer() const { return (bool)m_editor; }
|
bool has_buffer() const { return m_selections; }
|
||||||
|
|
||||||
Editor& editor() const;
|
|
||||||
bool has_editor() const { return (bool)m_editor; }
|
|
||||||
|
|
||||||
Window& window() const;
|
Window& window() const;
|
||||||
bool has_window() const;
|
bool has_window() const { return (bool)m_window; }
|
||||||
|
|
||||||
Client& client() const;
|
Client& client() const;
|
||||||
bool has_client() const { return (bool)m_client; }
|
bool has_client() const { return (bool)m_client; }
|
||||||
|
@ -54,9 +52,10 @@ public:
|
||||||
const SelectionList& selections() const;
|
const SelectionList& selections() const;
|
||||||
std::vector<String> selections_content() const;
|
std::vector<String> selections_content() const;
|
||||||
|
|
||||||
void change_editor(Editor& editor);
|
void change_buffer(Buffer& buffer);
|
||||||
|
|
||||||
void set_client(Client& client);
|
void set_client(Client& client);
|
||||||
|
void set_window(Window& window);
|
||||||
|
|
||||||
OptionManager& options() const;
|
OptionManager& options() const;
|
||||||
HookManager& hooks() const;
|
HookManager& hooks() const;
|
||||||
|
@ -81,10 +80,13 @@ private:
|
||||||
|
|
||||||
friend struct ScopedEdition;
|
friend struct ScopedEdition;
|
||||||
|
|
||||||
safe_ptr<Editor> m_editor;
|
|
||||||
safe_ptr<InputHandler> m_input_handler;
|
safe_ptr<InputHandler> m_input_handler;
|
||||||
|
safe_ptr<Window> m_window;
|
||||||
safe_ptr<Client> m_client;
|
safe_ptr<Client> m_client;
|
||||||
|
|
||||||
|
friend class Client;
|
||||||
|
boost::optional<DynamicSelectionList> m_selections;
|
||||||
|
|
||||||
String m_name;
|
String m_name;
|
||||||
|
|
||||||
using JumpList = std::vector<DynamicSelectionList>;
|
using JumpList = std::vector<DynamicSelectionList>;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "debug.hh"
|
#include "debug.hh"
|
||||||
|
|
||||||
#include "assert.hh"
|
#include "assert.hh"
|
||||||
|
#include "buffer.hh"
|
||||||
#include "buffer_manager.hh"
|
#include "buffer_manager.hh"
|
||||||
#include "editor.hh"
|
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
DynamicSelectionList::DynamicSelectionList(const Buffer& buffer,
|
DynamicSelectionList::DynamicSelectionList(Buffer& buffer,
|
||||||
SelectionList selections)
|
SelectionList selections)
|
||||||
: SelectionList(std::move(selections)),
|
: SelectionList(std::move(selections)),
|
||||||
BufferChangeListener_AutoRegister(buffer)
|
BufferChangeListener_AutoRegister(buffer)
|
||||||
|
|
|
@ -13,7 +13,7 @@ public:
|
||||||
using iterator = SelectionList::iterator;
|
using iterator = SelectionList::iterator;
|
||||||
using const_iterator = SelectionList::const_iterator;
|
using const_iterator = SelectionList::const_iterator;
|
||||||
|
|
||||||
DynamicSelectionList(const Buffer& buffer, SelectionList selections = {});
|
DynamicSelectionList(Buffer& buffer, SelectionList selections = {});
|
||||||
|
|
||||||
DynamicSelectionList& operator=(SelectionList selections);
|
DynamicSelectionList& operator=(SelectionList selections);
|
||||||
void check_invariant() const;
|
void check_invariant() const;
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
#ifndef editor_hh_INCLUDED
|
|
||||||
#define editor_hh_INCLUDED
|
|
||||||
|
|
||||||
#include "buffer.hh"
|
|
||||||
#include "dynamic_selection_list.hh"
|
|
||||||
#include "memoryview.hh"
|
|
||||||
|
|
||||||
namespace Kakoune
|
|
||||||
{
|
|
||||||
|
|
||||||
// An Editor is a to be removed class from the past
|
|
||||||
class Editor : public SafeCountable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Editor(Buffer& buffer)
|
|
||||||
: m_buffer(&buffer),
|
|
||||||
m_selections(buffer, {BufferCoord{}})
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual ~Editor() {}
|
|
||||||
|
|
||||||
Buffer& buffer() const { return *m_buffer; }
|
|
||||||
|
|
||||||
const SelectionList& selections() const { return m_selections; }
|
|
||||||
SelectionList& selections() { return m_selections; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
safe_ptr<Buffer> m_buffer;
|
|
||||||
DynamicSelectionList m_selections;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // editor_hh_INCLUDED
|
|
||||||
|
|
|
@ -995,7 +995,7 @@ private:
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void move(Type offset)
|
void move(Type offset)
|
||||||
{
|
{
|
||||||
auto& selections = context().editor().selections();
|
auto& selections = context().selections();
|
||||||
for (auto& sel : selections)
|
for (auto& sel : selections)
|
||||||
{
|
{
|
||||||
auto last = context().has_window() ? context().window().offset_coord(sel.last(), offset)
|
auto last = context().has_window() ? context().window().offset_coord(sel.last(), offset)
|
||||||
|
@ -1125,9 +1125,9 @@ void InputMode::reset_normal_mode()
|
||||||
m_input_handler.reset_normal_mode();
|
m_input_handler.reset_normal_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
InputHandler::InputHandler(Editor& editor, String name)
|
InputHandler::InputHandler(Buffer& buffer, SelectionList selections, String name)
|
||||||
: m_mode(new InputModes::Normal(*this)),
|
: m_mode(new InputModes::Normal(*this)),
|
||||||
m_context(*this, editor, std::move(name))
|
m_context(*this, buffer, std::move(selections), std::move(name))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ enum class InsertMode : unsigned;
|
||||||
class InputHandler : public SafeCountable
|
class InputHandler : public SafeCountable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InputHandler(Editor& editor, String name = "");
|
InputHandler(Buffer& buffer, SelectionList selections, String name = "");
|
||||||
~InputHandler();
|
~InputHandler();
|
||||||
|
|
||||||
// switch to insert mode
|
// switch to insert mode
|
||||||
|
|
|
@ -285,8 +285,7 @@ void goto_commands(Context& context, int line)
|
||||||
if (it->get() == &buffer and ++it == buffer_manager.end())
|
if (it->get() == &buffer and ++it == buffer_manager.end())
|
||||||
break;
|
break;
|
||||||
context.push_jump();
|
context.push_jump();
|
||||||
auto& client_manager = ClientManager::instance();
|
context.change_buffer(**it);
|
||||||
context.change_editor(client_manager.get_unused_window_for_buffer(**it));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'f':
|
case 'f':
|
||||||
|
@ -894,7 +893,7 @@ void scroll(Context& context, int)
|
||||||
auto cursor_pos = utf8::advance(buffer.iterator_at(position.line),
|
auto cursor_pos = utf8::advance(buffer.iterator_at(position.line),
|
||||||
buffer.iterator_at(position.line+1),
|
buffer.iterator_at(position.line+1),
|
||||||
position.column);
|
position.column);
|
||||||
select_coord(buffer, cursor_pos.coord(), window.selections());
|
select_coord(buffer, cursor_pos.coord(), context.selections());
|
||||||
window.set_position(position);
|
window.set_position(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,10 +984,7 @@ void jump(Context& context, int)
|
||||||
Buffer& buffer = const_cast<Buffer&>(jump.buffer());
|
Buffer& buffer = const_cast<Buffer&>(jump.buffer());
|
||||||
BufferManager::instance().set_last_used_buffer(buffer);
|
BufferManager::instance().set_last_used_buffer(buffer);
|
||||||
if (&buffer != &context.buffer())
|
if (&buffer != &context.buffer())
|
||||||
{
|
context.change_buffer(buffer);
|
||||||
auto& manager = ClientManager::instance();
|
|
||||||
context.change_editor(manager.get_unused_window_for_buffer(buffer));
|
|
||||||
}
|
|
||||||
context.selections() = jump;
|
context.selections() = jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "selection.hh"
|
#include "selection.hh"
|
||||||
#include "unicode.hh"
|
#include "unicode.hh"
|
||||||
#include "editor.hh"
|
|
||||||
#include "utf8_iterator.hh"
|
#include "utf8_iterator.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "assert.hh"
|
#include "assert.hh"
|
||||||
#include "buffer.hh"
|
#include "buffer.hh"
|
||||||
#include "editor.hh"
|
|
||||||
#include "keys.hh"
|
#include "keys.hh"
|
||||||
#include "selectors.hh"
|
#include "selectors.hh"
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(T* ptr)
|
void reset(T* ptr = nullptr)
|
||||||
{
|
{
|
||||||
*this = safe_ptr(ptr);
|
*this = safe_ptr(ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,13 @@ void expand_tabulations(const Context& context, DisplayBuffer& display_buffer);
|
||||||
void expand_unprintable(const Context& context, DisplayBuffer& display_buffer);
|
void expand_unprintable(const Context& context, DisplayBuffer& display_buffer);
|
||||||
|
|
||||||
Window::Window(Buffer& buffer)
|
Window::Window(Buffer& buffer)
|
||||||
: Editor(buffer),
|
: m_buffer(&buffer),
|
||||||
m_hooks(buffer.hooks()),
|
m_hooks(buffer.hooks()),
|
||||||
m_options(buffer.options()),
|
m_options(buffer.options()),
|
||||||
m_keymaps(buffer.keymaps())
|
m_keymaps(buffer.keymaps())
|
||||||
{
|
{
|
||||||
InputHandler hook_handler{*this};
|
InputHandler hook_handler{*m_buffer, SelectionList{ {} } };
|
||||||
|
hook_handler.context().set_window(*this);
|
||||||
m_hooks.run_hook("WinCreate", buffer.name(), hook_handler.context());
|
m_hooks.run_hook("WinCreate", buffer.name(), hook_handler.context());
|
||||||
m_options.register_watcher(*this);
|
m_options.register_watcher(*this);
|
||||||
|
|
||||||
|
@ -37,7 +38,8 @@ Window::Window(Buffer& buffer)
|
||||||
|
|
||||||
Window::~Window()
|
Window::~Window()
|
||||||
{
|
{
|
||||||
InputHandler hook_handler{*this};
|
InputHandler hook_handler{*m_buffer, SelectionList{ {} } };
|
||||||
|
hook_handler.context().set_window(*this);
|
||||||
m_hooks.run_hook("WinClose", buffer().name(), hook_handler.context());
|
m_hooks.run_hook("WinClose", buffer().name(), hook_handler.context());
|
||||||
m_options.unregister_watcher(*this);
|
m_options.unregister_watcher(*this);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +68,7 @@ void Window::scroll(CharCount offset)
|
||||||
void Window::update_display_buffer(const Context& context)
|
void Window::update_display_buffer(const Context& context)
|
||||||
{
|
{
|
||||||
kak_assert(&buffer() == &context.buffer());
|
kak_assert(&buffer() == &context.buffer());
|
||||||
scroll_to_keep_selection_visible_ifn(context.selections().main());
|
scroll_to_keep_selection_visible_ifn(context);
|
||||||
|
|
||||||
DisplayBuffer::LineList& lines = m_display_buffer.lines();
|
DisplayBuffer::LineList& lines = m_display_buffer.lines();
|
||||||
lines.clear();
|
lines.clear();
|
||||||
|
@ -143,8 +145,9 @@ static CharCount adapt_view_pos(const DisplayBuffer& display_buffer,
|
||||||
return view_pos;
|
return view_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::scroll_to_keep_selection_visible_ifn(const Range& selection)
|
void Window::scroll_to_keep_selection_visible_ifn(const Context& context)
|
||||||
{
|
{
|
||||||
|
auto& selection = context.selections().main();
|
||||||
const auto& first = selection.first();
|
const auto& first = selection.first();
|
||||||
const auto& last = selection.last();
|
const auto& last = selection.last();
|
||||||
|
|
||||||
|
@ -163,8 +166,8 @@ void Window::scroll_to_keep_selection_visible_ifn(const Range& selection)
|
||||||
lines.emplace_back(AtomList{ {buffer(), last.line, last.line+1} });
|
lines.emplace_back(AtomList{ {buffer(), last.line, last.line+1} });
|
||||||
|
|
||||||
display_buffer.compute_range();
|
display_buffer.compute_range();
|
||||||
m_highlighters(*this, display_buffer);
|
m_highlighters(context, display_buffer);
|
||||||
m_builtin_highlighters(*this, display_buffer);
|
m_builtin_highlighters(context, display_buffer);
|
||||||
|
|
||||||
// now we can compute where the cursor is in display columns
|
// now we can compute where the cursor is in display columns
|
||||||
// (this is only valid if highlighting one line and multiple lines put
|
// (this is only valid if highlighting one line and multiple lines put
|
||||||
|
@ -245,9 +248,10 @@ BufferCoord Window::offset_coord(BufferCoord coord, LineCount offset)
|
||||||
lines.emplace_back(AtomList{ {buffer(), line, line+1} });
|
lines.emplace_back(AtomList{ {buffer(), line, line+1} });
|
||||||
display_buffer.compute_range();
|
display_buffer.compute_range();
|
||||||
|
|
||||||
Context context(*this);
|
InputHandler hook_handler{*m_buffer, SelectionList{ {} } };
|
||||||
m_highlighters(*this, display_buffer);
|
hook_handler.context().set_window(*this);
|
||||||
m_builtin_highlighters(*this, display_buffer);
|
m_highlighters(hook_handler.context(), display_buffer);
|
||||||
|
m_builtin_highlighters(hook_handler.context(), display_buffer);
|
||||||
|
|
||||||
CharCount column = find_display_column(lines[0], buffer(), coord);
|
CharCount column = find_display_column(lines[0], buffer(), coord);
|
||||||
return find_buffer_coord(lines[1], buffer(), column);
|
return find_buffer_coord(lines[1], buffer(), column);
|
||||||
|
@ -256,7 +260,8 @@ BufferCoord Window::offset_coord(BufferCoord coord, LineCount offset)
|
||||||
void Window::on_option_changed(const Option& option)
|
void Window::on_option_changed(const Option& option)
|
||||||
{
|
{
|
||||||
String desc = option.name() + "=" + option.get_as_string();
|
String desc = option.name() + "=" + option.get_as_string();
|
||||||
InputHandler hook_handler{*this};
|
InputHandler hook_handler{*m_buffer, SelectionList{ {} } };
|
||||||
|
hook_handler.context().set_window(*this);
|
||||||
m_hooks.run_hook("WinSetOption", desc, hook_handler.context());
|
m_hooks.run_hook("WinSetOption", desc, hook_handler.context());
|
||||||
|
|
||||||
// an highlighter might depend on the option, so we need to redraw
|
// an highlighter might depend on the option, so we need to redraw
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
|
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
#include "display_buffer.hh"
|
#include "display_buffer.hh"
|
||||||
#include "editor.hh"
|
|
||||||
#include "highlighter.hh"
|
|
||||||
#include "highlighter.hh"
|
#include "highlighter.hh"
|
||||||
|
#include "selection.hh"
|
||||||
#include "hook_manager.hh"
|
#include "hook_manager.hh"
|
||||||
#include "option_manager.hh"
|
#include "option_manager.hh"
|
||||||
#include "keymap_manager.hh"
|
#include "keymap_manager.hh"
|
||||||
|
@ -13,13 +12,8 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
// A Window is an editing view onto a Buffer
|
// A Window is a view onto a Buffer
|
||||||
//
|
class Window : public SafeCountable, public OptionManagerWatcher
|
||||||
// The Window class is an interactive Editor adding display functionalities
|
|
||||||
// to the editing ones already provided by the Editor class.
|
|
||||||
// Display can be customized through the use of highlighters handled by
|
|
||||||
// the window's HighlighterGroup
|
|
||||||
class Window : public Editor, public OptionManagerWatcher
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Window(Buffer& buffer);
|
Window(Buffer& buffer);
|
||||||
|
@ -50,6 +44,8 @@ public:
|
||||||
KeymapManager& keymaps() { return m_keymaps; }
|
KeymapManager& keymaps() { return m_keymaps; }
|
||||||
const KeymapManager& keymaps() const { return m_keymaps; }
|
const KeymapManager& keymaps() const { return m_keymaps; }
|
||||||
|
|
||||||
|
Buffer& buffer() const { return *m_buffer; }
|
||||||
|
|
||||||
size_t timestamp() const { return m_timestamp; }
|
size_t timestamp() const { return m_timestamp; }
|
||||||
void forget_timestamp() { m_timestamp = -1; }
|
void forget_timestamp() { m_timestamp = -1; }
|
||||||
|
|
||||||
|
@ -59,8 +55,9 @@ private:
|
||||||
Window(const Window&) = delete;
|
Window(const Window&) = delete;
|
||||||
|
|
||||||
void on_option_changed(const Option& option) override;
|
void on_option_changed(const Option& option) override;
|
||||||
|
void scroll_to_keep_selection_visible_ifn(const Context& context);
|
||||||
|
|
||||||
void scroll_to_keep_selection_visible_ifn(const Range& selection);
|
safe_ptr<Buffer> m_buffer;
|
||||||
|
|
||||||
DisplayCoord m_position;
|
DisplayCoord m_position;
|
||||||
DisplayCoord m_dimensions;
|
DisplayCoord m_dimensions;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user