summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2020-07-19 12:56:55 +1000
committerMaxime Coste <mawww@kakoune.org>2020-07-19 12:56:55 +1000
commit47ba36c66e0e38c5bb5c832bfa751d553f769baa (patch)
treec44b20b3d7440374eefc9ff5cbc08352c8f73809 /src
parent5df8073c3c4213075d1c0ee6267cc58848b86721 (diff)
Add a RegisterModified hook
This one has been a long time coming, I am still concerned this could impact performance a lot. This hook does *not* trigger for capture registers (0-9) or any other dynamic registers (that are not writable). Fixes #859
Diffstat (limited to 'src')
-rw-r--r--src/hook_manager.hh2
-rw-r--r--src/main.cc12
-rw-r--r--src/register_manager.cc47
-rw-r--r--src/register_manager.hh59
4 files changed, 71 insertions, 49 deletions
diff --git a/src/hook_manager.hh b/src/hook_manager.hh
index a6547fa0..4b8a8913 100644
--- a/src/hook_manager.hh
+++ b/src/hook_manager.hh
@@ -49,6 +49,7 @@ enum class Hook
NormalKey,
ModeChange,
RawKey,
+ RegisterModified,
WinClose,
WinCreate,
WinDisplay,
@@ -93,6 +94,7 @@ constexpr auto enum_desc(Meta::Type<Hook>)
{Hook::NormalKey, "NormalKey"},
{Hook::ModeChange, "ModeChange"},
{Hook::RawKey, "RawKey"},
+ {Hook::RegisterModified, "RegisterModified"},
{Hook::WinClose, "WinClose"},
{Hook::WinCreate, "WinCreate"},
{Hook::WinDisplay, "WinDisplay"},
diff --git a/src/main.cc b/src/main.cc
index 63fea291..9385214f 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -350,25 +350,28 @@ void register_registers()
{
RegisterManager& register_manager = RegisterManager::instance();
- for (auto c : StringView{"abcdefghijklmnopqrstuvwxyz\"^@"})
- register_manager.add_register(c, std::make_unique<StaticRegister>());
+ for (Codepoint c : StringView{"abcdefghijklmnopqrstuvwxyz\"^@"})
+ register_manager.add_register(c, std::make_unique<StaticRegister>(String{c}));
- for (auto c : StringView{"/|:\\"})
- register_manager.add_register(c, std::make_unique<HistoryRegister>());
+ for (Codepoint c : StringView{"/|:\\"})
+ register_manager.add_register(c, std::make_unique<HistoryRegister>(String{c}));
using StringList = Vector<String, MemoryDomain::Registers>;
register_manager.add_register('%', make_dyn_reg(
+ "%",
[](const Context& context)
{ return StringList{{context.buffer().display_name()}}; }));
register_manager.add_register('.', make_dyn_reg(
+ ".",
[](const Context& context) {
auto content = context.selections_content();
return StringList{content.begin(), content.end()};
}));
register_manager.add_register('#', make_dyn_reg(
+ "#",
[](const Context& context) {
const size_t count = context.selections().size();
StringList res;
@@ -381,6 +384,7 @@ void register_registers()
for (size_t i = 0; i < 10; ++i)
{
register_manager.add_register('0'+i, make_dyn_reg(
+ String{Codepoint('0'+i)},
[i](const Context& context) {
StringList result;
for (auto& sel : context.selections())
diff --git a/src/register_manager.cc b/src/register_manager.cc
index 37c93628..65f9a7ce 100644
--- a/src/register_manager.cc
+++ b/src/register_manager.cc
@@ -1,12 +1,59 @@
#include "register_manager.hh"
#include "assert.hh"
+#include "context.hh"
#include "hash_map.hh"
#include "string_utils.hh"
namespace Kakoune
{
+void StaticRegister::set(Context& context, ConstArrayView<String> values, bool)
+{
+ m_content.assign(values.begin(), values.end());
+ context.hooks().run_hook(Hook::RegisterModified, m_name, context);
+}
+
+ConstArrayView<String> StaticRegister::get(const Context&)
+{
+ if (m_content.empty())
+ return ConstArrayView<String>(String::ms_empty);
+ else
+ return ConstArrayView<String>(m_content);
+}
+
+const String& StaticRegister::get_main(const Context& context, size_t main_index)
+{
+ auto content = get(context);
+ return content[std::min(main_index, content.size() - 1)];
+}
+
+void HistoryRegister::set(Context& context, ConstArrayView<String> values, bool restoring)
+{
+ constexpr size_t size_limit = 100;
+
+ if (restoring)
+ return StaticRegister::set(context, values, true);
+
+ for (auto& entry : values)
+ {
+ m_content.erase(std::remove(m_content.begin(), m_content.end(), entry),
+ m_content.end());
+ m_content.push_back(entry);
+ }
+
+ const size_t current_size = m_content.size();
+ if (current_size > size_limit)
+ m_content.erase(m_content.begin(), m_content.begin() + (current_size - size_limit));
+
+ context.hooks().run_hook(Hook::RegisterModified, m_name, context);
+}
+
+const String& HistoryRegister::get_main(const Context&, size_t)
+{
+ return m_content.empty() ? String::ms_empty : m_content.back();
+}
+
static const HashMap<String, Codepoint> reg_names = {
{ "slash", '/' },
{ "dquote", '"' },
diff --git a/src/register_manager.hh b/src/register_manager.hh
index d82849c3..732d3449 100644
--- a/src/register_manager.hh
+++ b/src/register_manager.hh
@@ -33,26 +33,14 @@ public:
class StaticRegister : public Register
{
public:
- void set(Context&, ConstArrayView<String> values, bool) override
- {
- m_content.assign(values.begin(), values.end());
- }
-
- ConstArrayView<String> get(const Context&) override
- {
- if (m_content.empty())
- return ConstArrayView<String>(String::ms_empty);
- else
- return ConstArrayView<String>(m_content);
- }
+ StaticRegister(String name) : m_name{std::move(name)} {}
- const String& get_main(const Context& context, size_t main_index) override
- {
- auto content = get(context);
- return content[std::min(main_index, content.size() - 1)];
- }
+ void set(Context& context, ConstArrayView<String> values, bool) override;
+ ConstArrayView<String> get(const Context&) override;
+ const String& get_main(const Context& context, size_t main_index) override;
protected:
+ String m_name;
Vector<String, MemoryDomain::Registers> m_content;
};
@@ -62,8 +50,8 @@ template<typename Getter, typename Setter>
class DynamicRegister : public StaticRegister
{
public:
- DynamicRegister(Getter getter, Setter setter)
- : m_getter(std::move(getter)), m_setter(std::move(setter)) {}
+ DynamicRegister(String name, Getter getter, Setter setter)
+ : StaticRegister(std::move(name)), m_getter(std::move(getter)), m_setter(std::move(setter)) {}
void set(Context& context, ConstArrayView<String> values, bool) override
{
@@ -85,45 +73,26 @@ private:
class HistoryRegister : public StaticRegister
{
public:
- void set(Context& context, ConstArrayView<String> values, bool restoring) override
- {
- constexpr size_t size_limit = 100;
-
- if (restoring)
- return StaticRegister::set(context, values, true);
-
- for (auto& entry : values)
- {
- m_content.erase(std::remove(m_content.begin(), m_content.end(), entry),
- m_content.end());
- m_content.push_back(entry);
- }
-
- const size_t current_size = m_content.size();
- if (current_size > size_limit)
- m_content.erase(m_content.begin(), m_content.begin() + (current_size - size_limit));
- }
+ using StaticRegister::StaticRegister;
- const String& get_main(const Context&, size_t) override
- {
- return m_content.empty() ? String::ms_empty : m_content.back();
- }
+ void set(Context& context, ConstArrayView<String> values, bool restoring) override;
+ const String& get_main(const Context&, size_t) override;
};
template<typename Func>
-std::unique_ptr<Register> make_dyn_reg(Func func)
+std::unique_ptr<Register> make_dyn_reg(String name, Func func)
{
auto setter = [](Context&, ConstArrayView<String>)
{
throw runtime_error("this register is not assignable");
};
- return std::make_unique<DynamicRegister<Func, decltype(setter)>>(std::move(func), setter);
+ return std::make_unique<DynamicRegister<Func, decltype(setter)>>(name, std::move(func), setter);
}
template<typename Getter, typename Setter>
-std::unique_ptr<Register> make_dyn_reg(Getter getter, Setter setter)
+std::unique_ptr<Register> make_dyn_reg(String name, Getter getter, Setter setter)
{
- return std::make_unique<DynamicRegister<Getter, Setter>>(std::move(getter), std::move(setter));
+ return std::make_unique<DynamicRegister<Getter, Setter>>(name, std::move(getter), std::move(setter));
}
class NullRegister : public Register