diff --git a/src/main.cc b/src/main.cc index 7242ff96..e3b0098e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -147,6 +147,11 @@ void register_env_vars() void register_registers() { + RegisterManager& register_manager = RegisterManager::instance(); + + for (auto c : "abcdefghijklmnopqrstuvwxyz/\"|^@") + register_manager.add_register(c, make_unique()); + using StringList = Vector; static const struct { char name; @@ -165,20 +170,21 @@ void register_registers() } } }; - RegisterManager& register_manager = RegisterManager::instance(); for (auto& dyn_reg : dyn_regs) - register_manager.register_dynamic_register(dyn_reg.name, dyn_reg.func); + register_manager.add_register(dyn_reg.name, make_unique(dyn_reg.func)); for (size_t i = 0; i < 10; ++i) { - register_manager.register_dynamic_register('0'+i, + register_manager.add_register('0'+i, make_unique( [i](const Context& context) { StringList result; for (auto& sel : context.selections()) result.emplace_back(i < sel.captures().size() ? sel.captures()[i] : ""); return result; - }); + })); } + + register_manager.add_register('_', make_unique()); } void register_options() diff --git a/src/register_manager.cc b/src/register_manager.cc index 64e56926..c026f3fc 100644 --- a/src/register_manager.cc +++ b/src/register_manager.cc @@ -1,62 +1,12 @@ #include "register_manager.hh" #include "assert.hh" -#include "exception.hh" #include "id_map.hh" namespace Kakoune { -// static value register, which can be modified -// using operator=, so should be user modifiable -class StaticRegister : public Register -{ -public: - Register& operator=(ConstArrayView values) override - { - m_content = Vector(values.begin(), values.end()); - return *this; - } - - ConstArrayView values(const Context&) override - { - if (m_content.empty()) - return ConstArrayView(ms_empty); - else - return ConstArrayView(m_content); - } -protected: - Vector m_content; - - static const String ms_empty; -}; - -const String StaticRegister::ms_empty; - -// Dynamic value register, use it's RegisterRetriever -// to get it's value when needed. -class DynamicRegister : public StaticRegister -{ -public: - DynamicRegister(RegisterRetriever function) - : m_function(std::move(function)) {} - - Register& operator=(ConstArrayView values) override - { - throw runtime_error("this register is not assignable"); - } - - ConstArrayView values(const Context& context) override - { - m_content = m_function(context); - return StaticRegister::values(context); - } - -private: - RegisterRetriever m_function; -}; - -Register& RegisterManager::operator[](StringView reg) +Register& RegisterManager::operator[](StringView reg) const { if (reg.length() == 1) return (*this)[reg[0_byte]]; @@ -74,23 +24,21 @@ Register& RegisterManager::operator[](StringView reg) return (*this)[it->value]; } -Register& RegisterManager::operator[](Codepoint c) +Register& RegisterManager::operator[](Codepoint c) const { c = to_lower(c); - if (c < 32 or c > 127) - throw runtime_error(format("invalid register name: '{}'", c)); + auto it = m_registers.find(c); + if (it == m_registers.end()) + throw runtime_error(format("no such register: '{}'", c)); - auto& reg_ptr = m_registers[c]; - if (not reg_ptr) - reg_ptr.reset(new StaticRegister()); - return *reg_ptr; + return *(it->second); } -void RegisterManager::register_dynamic_register(char reg, RegisterRetriever function) +void RegisterManager::add_register(char c, std::unique_ptr reg) { - auto& reg_ptr = m_registers[reg]; + auto& reg_ptr = m_registers[c]; kak_assert(not reg_ptr); - reg_ptr.reset(new DynamicRegister(std::move(function))); + reg_ptr = std::move(reg); } } diff --git a/src/register_manager.hh b/src/register_manager.hh index df829763..355bec1f 100644 --- a/src/register_manager.hh +++ b/src/register_manager.hh @@ -2,6 +2,7 @@ #define register_manager_hh_INCLUDED #include "array_view.hh" +#include "exception.hh" #include "utils.hh" #include "unordered_map.hh" #include "string.hh" @@ -23,14 +24,73 @@ public: virtual ConstArrayView values(const Context& context) = 0; }; +// static value register, which can be modified +// using operator=, so should be user modifiable +class StaticRegister : public Register +{ +public: + Register& operator=(ConstArrayView values) override + { + m_content = Vector(values.begin(), values.end()); + return *this; + } + + ConstArrayView values(const Context&) override + { + if (m_content.empty()) + return ConstArrayView(String::ms_empty); + else + return ConstArrayView(m_content); + } +protected: + Vector m_content; +}; + using RegisterRetriever = std::function (const Context&)>; +// Dynamic value register, use it's RegisterRetriever +// to get it's value when needed. +class DynamicRegister : public StaticRegister +{ +public: + DynamicRegister(RegisterRetriever function) + : m_function(std::move(function)) {} + + Register& operator=(ConstArrayView values) override + { + throw runtime_error("this register is not assignable"); + } + + ConstArrayView values(const Context& context) override + { + m_content = m_function(context); + return StaticRegister::values(context); + } + +private: + RegisterRetriever m_function; +}; + +class NullRegister : public Register +{ +public: + Register& operator=(ConstArrayView values) override + { + return *this; + } + + ConstArrayView values(const Context& context) override + { + return ConstArrayView(String::ms_empty); + } +}; + class RegisterManager : public Singleton { public: - Register& operator[](StringView reg); - Register& operator[](Codepoint c); - void register_dynamic_register(char reg, RegisterRetriever function); + Register& operator[](StringView reg) const; + Register& operator[](Codepoint c) const; + void add_register(char c, std::unique_ptr reg); protected: UnorderedMap, MemoryDomain::Registers> m_registers;