home/src/option_manager.cc

150 lines
4.5 KiB
C++
Raw Normal View History

#include "option_manager.hh"
2013-04-09 20:05:40 +02:00
#include "assert.hh"
#include <sstream>
namespace Kakoune
{
Option::Option(OptionManager& manager, String name, Flags flags)
: m_manager(manager), m_name(std::move(name)), m_flags(flags) {}
OptionManager::OptionManager(OptionManager& parent)
: m_parent(&parent)
2012-04-03 20:25:27 +02:00
{
parent.register_watcher(*this);
}
OptionManager::~OptionManager()
{
if (m_parent)
m_parent->unregister_watcher(*this);
kak_assert(m_watchers.empty());
}
void OptionManager::register_watcher(OptionManagerWatcher& watcher)
{
kak_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);
kak_assert(it != m_watchers.end());
m_watchers.erase(it);
}
Option& OptionManager::get_local_option(const String& name)
{
auto it = find_option(m_options, name);
if (it != m_options.end())
return **it;
else if (m_parent)
{
m_options.emplace_back((*m_parent)[name].clone(*this));
return *m_options.back();
}
else
throw option_not_found(name);
2012-04-03 20:25:27 +02:00
}
const Option& OptionManager::operator[](const String& name) const
2012-04-03 20:25:27 +02:00
{
auto it = find_option(m_options, name);
2012-04-03 20:25:27 +02:00
if (it != m_options.end())
return **it;
2012-04-03 20:25:27 +02:00
else if (m_parent)
return (*m_parent)[name];
else
throw option_not_found(name);
}
template<typename MatchingFunc>
CandidateList OptionManager::get_matching_names(MatchingFunc func)
2012-04-03 20:25:27 +02:00
{
CandidateList result;
if (m_parent)
result = m_parent->get_matching_names(func);
2012-04-03 20:25:27 +02:00
for (auto& option : m_options)
{
if (option->flags() & Option::Flags::Hidden)
continue;
const auto& name = option->name();
if (func(name) and not contains(result, name))
result.push_back(name);
2012-04-03 20:25:27 +02:00
}
return result;
}
CandidateList OptionManager::complete_option_name(const String& prefix,
ByteCount cursor_pos)
{
using namespace std::placeholders;
String real_prefix = prefix.substr(0, cursor_pos);
auto result = get_matching_names(std::bind(prefix_match, _1, std::ref(real_prefix)));
if (result.empty())
result = get_matching_names(std::bind(subsequence_match, _1, std::ref(real_prefix)));
return result;
}
OptionManager::OptionList OptionManager::flatten_options() const
{
OptionList res = m_parent ? m_parent->flatten_options() : OptionList{};
for (auto& option : m_options)
{
auto it = find_option(res, option->name());
if (it != res.end())
*it = option.get();
else
res.emplace_back(option.get());
}
return res;
}
void OptionManager::on_option_changed(const Option& option)
{
// if parent option changed, but we overrided it, it's like nothing happened
if (&option.manager() != this and
find_option(m_options, option.name()) != m_options.end())
return;
for (auto watcher : m_watchers)
watcher->on_option_changed(option);
}
GlobalOptions::GlobalOptions()
: OptionManager()
{
declare_option<int>("tabstop", 8);
declare_option<int>("indentwidth", 4);
2013-05-16 19:22:44 +02:00
declare_option<int>("scrolloff", 0);
declare_option<String>("eolformat", "lf");
declare_option<String>("BOM", "no");
declare_option<String>("shell", "bash");
2013-03-05 19:03:42 +01:00
declare_option<bool>("complete_prefix", true);
declare_option<bool>("incsearch", true);
2013-07-26 19:52:25 +02:00
declare_option<bool>("autoinfo", true);
declare_option<bool>("autoshowcompl", true);
2013-11-06 20:11:46 +01:00
declare_option<bool>("aligntab", false);
declare_option<Regex>("ignored_files", Regex{R"(^(\..*|.*\.(o|so|a))$)"});
declare_option<String>("filetype", "");
declare_option<std::vector<String>>("completions", {});
declare_option<std::vector<String>>("path", { "./", "/usr/include" });
declare_option<std::vector<String>>("completers", {"option", "filename", "word=buffer"},
Option::Flags::None,
[](const std::vector<String>& s) {
static const auto values = {"option", "word=buffer", "word=all", "filename" };
for (auto& v : s)
if (not contains(values, v))
throw runtime_error(v + " is not a recognised value for completers");
});
declare_option<YesNoAsk>("autoreload", Ask);
}
}