diff --git a/rc/filetype/c-family.kak b/rc/filetype/c-family.kak index 33fd31e50..a3d46e0ae 100644 --- a/rc/filetype/c-family.kak +++ b/rc/filetype/c-family.kak @@ -27,39 +27,10 @@ hook global BufCreate .*\.m %{ hook global WinSetOption filetype=(c|cpp|objc) %[ require-module c-family - evaluate-commands "set-option window static_words %%opt{%val{hook_param_capture_1}_static_words}" - - hook -group "%val{hook_param_capture_1}-trim-indent" window ModeChange pop:insert:.* c-family-trim-indent - hook -group "%val{hook_param_capture_1}-insert" window InsertChar \n c-family-insert-on-newline - hook -group "%val{hook_param_capture_1}-indent" window InsertChar \n c-family-indent-on-newline - hook -group "%val{hook_param_capture_1}-indent" window InsertChar \{ c-family-indent-on-opening-curly-brace - hook -group "%val{hook_param_capture_1}-indent" window InsertChar \} c-family-indent-on-closing-curly-brace - hook -group "%val{hook_param_capture_1}-insert" window InsertChar \} c-family-insert-on-closing-curly-brace - - alias window alt "%val{hook_param_capture_1}-alternative-file" - - hook -once -always window WinSetOption filetype=.* " - remove-hooks window %val{hook_param_capture_1}-.+ - unalias window alt %val{hook_param_capture_1}-alternative-file - " + link-shared-scope buffer %val{hook_param_capture_1} + hook -once -always window WinSetOption filetype=.* "unlink-shared-scope window %val{hook_param_capture_1}" ] -hook -group c-highlight global WinSetOption filetype=c %{ - add-highlighter window/c ref c - hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/c } -} - -hook -group cpp-highlight global WinSetOption filetype=cpp %{ - add-highlighter window/cpp ref cpp - hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cpp } -} - -hook -group objc-highlight global WinSetOption filetype=objc %{ - add-highlighter window/objc ref objc - hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/objc } -} - - provide-module c-family %§ define-command -hidden c-family-trim-indent %{ @@ -459,6 +430,27 @@ define-command objc-alternative-file -docstring "Jump to the alternate objc file c-family-alternative-file } +evaluate-commands %sh[ + for ft in c cpp objc; do + cat <<-EOF + declare-shared-scope $ft + + add-highlighter shared/$ft/ ref $ft + + evaluate-commands "set-option shared/$ft static_words %%opt{${ft}_static_words}" + + hook -group "${ft}-trim-indent" shared/${ft} ModeChange pop:insert:.* c-family-trim-indent + hook -group "${ft}-insert" shared/${ft} InsertChar \n c-family-insert-on-newline + hook -group "${ft}-indent" shared/${ft} InsertChar \n c-family-indent-on-newline + hook -group "${ft}-indent" shared/${ft} InsertChar \{ c-family-indent-on-opening-curly-brace + hook -group "${ft}-indent" shared/${ft} InsertChar \} c-family-indent-on-closing-curly-brace + hook -group "${ft}-insert" shared/${ft} InsertChar \} c-family-insert-on-closing-curly-brace + + alias shared/${ft} alt "${ft}-alternative-file" +EOF + done +] + § # Module aliases diff --git a/src/commands.cc b/src/commands.cc index dd95f0fc4..81a0a6b5e 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -190,7 +190,7 @@ const ParameterDesc single_param{ {}, ParameterDesc::Flags::None, 1, 1 }; const ParameterDesc single_optional_param{ {}, ParameterDesc::Flags::None, 0, 1 }; const ParameterDesc double_params{ {}, ParameterDesc::Flags::None, 2, 2 }; -static constexpr auto scopes = { "global", "buffer", "window" }; +static constexpr auto scopes = { "global", "buffer", "window", "shared" }; static Completions complete_scope(const Context&, CompletionFlags, const String& prefix, ByteCount cursor_pos) @@ -321,6 +321,12 @@ Scope* get_scope_ifp(StringView scope, const Context& context) return &context.window(); else if (prefix_match(scope, "buffer=")) return &BufferManager::instance().get_buffer(scope.substr(7_byte)); + else if (prefix_match(scope, "shared/")) + { + auto it = SharedScopes::instance().scopes.find(scope.substr(7_byte)); + if (it != SharedScopes::instance().scopes.end()) + return it->value.get(); + } return nullptr; } @@ -2649,6 +2655,81 @@ const CommandDesc require_module_cmd = { } }; +const CommandDesc declare_shared_scope_cmd = { + "declare-shared-scope", + nullptr, + "declare-shared-scope : declare ", + ParameterDesc{ + {}, + ParameterDesc::Flags::None, + 1, 1 + }, + CommandFlags::None, + CommandHelper{}, + make_completer(complete_scope), + [](const ParametersParser& parser, Context& context, const ShellContext&) + { + auto name = parser[0]; + if (name.empty() or not all_of(name, is_identifier)) + throw runtime_error(format("invalid shared scope name: '{}'", name)); + + if (SharedScopes::instance().scopes.contains(name)) + throw runtime_error(format("duplicate shared scope name: '{}'", name)); + + SharedScopes::instance().scopes.insert({name, std::make_unique()}); + } +}; + +static Completions complete_shared_scope(const Context&, CompletionFlags, + const String& prefix, ByteCount cursor_pos) +{ + return { 0_byte, cursor_pos, complete(prefix, cursor_pos, SharedScopes::instance().scopes | transform([](auto&& v) -> const String& { return v.key; })) }; +} + +SharedScope& get_shared_scope(StringView name) +{ + auto it = SharedScopes::instance().scopes.find(name); + if (it == SharedScopes::instance().scopes.end()) + throw runtime_error(format("no such shared scope '{}'", name)); + return *it->value; +} + +const CommandDesc link_shared_scope_cmd = { + "link-shared-scope", + nullptr, + "link-shared-scope : link into ", + ParameterDesc{ + {}, + ParameterDesc::Flags::None, + 2, 2 + }, + CommandFlags::None, + CommandHelper{}, + make_completer(complete_scope, complete_shared_scope), + [](const ParametersParser& parser, Context& context, const ShellContext&) + { + get_scope(parser[0], context).add_shared_scope(get_shared_scope(parser[1])); + } +}; + +const CommandDesc unlink_shared_scope_cmd = { + "unlink-shared-scope", + nullptr, + "unlink-shared-scope : unlink into ", + ParameterDesc{ + {}, + ParameterDesc::Flags::None, + 2, 2 + }, + CommandFlags::None, + CommandHelper{}, + make_completer(complete_scope, complete_shared_scope), + [](const ParametersParser& parser, Context& context, const ShellContext&) + { + get_scope(parser[0], context).remove_shared_scope(get_shared_scope(parser[1])); + } +}; + } void register_commands() @@ -2718,6 +2799,9 @@ void register_commands() register_command(enter_user_mode_cmd); register_command(provide_module_cmd); register_command(require_module_cmd); + register_command(declare_shared_scope_cmd); + register_command(link_shared_scope_cmd); + register_command(unlink_shared_scope_cmd); } } diff --git a/src/highlighter_group.cc b/src/highlighter_group.cc index d5d431987..2ffbd9ae9 100644 --- a/src/highlighter_group.cc +++ b/src/highlighter_group.cc @@ -85,6 +85,8 @@ void Highlighters::highlight(HighlightContext context, DisplayBuffer& display_bu if (m_parent) m_parent->highlight({context.context, context.setup, context.pass, disabled_ids}, display_buffer, range); + for (auto& shared : m_shared) + shared->highlight({context.context, context.setup, context.pass, disabled_ids}, display_buffer, range); m_group.highlight(context, display_buffer, range); } @@ -95,6 +97,8 @@ void Highlighters::compute_display_setup(HighlightContext context, DisplaySetup& if (m_parent) m_parent->compute_display_setup({context.context, context.setup, context.pass, disabled_ids}, setup); + for (auto& shared : m_shared) + shared->compute_display_setup({context.context, context.setup, context.pass, disabled_ids}, setup); m_group.compute_display_setup(context, setup); } diff --git a/src/hook_manager.cc b/src/hook_manager.cc index c0f8e265f..d3c6bf06f 100644 --- a/src/hook_manager.cc +++ b/src/hook_manager.cc @@ -79,6 +79,9 @@ void HookManager::run_hook(Hook hook, StringView param, Context& context) hooks_to_run.push_back({ hook.get(), std::move(captures) }); } + for (auto& shared : m_shared) + m_shared->run_hook(hook, param, context); + if (m_parent) m_parent->run_hook(hook, param, context); diff --git a/src/option_manager.cc b/src/option_manager.cc index 0b91b5557..d6feaf085 100644 --- a/src/option_manager.cc +++ b/src/option_manager.cc @@ -52,14 +52,14 @@ Option& OptionManager::get_local_option(StringView name) auto it = m_options.find(name); if (it != m_options.end()) return *(it->value); - else if (m_parent) + + if (m_parent) { auto* clone = (*m_parent)[name].clone(*this); return *m_options.insert({clone->name(), std::unique_ptr