diff --git a/README.asciidoc b/README.asciidoc index b6d61284..c1a3e47b 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -398,9 +398,12 @@ window scope (+BOM+ or +eolformat+ for example). New options can be declared using the +:decl+ command: ------------------------------ -:decl [] ------------------------------ +--------------------------------------- +:decl [-hidden] [] +--------------------------------------- + +the +-hidden+ parameter makes the option invisible in completion, but +still modifiable. Some options are built in kakoune, and can be used to control it's behaviour: diff --git a/src/commands.cc b/src/commands.cc index a577895c..4911337c 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -458,29 +458,36 @@ void set_option(CommandParameters params, Context& context) void declare_option(CommandParameters params, Context& context) { - if (params.size() != 2 and params.size() != 3) - throw wrong_argument_count(); + ParametersParser parser(params, { { "hidden", false } }, + ParametersParser::Flags::OptionsOnlyAtStart, + 2, 3); Option* opt = nullptr; - if (params[0] == "int") - opt = &GlobalOptions::instance().declare_option(params[1], 0); - if (params[0] == "bool") - opt = &GlobalOptions::instance().declare_option(params[1], 0); - else if (params[0] == "str") - opt = &GlobalOptions::instance().declare_option(params[1], ""); - else if (params[0] == "regex") - opt = &GlobalOptions::instance().declare_option(params[1], Regex{}); - else if (params[0] == "int-list") - opt = &GlobalOptions::instance().declare_option>(params[1], {}); - else if (params[0] == "str-list") - opt = &GlobalOptions::instance().declare_option>(params[1], {}); - else if (params[0] == "line-flag-list") - opt = &GlobalOptions::instance().declare_option>(params[1], {}); - else - throw runtime_error("unknown type " + params[0]); + Option::Flags flags = Option::Flags::None; + if (parser.has_option("hidden")) + flags = Option::Flags::Hidden; - if (params.size() == 3) - opt->set_from_string(params[2]); + GlobalOptions& opts = GlobalOptions::instance(); + + if (parser[0] == "int") + opt = &opts.declare_option(parser[1], 0, flags); + if (parser[0] == "bool") + opt = &opts.declare_option(parser[1], 0, flags); + else if (parser[0] == "str") + opt = &opts.declare_option(parser[1], "", flags); + else if (parser[0] == "regex") + opt = &opts.declare_option(parser[1], Regex{}, flags); + else if (parser[0] == "int-list") + opt = &opts.declare_option>(parser[1], {}, flags); + else if (parser[0] == "str-list") + opt = &opts.declare_option>(parser[1], {}, flags); + else if (parser[0] == "line-flag-list") + opt = &opts.declare_option>(parser[1], {}, flags); + else + throw runtime_error("unknown type " + parser[0]); + + if (parser.positional_count() == 3) + opt->set_from_string(parser[2]); } diff --git a/src/option_manager.cc b/src/option_manager.cc index ec3ae4fe..7eb9e7f5 100644 --- a/src/option_manager.cc +++ b/src/option_manager.cc @@ -7,8 +7,8 @@ namespace Kakoune { -Option::Option(OptionManager& manager, String name) - : m_manager(manager), m_name(std::move(name)) {} +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) @@ -72,6 +72,9 @@ CandidateList OptionManager::complete_option_name(const String& prefix, result = m_parent->complete_option_name(prefix, cursor_pos); for (auto& option : m_options) { + if (option->flags() & Option::Flags::Hidden) + continue; + const auto& name = option->name(); if (prefix_match(name, real_prefix) and not contains(result, name)) result.push_back(name); @@ -123,6 +126,7 @@ GlobalOptions::GlobalOptions() declare_option>("completions", {}); declare_option>("path", { "./", "/usr/include" }); declare_option>("completers", {"option", "filename", "word=buffer"}, + Option::Flags::None, [](const std::vector& s) { static const auto values = {"option", "word=buffer", "word=all", "filename" }; for (auto& v : s) diff --git a/src/option_manager.hh b/src/option_manager.hh index 388f0e97..a8688b27 100644 --- a/src/option_manager.hh +++ b/src/option_manager.hh @@ -22,7 +22,13 @@ class OptionManager; class Option : public SafeCountable { public: - Option(OptionManager& manager, String name); + enum class Flags + { + None = 0, + Hidden = 1, + }; + + Option(OptionManager& manager, String name, Flags flags); virtual ~Option() {} template const T& get() const; @@ -37,9 +43,19 @@ public: OptionManager& manager() const { return m_manager; } virtual Option* clone(OptionManager& manager) const = 0; + + Flags flags() const { return m_flags; } + + friend constexpr Flags operator|(Flags lhs, Flags rhs) + { return (Flags)((int)lhs | (int)rhs); } + + friend constexpr bool operator&(Flags lhs, Flags rhs) + { return (bool)((int)lhs & (int)rhs); } + protected: OptionManager& m_manager; String m_name; + Flags m_flags; }; class OptionManagerWatcher @@ -87,9 +103,9 @@ template class TypedOption : public Option { public: - TypedOption(OptionManager& manager, String name, const T& value, - OptionChecker checker) - : Option(manager, std::move(name)), m_value(value), + TypedOption(OptionManager& manager, String name, Option::Flags flags, + const T& value, OptionChecker checker) + : Option(manager, std::move(name), flags), m_value(value), m_checker(std::move(checker)) {} void set(T value) @@ -126,7 +142,7 @@ public: Option* clone(OptionManager& manager) const override { - return new TypedOption{manager, name(), m_value, m_checker}; + return new TypedOption{manager, name(), flags(), m_value, m_checker}; } private: T m_value; @@ -169,16 +185,18 @@ public: template Option& declare_option(const String& name, const T& value, + Option::Flags flags = Option::Flags::None, OptionChecker checker = OptionChecker{}) { auto it = find_option(m_options, name); if (it != m_options.end()) { - if ((*it)->is_of_type()) + if ((*it)->is_of_type() and (*it)->flags() == flags) return **it; - throw runtime_error("option " + name + " already declared with different type"); + throw runtime_error("option " + name + " already declared with different type or flags"); } - m_options.emplace_back(new TypedOption{*this, name, value, std::move(checker)}); + m_options.emplace_back(new TypedOption{*this, name, flags, value, + std::move(checker)}); return *m_options.back(); } }; diff --git a/src/rc/clang.kak b/src/rc/clang.kak index 5b6c4677..91efc8bf 100644 --- a/src/rc/clang.kak +++ b/src/rc/clang.kak @@ -1,4 +1,4 @@ -decl str clang_filename +decl -hidden str clang_filename decl str clang_options def clang-complete %{