mirror of
https://github.com/mawww/kakoune.git
synced 2024-11-24 07:53:41 +03:00
Buffers can hold arbitrary values for for other systems
This commit is contained in:
parent
e6884f989c
commit
85387b3efe
@ -6,6 +6,7 @@
|
||||
#include "option_manager.hh"
|
||||
#include "keymap_manager.hh"
|
||||
#include "string.hh"
|
||||
#include "value.hh"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
@ -166,6 +167,8 @@ public:
|
||||
KeymapManager& keymaps() { return m_keymaps; }
|
||||
const KeymapManager& keymaps() const { return m_keymaps; }
|
||||
|
||||
ValueMap& values() const { return m_values; }
|
||||
|
||||
void run_hook_in_own_context(const String& hook_name, const String& param);
|
||||
|
||||
std::unordered_set<BufferChangeListener*>& change_listeners() const { return m_change_listeners; }
|
||||
@ -224,6 +227,10 @@ private:
|
||||
HookManager m_hooks;
|
||||
KeymapManager m_keymaps;
|
||||
|
||||
// Values are just data holding by the buffer, so it is part of its
|
||||
// observable state
|
||||
mutable ValueMap m_values;
|
||||
|
||||
friend constexpr Flags operator|(Flags lhs, Flags rhs)
|
||||
{
|
||||
return (Flags)((int) lhs | (int) rhs);
|
||||
|
118
src/value.hh
Normal file
118
src/value.hh
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef value_hh_INCLUDED
|
||||
#define value_hh_INCLUDED
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "units.hh"
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
||||
struct bad_value_cast {};
|
||||
|
||||
struct Value
|
||||
{
|
||||
Value() = default;
|
||||
|
||||
template<typename T>
|
||||
Value(const T& val) : m_value{new Model<T>{val}} {}
|
||||
|
||||
template<typename T>
|
||||
Value(T&& val) : m_value{new Model<T>{std::move(val)}} {}
|
||||
|
||||
Value(const Value& val)
|
||||
{
|
||||
if (val.m_value)
|
||||
m_value.reset(val.m_value->clone());
|
||||
}
|
||||
|
||||
Value(Value&&) = default;
|
||||
|
||||
Value& operator=(const Value& val)
|
||||
{
|
||||
if (val.m_value)
|
||||
m_value.reset(val.m_value->clone());
|
||||
else
|
||||
m_value.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value& operator=(Value&& val) = default;
|
||||
|
||||
explicit operator bool() const { return (bool)m_value; }
|
||||
|
||||
template<typename T>
|
||||
bool is_a() const
|
||||
{
|
||||
return m_value and m_value->type() == typeid(T);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& as()
|
||||
{
|
||||
if (not is_a<T>())
|
||||
throw bad_value_cast{};
|
||||
return static_cast<Model<T>*>(m_value.get())->m_content;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& as() const
|
||||
{
|
||||
return const_cast<Value*>(this)->as<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
struct Concept
|
||||
{
|
||||
virtual ~Concept() {}
|
||||
virtual const std::type_info& type() const = 0;
|
||||
virtual Concept* clone() const = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Model : public Concept
|
||||
{
|
||||
Model(const T& val) : m_content(val) {}
|
||||
Model(T&& val) : m_content(std::move(val)) {}
|
||||
|
||||
const std::type_info& type() const override { return typeid(T); }
|
||||
Concept* clone() const { return new Model(m_content); }
|
||||
|
||||
T m_content;
|
||||
};
|
||||
|
||||
std::unique_ptr<Concept> m_value;
|
||||
};
|
||||
|
||||
struct ValueId : public StronglyTypedNumber<ValueId, int>
|
||||
{
|
||||
constexpr ValueId(int value = 0) : StronglyTypedNumber<ValueId>(value) {}
|
||||
|
||||
static ValueId get_free_id()
|
||||
{
|
||||
static ValueId next;
|
||||
return next++;
|
||||
}
|
||||
};
|
||||
|
||||
using ValueMap = std::unordered_map<ValueId, Value>;
|
||||
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<>
|
||||
struct hash<Kakoune::ValueId>
|
||||
{
|
||||
size_t operator()(Kakoune::ValueId val) const
|
||||
{
|
||||
return std::hash<int>()((int)val);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // value_hh_INCLUDED
|
Loading…
Reference in New Issue
Block a user