summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2012-06-14 13:16:44 +0000
committerMaxime Coste <frrrwww@gmail.com>2012-06-14 13:16:44 +0000
commita943e08dc7b93c065d83639862fbcf1dd2fcb9c1 (patch)
tree77319eb952d7f493a26160e92f39c126e4613919 /src
parent109c11f29c08f6592e53cb9e309e76d6619ee522 (diff)
Refactor OptionManager, add OptionManagerWatcher
- use set_option to set an option, instead of operator[] (no-const) - keeps a list of OptionManagerWatcher to notify when an option change it also notifies when an option changes in his parent and the option is not overridden.
Diffstat (limited to 'src')
-rw-r--r--src/commands.cc11
-rw-r--r--src/option_manager.cc76
-rw-r--r--src/option_manager.hh34
3 files changed, 89 insertions, 32 deletions
diff --git a/src/commands.cc b/src/commands.cc
index f5ab6c9d..71043d28 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -640,13 +640,12 @@ void exec_commands_in_runtime_file(const CommandParameters& params,
}
void set_option(OptionManager& option_manager, const CommandParameters& params,
- HookManager& hook_manager, const Context& context)
+ const Context& context)
{
if (params.size() != 2)
throw wrong_argument_count();
- option_manager[params[0]] = params[1];
- hook_manager.run_hook("SetOption", params[0] + "=" + params[1], context);
+ option_manager.set_option(params[0], Option(params[1]));
}
class RegisterRestorer
@@ -920,7 +919,7 @@ void register_commands()
cm.register_commands({ "setg", "setglobal" },
[](const CommandParameters& params, const Context& context)
- { set_option(GlobalOptionManager::instance(), params, GlobalHookManager::instance(), context); },
+ { set_option(GlobalOptionManager::instance(), params, context); },
CommandManager::None,
PerArgumentCommandCompleter({
[](const String& prefix, size_t cursor_pos)
@@ -928,7 +927,7 @@ void register_commands()
}));
cm.register_commands({ "setb", "setbuffer" },
[](const CommandParameters& params, const Context& context)
- { set_option(context.buffer().option_manager(), params, context.buffer().hook_manager(), context); },
+ { set_option(context.buffer().option_manager(), params, context); },
CommandManager::None,
PerArgumentCommandCompleter({
[](const String& prefix, size_t cursor_pos)
@@ -936,7 +935,7 @@ void register_commands()
}));
cm.register_commands({ "setw", "setwindow" },
[](const CommandParameters& params, const Context& context)
- { set_option(context.window().option_manager(), params, context.window().hook_manager(), context); },
+ { set_option(context.window().option_manager(), params, context); },
CommandManager::None,
PerArgumentCommandCompleter({
[](const String& prefix, size_t cursor_pos)
diff --git a/src/option_manager.cc b/src/option_manager.cc
index a0533f8f..c7d63d55 100644
--- a/src/option_manager.cc
+++ b/src/option_manager.cc
@@ -1,35 +1,51 @@
#include "option_manager.hh"
+#include "assert.hh"
#include <sstream>
namespace Kakoune
{
-Option& OptionManager::operator[] (const String& name)
+OptionManager::OptionManager(OptionManager& parent)
+ : m_parent(&parent)
{
- auto it = m_options.find(name);
- if (it != m_options.end())
- return it->second;
- else
+ parent.register_watcher(*this);
+}
+
+OptionManager::~OptionManager()
+{
+ if (m_parent)
+ m_parent->unregister_watcher(*this);
+
+ assert(m_watchers.empty());
+}
+
+void OptionManager::register_watcher(OptionManagerWatcher& watcher)
+{
+ assert(not contains(m_watchers, &watcher));
+ m_watchers.push_back(&watcher);
+}
+
+void OptionManager::unregister_watcher(OptionManagerWatcher& watcher)
+{
+ auto it = find(m_watchers.begin(), m_watchers.end(), &watcher);
+ assert(it != m_watchers.end());
+ m_watchers.erase(it);
+}
+
+void OptionManager::set_option(const String& name, const Option& value)
+{
+ Option old_value = m_options[name];
+ m_options[name] = value;
+
+ if (old_value != value)
{
- Option& res = m_options[name];
- OptionManager* parent = m_parent;
- while (parent)
- {
- auto parent_it = parent->m_options.find(name);
- if (parent_it != parent->m_options.end())
- {
- res = parent_it->second;
- break;
- }
- else
- parent = parent->m_parent;
- }
- return res;
+ for (auto watcher : m_watchers)
+ watcher->on_option_changed(name, value);
}
}
-const Option& OptionManager::operator[] (const String& name) const
+const Option& OptionManager::operator[](const String& name) const
{
auto it = m_options.find(name);
if (it != m_options.end())
@@ -56,10 +72,28 @@ CandidateList OptionManager::complete_option_name(const String& prefix,
return result;
}
+OptionManager::OptionMap OptionManager::flatten_options() const
+{
+ OptionMap res = m_parent ? m_parent->flatten_options() : OptionMap();
+ for (auto& option : m_options)
+ res.insert(option);
+ return res;
+}
+
+void OptionManager::on_option_changed(const String& name, const Option& value)
+{
+ // if parent option changed, but we overrided it, it's like nothing happened
+ if (m_options.find(name) != m_options.end())
+ return;
+
+ for (auto watcher : m_watchers)
+ watcher->on_option_changed(name, value);
+}
+
GlobalOptionManager::GlobalOptionManager()
: OptionManager()
{
- (*this)["tabstop"] = 8;
+ set_option("tabstop", Option(8));
}
}
diff --git a/src/option_manager.hh b/src/option_manager.hh
index 91f35c08..49b8c9d5 100644
--- a/src/option_manager.hh
+++ b/src/option_manager.hh
@@ -28,32 +28,56 @@ public:
Option& operator=(int value) { m_value = int_to_str(value); return *this; }
Option& operator=(const String& value) { m_value = value; return *this; }
+ bool operator==(const Option& other) const { return m_value == other.m_value; }
+ bool operator!=(const Option& other) const { return m_value != other.m_value; }
+
int as_int() const { return atoi(m_value.c_str()); }
String as_string() const { return m_value; }
private:
String m_value;
};
-class OptionManager
+class OptionManagerWatcher
+{
+public:
+ virtual ~OptionManagerWatcher() {}
+
+ virtual void on_option_changed(const String& name,
+ const Option& option) = 0;
+};
+
+class OptionManager : private OptionManagerWatcher
{
public:
- OptionManager(OptionManager& parent)
- : m_parent(&parent) {}
+ OptionManager(OptionManager& parent);
+ ~OptionManager();
- Option& operator[] (const String& name);
const Option& operator[] (const String& name) const;
+ void set_option(const String& name, const Option& value);
+
CandidateList complete_option_name(const String& prefix,
size_t cursor_pos);
+ typedef std::unordered_map<String, Option> OptionMap;
+ OptionMap flatten_options() const;
+
+ void register_watcher(OptionManagerWatcher& watcher);
+ void unregister_watcher(OptionManagerWatcher& watcher);
+
private:
OptionManager()
: m_parent(nullptr) {}
// the only one allowed to construct a root option manager
friend class GlobalOptionManager;
- std::unordered_map<String, Option> m_options;
+ OptionMap m_options;
OptionManager* m_parent;
+
+ void on_option_changed(const String& name,
+ const Option& value);
+
+ std::vector<OptionManagerWatcher*> m_watchers;
};
class GlobalOptionManager : public OptionManager,