From f3dd65fbf193ef4e53a58919cb14264b376cd1b0 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 3 Apr 2012 13:39:20 +0000 Subject: [PATCH] add an OptionManager class and use it to manage tabstops OptionManager map names to options, and may delegate option resolution to it's parent if it does not contains the asked for option. That way Buffers can override global options, and Windows can override Buffer options. --- src/buffer.cc | 3 +- src/buffer.hh | 5 +++ src/filters.cc | 2 +- src/highlighters.cc | 11 +++--- src/main.cc | 2 ++ src/option_manager.cc | 21 +++++++++++ src/option_manager.hh | 84 +++++++++++++++++++++++++++++++++++++++++++ src/window.cc | 3 +- src/window.hh | 5 ++- 9 files changed, 127 insertions(+), 9 deletions(-) create mode 100644 src/option_manager.cc create mode 100644 src/option_manager.hh diff --git a/src/buffer.cc b/src/buffer.cc index 13aa5b00..060f55c4 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -26,7 +26,8 @@ Buffer::Buffer(const std::string& name, Type type, const String& initial_content) : m_name(name), m_type(type), m_history(1), m_history_cursor(m_history.begin()), - m_last_save_undo_index(0) + m_last_save_undo_index(0), + m_option_manager(GlobalOptionManager::instance()) { BufferManager::instance().register_buffer(this); if (not initial_content.empty()) diff --git a/src/buffer.hh b/src/buffer.hh index 83e5ffc7..fb142aec 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -7,6 +7,7 @@ #include #include "line_and_column.hh" +#include "option_manager.hh" namespace Kakoune { @@ -173,6 +174,8 @@ public: const String& line_content(size_t l) const { return m_lines[l].content; } + OptionManager& option_manager() { return m_option_manager; } + private: friend class BufferIterator; @@ -210,6 +213,8 @@ private: size_t m_last_save_undo_index; std::vector m_modification_listeners; + + OptionManager m_option_manager; }; inline Modification Modification::make_erase(BufferIterator begin, diff --git a/src/filters.cc b/src/filters.cc index 8290d6a7..9d1589f4 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -39,7 +39,7 @@ void cleanup_whitespaces(Buffer& buffer, Modification& modification) void expand_tabulations(Buffer& buffer, Modification& modification) { - const int tabstop = 8; + const int tabstop = buffer.option_manager()["tabstop"]; if (modification.type == Modification::Insert and modification.content == "\t") { diff --git a/src/highlighters.cc b/src/highlighters.cc index eef24701..ed0fa63c 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -10,6 +10,8 @@ namespace Kakoune { +using namespace std::placeholders; + void colorize_regex_range(DisplayBuffer& display_buffer, const BufferIterator& range_begin, const BufferIterator& range_end, @@ -97,13 +99,13 @@ HighlighterAndId colorize_regex_factory(Window& window, std::string id = "colre'" + params[0] + "'"; - return HighlighterAndId(id, std::bind(colorize_regex, std::placeholders::_1, + return HighlighterAndId(id, std::bind(colorize_regex, _1, ex, fg_color, bg_color)); } -void expand_tabulations(DisplayBuffer& display_buffer) +void expand_tabulations(Window& window, DisplayBuffer& display_buffer) { - const int tabstop = 8; + const int tabstop = window.option_manager()["tabstop"]; for (auto atom_it = display_buffer.begin(); atom_it != display_buffer.end(); ++atom_it) { @@ -289,7 +291,6 @@ public: HighlighterAndId operator()(Window& window, const HighlighterParameters& params) const { - using namespace std::placeholders; return HighlighterAndId(m_id, std::bind(highlighter_func, std::ref(window), _1)); } private: @@ -310,7 +311,7 @@ void register_highlighters() HighlighterRegistry& registry = HighlighterRegistry::instance(); registry.register_factory("highlight_selections", WindowHighlighterFactory("highlight_selections")); - registry.register_factory("expand_tabs", SimpleHighlighterFactory("expand_tabs")); + registry.register_factory("expand_tabs", WindowHighlighterFactory("expand_tabs")); registry.register_factory("number_lines", SimpleHighlighterFactory("number_lines")); registry.register_factory("regex", colorize_regex_factory); registry.register_factory("group", highlighter_group_factory); diff --git a/src/main.cc b/src/main.cc index 78e8ad32..488e4e33 100644 --- a/src/main.cc +++ b/src/main.cc @@ -12,6 +12,7 @@ #include "filters.hh" #include "filter_registry.hh" #include "hook_manager.hh" +#include "option_manager.hh" #include "context.hh" #include "ncurses.hh" @@ -918,6 +919,7 @@ int main(int argc, char* argv[]) HighlighterRegistry highlighter_registry; FilterRegistry filter_registry; GlobalHookManager hook_manager; + GlobalOptionManager option_manager; run_unit_tests(); diff --git a/src/option_manager.cc b/src/option_manager.cc new file mode 100644 index 00000000..0e326fc2 --- /dev/null +++ b/src/option_manager.cc @@ -0,0 +1,21 @@ +#include "option_manager.hh" + +#include + +namespace Kakoune +{ + +std::string int_to_str(int value) +{ + std::ostringstream oss; + oss << value; + return oss.str(); +} + +GlobalOptionManager::GlobalOptionManager() + : OptionManager() +{ + (*this)["tabstop"] = 8; +} + +} diff --git a/src/option_manager.hh b/src/option_manager.hh new file mode 100644 index 00000000..b88ac73e --- /dev/null +++ b/src/option_manager.hh @@ -0,0 +1,84 @@ +#ifndef option_manager_hh_INCLUDED +#define option_manager_hh_INCLUDED + +#include "utils.hh" +#include "exception.hh" + +#include + +namespace Kakoune +{ + +struct option_not_found : public runtime_error +{ + option_not_found(const std::string& name) + : runtime_error("option not found: " + name) {} +}; + +std::string int_to_str(int value); + +class Option +{ +public: + Option() {} + explicit Option(int value) : m_value(int_to_str(value)) {} + explicit Option(const std::string& value) : m_value(value) {} + + Option& operator=(int value) { m_value = int_to_str(value); return *this; } + Option& operator=(const std::string& value) { m_value = value; return *this; } + + operator int() const { return atoi(m_value.c_str()); } + operator std::string() const { return m_value; } +private: + std::string m_value; +}; + +class OptionManager +{ +public: + OptionManager(OptionManager& parent) + : m_parent(&parent) {} + + Option& operator[] (const std::string& name) + { + auto it = m_options.find(name); + if (it != m_options.end()) + return it->second; + else if (m_parent) + return (*m_parent)[name]; + else + return m_options[name]; + } + + const Option& operator[] (const std::string& name) const + { + auto it = m_options.find(name); + if (it != m_options.end()) + return it->second; + else if (m_parent) + return (*m_parent)[name]; + else + throw option_not_found(name); + } + +private: + OptionManager() + : m_parent(nullptr) {} + // the only one allowed to construct a root option manager + friend class GlobalOptionManager; + + std::unordered_map m_options; + OptionManager* m_parent; +}; + +class GlobalOptionManager : public OptionManager, + public Singleton +{ +public: + GlobalOptionManager(); +}; + + +} + +#endif // option_manager_hh_INCLUDED diff --git a/src/window.cc b/src/window.cc index 2a0b2a86..84503ca4 100644 --- a/src/window.cc +++ b/src/window.cc @@ -14,7 +14,8 @@ namespace Kakoune Window::Window(Buffer& buffer) : Editor(buffer), m_position(0, 0), - m_dimensions(0, 0) + m_dimensions(0, 0), + m_option_manager(buffer.option_manager()) { HighlighterRegistry& registry = HighlighterRegistry::instance(); diff --git a/src/window.hh b/src/window.hh index 9105d04a..7e77c6ee 100644 --- a/src/window.hh +++ b/src/window.hh @@ -9,6 +9,7 @@ #include "highlighter.hh" #include "highlighter_group.hh" #include "hook_manager.hh" +#include "option_manager.hh" namespace Kakoune { @@ -38,7 +39,8 @@ public: HighlighterGroup& highlighters() { return m_highlighters; } - HookManager& hook_manager() { return m_hook_manager; } + HookManager& hook_manager() { return m_hook_manager; } + OptionManager& option_manager() { return m_option_manager; } private: friend class Buffer; @@ -57,6 +59,7 @@ private: HighlighterGroup m_highlighters; HookManager m_hook_manager; + OptionManager m_option_manager; }; }