2012-04-03 17:39:20 +04:00
|
|
|
#include "option_manager.hh"
|
2013-04-09 22:05:40 +04:00
|
|
|
|
2012-06-14 17:16:44 +04:00
|
|
|
#include "assert.hh"
|
2012-04-03 17:39:20 +04:00
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
2013-03-03 20:25:40 +04:00
|
|
|
Option::Option(OptionManager& manager, String name)
|
|
|
|
: m_manager(manager), m_name(std::move(name)) {}
|
|
|
|
|
2012-06-14 17:16:44 +04:00
|
|
|
OptionManager::OptionManager(OptionManager& parent)
|
|
|
|
: m_parent(&parent)
|
2012-04-03 22:25:27 +04:00
|
|
|
{
|
2012-06-14 17:16:44 +04:00
|
|
|
parent.register_watcher(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
OptionManager::~OptionManager()
|
|
|
|
{
|
|
|
|
if (m_parent)
|
|
|
|
m_parent->unregister_watcher(*this);
|
|
|
|
|
2013-04-09 22:04:11 +04:00
|
|
|
kak_assert(m_watchers.empty());
|
2012-06-14 17:16:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void OptionManager::register_watcher(OptionManagerWatcher& watcher)
|
|
|
|
{
|
2013-04-09 22:04:11 +04:00
|
|
|
kak_assert(not contains(m_watchers, &watcher));
|
2012-06-14 17:16:44 +04:00
|
|
|
m_watchers.push_back(&watcher);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OptionManager::unregister_watcher(OptionManagerWatcher& watcher)
|
|
|
|
{
|
|
|
|
auto it = find(m_watchers.begin(), m_watchers.end(), &watcher);
|
2013-04-09 22:04:11 +04:00
|
|
|
kak_assert(it != m_watchers.end());
|
2012-06-14 17:16:44 +04:00
|
|
|
m_watchers.erase(it);
|
|
|
|
}
|
|
|
|
|
2013-03-03 20:25:40 +04:00
|
|
|
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)
|
2012-06-12 22:28:25 +04:00
|
|
|
{
|
2013-03-03 20:25:40 +04:00
|
|
|
m_options.emplace_back((*m_parent)[name].clone(*this));
|
|
|
|
return *m_options.back();
|
2012-06-12 22:28:25 +04:00
|
|
|
}
|
2013-03-03 20:25:40 +04:00
|
|
|
else
|
|
|
|
throw option_not_found(name);
|
|
|
|
|
2012-04-03 22:25:27 +04:00
|
|
|
}
|
|
|
|
|
2012-06-14 17:16:44 +04:00
|
|
|
const Option& OptionManager::operator[](const String& name) const
|
2012-04-03 22:25:27 +04:00
|
|
|
{
|
2013-03-03 20:25:40 +04:00
|
|
|
auto it = find_option(m_options, name);
|
2012-04-03 22:25:27 +04:00
|
|
|
if (it != m_options.end())
|
2013-03-03 20:25:40 +04:00
|
|
|
return **it;
|
2012-04-03 22:25:27 +04:00
|
|
|
else if (m_parent)
|
|
|
|
return (*m_parent)[name];
|
|
|
|
else
|
|
|
|
throw option_not_found(name);
|
|
|
|
}
|
|
|
|
|
2012-04-14 05:17:09 +04:00
|
|
|
CandidateList OptionManager::complete_option_name(const String& prefix,
|
2012-10-11 02:41:48 +04:00
|
|
|
ByteCount cursor_pos)
|
2012-04-03 22:25:27 +04:00
|
|
|
{
|
2012-04-14 05:17:09 +04:00
|
|
|
String real_prefix = prefix.substr(0, cursor_pos);
|
2012-04-03 22:25:27 +04:00
|
|
|
CandidateList result;
|
|
|
|
if (m_parent)
|
|
|
|
result = m_parent->complete_option_name(prefix, cursor_pos);
|
|
|
|
for (auto& option : m_options)
|
|
|
|
{
|
2013-03-03 20:25:40 +04:00
|
|
|
const auto& name = option->name();
|
|
|
|
if (name.substr(0, real_prefix.length()) == real_prefix and
|
|
|
|
not contains(result, name))
|
|
|
|
result.push_back(name);
|
2012-04-03 22:25:27 +04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-03-03 20:25:40 +04:00
|
|
|
OptionManager::OptionList OptionManager::flatten_options() const
|
2012-06-14 17:16:44 +04:00
|
|
|
{
|
2013-03-03 20:25:40 +04:00
|
|
|
OptionList res = m_parent ? m_parent->flatten_options() : OptionList{};
|
2012-06-14 17:16:44 +04:00
|
|
|
for (auto& option : m_options)
|
2013-03-03 20:25:40 +04:00
|
|
|
{
|
|
|
|
auto it = find_option(res, option->name());
|
|
|
|
if (it != res.end())
|
|
|
|
*it = option.get();
|
|
|
|
else
|
|
|
|
res.emplace_back(option.get());
|
|
|
|
}
|
2012-06-14 17:16:44 +04:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-03-03 20:25:40 +04:00
|
|
|
void OptionManager::on_option_changed(const Option& option)
|
2012-06-14 17:16:44 +04:00
|
|
|
{
|
|
|
|
// if parent option changed, but we overrided it, it's like nothing happened
|
2013-03-03 20:25:40 +04:00
|
|
|
if (&option.manager() != this and
|
|
|
|
find_option(m_options, option.name()) != m_options.end())
|
2012-06-14 17:16:44 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (auto watcher : m_watchers)
|
2013-03-03 20:25:40 +04:00
|
|
|
watcher->on_option_changed(option);
|
2012-06-14 17:16:44 +04:00
|
|
|
}
|
|
|
|
|
2012-11-22 16:50:29 +04:00
|
|
|
GlobalOptions::GlobalOptions()
|
2012-04-03 17:39:20 +04:00
|
|
|
: OptionManager()
|
|
|
|
{
|
2013-03-03 20:25:40 +04:00
|
|
|
declare_option<int>("tabstop", 8);
|
|
|
|
declare_option<int>("indentwidth", 4);
|
2013-05-16 21:22:44 +04:00
|
|
|
declare_option<int>("scrolloff", 0);
|
2013-03-03 20:25:40 +04:00
|
|
|
declare_option<String>("eolformat", "lf");
|
|
|
|
declare_option<String>("BOM", "no");
|
2013-04-01 00:33:06 +04:00
|
|
|
declare_option<String>("shell", "bash");
|
2013-03-05 22:03:42 +04:00
|
|
|
declare_option<bool>("complete_prefix", true);
|
|
|
|
declare_option<bool>("incsearch", true);
|
2013-07-26 21:52:25 +04:00
|
|
|
declare_option<bool>("autoinfo", true);
|
2013-03-14 16:42:07 +04:00
|
|
|
declare_option<Regex>("ignored_files", Regex{R"(^(\..*|.*\.(o|so|a))$)"});
|
2013-03-03 20:25:40 +04:00
|
|
|
declare_option<String>("filetype", "");
|
2013-03-09 17:23:19 +04:00
|
|
|
declare_option<std::vector<String>>("completions", {});
|
2013-03-13 21:52:55 +04:00
|
|
|
declare_option<std::vector<String>>("path", { "./", "/usr/include" });
|
2013-05-20 16:10:53 +04:00
|
|
|
declare_option<std::unordered_set<String>>("completers", {"option", "word=buffer"},
|
2013-05-06 15:52:41 +04:00
|
|
|
[](const std::unordered_set<String>& s) {
|
|
|
|
for (auto& v : s)
|
|
|
|
{
|
2013-05-20 16:10:53 +04:00
|
|
|
if (v != "option" and v != "word=buffer" and v != "word=all")
|
2013-05-06 15:52:41 +04:00
|
|
|
throw runtime_error(v + " is not a recognised value for completers");
|
|
|
|
}
|
|
|
|
});
|
2013-03-19 17:04:24 +04:00
|
|
|
declare_option<bool>("insert_hide_sel", false);
|
2013-03-03 20:25:40 +04:00
|
|
|
}
|
|
|
|
|
2012-04-03 17:39:20 +04:00
|
|
|
}
|