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; }; }