From 5938712d1f6b90d24a520074e234a6c4c3fb666e Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 22 Oct 2015 13:21:59 +0100 Subject: [PATCH 01/10] Support :set -add on strings, using concatenation --- src/option_types.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/option_types.hh b/src/option_types.hh index fce15ad6..d2161be2 100644 --- a/src/option_types.hh +++ b/src/option_types.hh @@ -16,6 +16,7 @@ namespace Kakoune inline String option_to_string(StringView opt) { return opt.str(); } inline void option_from_string(StringView str, String& opt) { opt = str.str(); } +inline bool option_add(String& opt, const String& val) { opt += val; return not val.empty(); } inline String option_to_string(int opt) { return to_string(opt); } inline void option_from_string(StringView str, int& opt) { opt = str_to_int(str); } From 7346220e38b24f32e4f250909d81eceda4478397 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 22 Oct 2015 13:29:34 +0100 Subject: [PATCH 02/10] Fix :set completion when -add switch is given --- src/commands.cc | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/commands.cc b/src/commands.cc index 311520c8..8d91acbd 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -1016,19 +1016,22 @@ const CommandDesc set_option_cmd = { CommandParameters params, size_t token_to_complete, ByteCount pos_in_token) -> Completions { - if (token_to_complete == 0) - return { 0_byte, params[0].length(), - complete(params[0], pos_in_token, scopes) }; - else if (token_to_complete == 1) - return { 0_byte, params[1].length(), - GlobalScope::instance().option_registry().complete_option_name(params[1], pos_in_token) }; - else if (token_to_complete == 2 and - GlobalScope::instance().option_registry().option_exists(params[1])) + const bool add = params.size() > 1 and params[0] == "-add"; + const int start = add ? 1 : 0; + + if (token_to_complete == start) + return { 0_byte, params[start].length(), + complete(params[start], pos_in_token, scopes) }; + else if (token_to_complete == start + 1) + return { 0_byte, params[start + 1].length(), + GlobalScope::instance().option_registry().complete_option_name(params[start + 1], pos_in_token) }; + else if (not add and token_to_complete == start + 2 and + GlobalScope::instance().option_registry().option_exists(params[start + 1])) { - OptionManager& options = get_scope(params[0], context).options(); - String val = options[params[1]].get_as_string(); - if (prefix_match(val, params[2])) - return { 0_byte, params[2].length(), { std::move(val) } }; + OptionManager& options = get_scope(params[start], context).options(); + String val = options[params[start + 1]].get_as_string(); + if (prefix_match(val, params[start + 2])) + return { 0_byte, params[start + 2].length(), { std::move(val) } }; } return Completions{}; }, From e51ef6c3c29ca23c342776a19bdb9bcfc257875d Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 22 Oct 2015 13:48:57 +0100 Subject: [PATCH 03/10] Wrap the shell params en env vars in a ShellContext struct --- src/command_manager.cc | 26 ++++++++++---------------- src/command_manager.hh | 6 ++---- src/commands.cc | 16 +++++++++------- src/highlighters.cc | 4 ++-- src/normal.cc | 14 +++++--------- src/shell_manager.cc | 8 ++++---- src/shell_manager.hh | 9 +++++++-- 7 files changed, 39 insertions(+), 44 deletions(-) diff --git a/src/command_manager.cc b/src/command_manager.cc index a554d35d..8c3a6454 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -323,8 +323,7 @@ TokenList parse(StringView line) } String expand_token(const Token& token, const Context& context, - ConstArrayView shell_params, - const EnvVarMap& env_vars) + const ShellContext& shell_context) { auto& content = token.content(); switch (token.type()) @@ -332,20 +331,20 @@ String expand_token(const Token& token, const Context& context, case Token::Type::ShellExpand: return ShellManager::instance().eval(content, context, {}, ShellManager::Flags::WaitForStdout, - shell_params, env_vars).first; + shell_context).first; case Token::Type::RegisterExpand: return context.main_sel_register_value(content).str(); case Token::Type::OptionExpand: return context.options()[content].get_as_string(); case Token::Type::ValExpand: { - auto it = env_vars.find(content); - if (it != env_vars.end()) + auto it = shell_context.env_vars.find(content); + if (it != shell_context.env_vars.end()) return it->value; return ShellManager::instance().get_val(content, context); } case Token::Type::RawEval: - return expand(content, context, shell_params, env_vars); + return expand(content, context, shell_context); case Token::Type::Raw: case Token::Type::RawQuoted: return content; @@ -357,8 +356,7 @@ String expand_token(const Token& token, const Context& context, } String expand(StringView str, const Context& context, - ConstArrayView shell_params, - const EnvVarMap& env_vars) + const ShellContext& shell_context) { Reader reader{str}; String res; @@ -380,7 +378,7 @@ String expand(StringView str, const Context& context, { res += reader.substr_from(beg); Token token = parse_percent_token(reader); - res += expand_token(token, context, shell_params, env_vars); + res += expand_token(token, context, shell_context); beg = (++reader).pos; } else @@ -431,9 +429,7 @@ void CommandManager::execute_single_command(CommandParameters params, } void CommandManager::execute(StringView command_line, - Context& context, - ConstArrayView shell_params, - const EnvVarMap& env_vars) + Context& context, const ShellContext& shell_context) { TokenList tokens = parse(command_line); if (tokens.empty()) @@ -455,8 +451,7 @@ void CommandManager::execute(StringView command_line, else if (it->type() == Token::Type::ShellExpand) { auto shell_tokens = parse(expand_token(*it, context, - shell_params, - env_vars)); + shell_context)); it = tokens.erase(it); for (Token& token : shell_tokens) it = ++tokens.emplace(it, std::move(token)); @@ -467,8 +462,7 @@ void CommandManager::execute(StringView command_line, it -= shell_tokens.size() + 1; } else - params.push_back(expand_token(*it, context, shell_params, - env_vars)); + params.push_back(expand_token(*it, context, shell_context)); } execute_single_command(params, context, command_coord); } diff --git a/src/command_manager.hh b/src/command_manager.hh index 9592bce6..d47dbdbc 100644 --- a/src/command_manager.hh +++ b/src/command_manager.hh @@ -61,8 +61,7 @@ class CommandManager : public Singleton { public: void execute(StringView command_line, Context& context, - ConstArrayView shell_params = {}, - const EnvVarMap& env_vars = EnvVarMap{}); + const ShellContext& shell_context = {}); Completions complete(const Context& context, CompletionFlags flags, StringView command_line, ByteCount cursor_pos); @@ -104,8 +103,7 @@ private: }; String expand(StringView str, const Context& context, - ConstArrayView shell_params = {}, - const EnvVarMap& env_vars = EnvVarMap{}); + const ShellContext& shell_context = {}); } diff --git a/src/commands.cc b/src/commands.cc index 8d91acbd..863170ee 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -675,8 +675,8 @@ const CommandDesc add_hook_cmd = { ScopedSetBool disable_history{context.history_disabled()}; if (regex_match(param.begin(), param.end(), regex)) - CommandManager::instance().execute(command, context, {}, - { { "hook_param", param.str() } }); + CommandManager::instance().execute(command, context, + { {}, { { "hook_param", param.str() } } }); }; auto group = parser.get_switch("group").value_or(StringView{}); get_scope(parser[0], context).hooks().add_hook(parser[1], group.str(), hook_func); @@ -738,7 +738,7 @@ void define_command(const ParametersParser& parser, Context& context) { desc = ParameterDesc{ {}, ParameterDesc::Flags::SwitchesAsPositional }; cmd = [=](const ParametersParser& parser, Context& context) { - CommandManager::instance().execute(commands, context, params_to_shell(parser)); + CommandManager::instance().execute(commands, context, { params_to_shell(parser) }); }; } else @@ -795,13 +795,15 @@ void define_command(const ParametersParser& parser, Context& context) { if (flags == CompletionFlags::Fast) // no shell on fast completion return Completions{}; - EnvVarMap vars = { - { "token_to_complete", to_string(token_to_complete) }, - { "pos_in_token", to_string(pos_in_token) } + + ShellContext shell_context{ + params, + { { "token_to_complete", to_string(token_to_complete) }, + { "pos_in_token", to_string(pos_in_token) } } }; String output = ShellManager::instance().eval(shell_cmd, context, {}, ShellManager::Flags::WaitForStdout, - params, vars).first; + shell_context).first; return Completions{ 0_byte, pos_in_token, split(output, '\n', 0) }; }; } diff --git a/src/highlighters.cc b/src/highlighters.cc index 648e6072..17f32cf4 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -485,7 +485,7 @@ HighlighterAndId create_line_highlighter(HighlighterParameters params) auto func = [=](const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange) { - const LineCount line = str_to_int_ifp(expand(option_name, context, {}, EnvVarMap{})).value_or(0) - 1; + const LineCount line = str_to_int_ifp(expand(option_name, context)).value_or(0) - 1; if (line < 0) return; @@ -527,7 +527,7 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params) auto func = [=](const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange) { - const CharCount column = str_to_int_ifp(expand(option_name, context, {}, EnvVarMap{})).value_or(0) - 1; + const CharCount column = str_to_int_ifp(expand(option_name, context)).value_or(0) - 1; if (column < 0) return; diff --git a/src/normal.cc b/src/normal.cc index db878909..2ec36d10 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -381,8 +381,7 @@ void pipe(Context& context, NormalParams) in += '\n'; auto out = ShellManager::instance().eval( real_cmd, context, in, - ShellManager::Flags::WaitForStdout, - {}, EnvVarMap{}).first; + ShellManager::Flags::WaitForStdout).first; if ((insert_eol or sel.max() == buffer.back_coord()) and out.back() == '\n') @@ -397,8 +396,7 @@ void pipe(Context& context, NormalParams) for (auto& sel : selections) ShellManager::instance().eval(real_cmd, context, content(buffer, sel), - ShellManager::Flags::None, - {}, EnvVarMap{}); + ShellManager::Flags::None); } }); } @@ -425,9 +423,8 @@ void insert_output(Context& context, NormalParams) if (real_cmd.empty()) return; - auto str = ShellManager::instance().eval(real_cmd, context, {}, - ShellManager::Flags::WaitForStdout, - {}, EnvVarMap{}).first; + auto str = ShellManager::instance().eval( + real_cmd, context, {}, ShellManager::Flags::WaitForStdout).first; ScopedEdition edition(context); context.selections().insert(str, mode); }); @@ -781,8 +778,7 @@ void keep_pipe(Context& context, NormalParams) for (auto& sel : context.selections()) { if (shell_manager.eval(cmdline, context, content(buffer, sel), - ShellManager::Flags::None, - {}, EnvVarMap{}).second == 0) + ShellManager::Flags::None).second == 0) keep.push_back(sel); } if (keep.empty()) diff --git a/src/shell_manager.cc b/src/shell_manager.cc index e6fb068c..6ac02d65 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -83,7 +83,7 @@ pid_t spawn_process(StringView cmdline, ConstArrayView params, ConstArra std::pair ShellManager::eval( StringView cmdline, const Context& context, StringView input, - Flags flags, ConstArrayView params, const EnvVarMap& env_vars) + Flags flags, const ShellContext& shell_context) { static const Regex re(R"(\bkak_(\w+)\b)"); @@ -100,10 +100,10 @@ std::pair ShellManager::eval( if (find_if(kak_env, match_name) != kak_env.end()) continue; - auto var_it = env_vars.find(name); + auto var_it = shell_context.env_vars.find(name); try { - const String& value = var_it != env_vars.end() ? + const String& value = var_it != shell_context.env_vars.end() ? var_it->value : get_val(name, context); kak_env.push_back(format("kak_{}={}", name, value)); @@ -111,7 +111,7 @@ std::pair ShellManager::eval( } Pipe child_stdin, child_stdout, child_stderr; - pid_t pid = spawn_process(cmdline, params, kak_env, + pid_t pid = spawn_process(cmdline, shell_context.params, kak_env, child_stdin, child_stdout, child_stderr); child_stdin.close_read_fd(); diff --git a/src/shell_manager.hh b/src/shell_manager.hh index 6394f5e3..b7e462e7 100644 --- a/src/shell_manager.hh +++ b/src/shell_manager.hh @@ -14,6 +14,12 @@ class Context; using EnvVarRetriever = std::function; +struct ShellContext +{ + ConstArrayView params; + EnvVarMap env_vars; +}; + class ShellManager : public Singleton { public: @@ -28,8 +34,7 @@ public: std::pair eval(StringView cmdline, const Context& context, StringView input = {}, Flags flags = Flags::WaitForStdout, - ConstArrayView params = {}, - const EnvVarMap& env_vars = EnvVarMap{}); + const ShellContext& shell_context = {}); void register_env_var(StringView str, bool prefix, EnvVarRetriever retriever); String get_val(StringView name, const Context& context) const; From da7fc3311fba98bde4fbc3457fdbf2503fd2b4d0 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 22 Oct 2015 13:59:23 +0100 Subject: [PATCH 04/10] Pass ShellContext to commands Fix #427 --- src/command_manager.cc | 7 ++-- src/command_manager.hh | 10 ++++- src/commands.cc | 94 +++++++++++++++++++++--------------------- 3 files changed, 59 insertions(+), 52 deletions(-) diff --git a/src/command_manager.cc b/src/command_manager.cc index 8c3a6454..0c8613f2 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -405,6 +405,7 @@ CommandManager::find_command(const Context& context, const String& name) const void CommandManager::execute_single_command(CommandParameters params, Context& context, + const ShellContext& shell_context, CharCoord pos) const { if (params.empty()) @@ -419,7 +420,7 @@ void CommandManager::execute_single_command(CommandParameters params, { ParametersParser parameter_parser(param_view, command_it->second.param_desc); - command_it->second.command(parameter_parser, context); + command_it->second.command(parameter_parser, context, shell_context); } catch (runtime_error& error) { @@ -444,7 +445,7 @@ void CommandManager::execute(StringView command_line, if (it->type() == Token::Type::CommandSeparator) { - execute_single_command(params, context, command_coord); + execute_single_command(params, context, shell_context, command_coord); params.clear(); } // Shell expand are retokenized @@ -464,7 +465,7 @@ void CommandManager::execute(StringView command_line, else params.push_back(expand_token(*it, context, shell_context)); } - execute_single_command(params, context, command_coord); + execute_single_command(params, context, shell_context, command_coord); } CommandInfo CommandManager::command_info(const Context& context, StringView command_line) const diff --git a/src/command_manager.hh b/src/command_manager.hh index d47dbdbc..f2d49761 100644 --- a/src/command_manager.hh +++ b/src/command_manager.hh @@ -19,11 +19,15 @@ namespace Kakoune class Context; using CommandParameters = ConstArrayView; -using Command = std::function; +using Command = std::function; + using CommandCompleter = std::function; + using CommandHelper = std::function; enum class CommandFlags @@ -84,7 +88,9 @@ public: private: void execute_single_command(CommandParameters params, - Context& context, CharCoord pos) const; + Context& context, + const ShellContext& shell_context, + CharCoord pos) const; struct CommandDescriptor { diff --git a/src/commands.cc b/src/commands.cc index 863170ee..f4627bc6 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -120,11 +120,11 @@ struct CommandDesc CommandFlags flags; CommandHelper helper; CommandCompleter completer; - void (*func)(const ParametersParser&, Context&); + void (*func)(const ParametersParser&, Context&, const ShellContext&); }; template -void edit(const ParametersParser& parser, Context& context) +void edit(const ParametersParser& parser, Context& context, const ShellContext&) { if (parser.positional_count() == 0 and not force_reload) throw wrong_argument_count(); @@ -215,7 +215,7 @@ const CommandDesc force_edit_cmd = { edit }; -void write_buffer(const ParametersParser& parser, Context& context) +void write_buffer(const ParametersParser& parser, Context& context, const ShellContext&) { Buffer& buffer = context.buffer(); @@ -256,7 +256,7 @@ const CommandDesc writeall_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser&, Context&){ write_all_buffers(); } + [](const ParametersParser&, Context&, const ShellContext&){ write_all_buffers(); } }; const CommandDesc kill_cmd = { @@ -267,7 +267,7 @@ const CommandDesc kill_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser&, Context&){ throw kill_session{}; } + [](const ParametersParser&, Context&, const ShellContext&){ throw kill_session{}; } }; template @@ -307,7 +307,7 @@ const CommandDesc quit_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser&, Context&){ quit(); } + [](const ParametersParser&, Context&, const ShellContext&){ quit(); } }; const CommandDesc force_quit_cmd = { @@ -320,7 +320,7 @@ const CommandDesc force_quit_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser&, Context&){ quit(); } + [](const ParametersParser&, Context&, const ShellContext&){ quit(); } }; const CommandDesc write_quit_cmd = { @@ -331,9 +331,9 @@ const CommandDesc write_quit_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext& shell_context) { - write_buffer(parser, context); + write_buffer(parser, context, shell_context); quit(); } }; @@ -347,9 +347,9 @@ const CommandDesc force_write_quit_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext& shell_context) { - write_buffer(parser, context); + write_buffer(parser, context, shell_context); quit(); } }; @@ -362,7 +362,7 @@ const CommandDesc writeall_quit_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { write_all_buffers(); quit(); @@ -377,7 +377,7 @@ const CommandDesc buffer_cmd = { CommandFlags::None, CommandHelper{}, buffer_completer, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { Buffer* oldbuf = &context.buffer(); Buffer& buffer = BufferManager::instance().get_buffer(parser[0]); @@ -392,7 +392,7 @@ const CommandDesc buffer_cmd = { }; template -void cycle_buffer(const ParametersParser& parser, Context& context) +void cycle_buffer(const ParametersParser& parser, Context& context, const ShellContext&) { Buffer* oldbuf = &context.buffer(); auto it = find_if(BufferManager::instance(), @@ -446,7 +446,7 @@ const CommandDesc bufferprev_cmd = { }; template -void delete_buffer(const ParametersParser& parser, Context& context) +void delete_buffer(const ParametersParser& parser, Context& context, const ShellContext&) { BufferManager& manager = BufferManager::instance(); Buffer& buffer = parser.positional_count() == 0 ? context.buffer() : manager.get_buffer(parser[0]); @@ -490,7 +490,7 @@ const CommandDesc namebuf_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { if (not context.buffer().set_name(parser[0])) throw runtime_error(format("unable to change buffer name to '{}'", parser[0])); @@ -585,7 +585,7 @@ const CommandDesc add_highlighter_cmd = { return ""; }, add_highlighter_completer, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { HighlighterRegistry& registry = HighlighterRegistry::instance(); @@ -616,7 +616,7 @@ const CommandDesc rm_highlighter_cmd = { CommandFlags::None, CommandHelper{}, rm_highlighter_completer, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { StringView path = parser[0]; auto sep_it = find(reversed(path), '/'); @@ -661,7 +661,7 @@ const CommandDesc add_hook_cmd = { } return {}; }, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { Regex regex(parser[2].begin(), parser[2].end(), Regex::optimize | Regex::nosubs | Regex::ECMAScript); @@ -705,7 +705,7 @@ const CommandDesc rm_hook_cmd = { } return {}; }, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { get_scope(parser[0], context).hooks().remove_hooks(parser[1]); } @@ -719,7 +719,7 @@ Vector params_to_shell(const ParametersParser& parser) return vars; } -void define_command(const ParametersParser& parser, Context& context) +void define_command(const ParametersParser& parser, Context& context, const ShellContext&) { const String& cmd_name = parser[0]; auto& cm = CommandManager::instance(); @@ -737,14 +737,14 @@ void define_command(const ParametersParser& parser, Context& context) if (parser.get_switch("shell-params")) { desc = ParameterDesc{ {}, ParameterDesc::Flags::SwitchesAsPositional }; - cmd = [=](const ParametersParser& parser, Context& context) { + cmd = [=](const ParametersParser& parser, Context& context, const ShellContext&) { CommandManager::instance().execute(commands, context, { params_to_shell(parser) }); }; } else { desc = ParameterDesc{ {}, ParameterDesc::Flags::SwitchesAsPositional, 0, 0 }; - cmd = [=](const ParametersParser& parser, Context& context) { + cmd = [=](const ParametersParser& parser, Context& context, const ShellContext&) { CommandManager::instance().execute(commands, context); }; } @@ -854,7 +854,7 @@ const CommandDesc alias_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { if (not CommandManager::instance().command_defined(parser[2])) throw runtime_error(format("Command '{}' does not exist", parser[2])); @@ -873,7 +873,7 @@ const CommandDesc unalias_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { AliasRegistry& aliases = get_scope(parser[0], context).aliases(); if (parser.positional_count() == 3 and @@ -896,7 +896,7 @@ const CommandDesc echo_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { String message = join(parser, ' ', false); if (parser.get_switch("debug")) @@ -926,7 +926,7 @@ const CommandDesc debug_cmd = { auto c = {"info", "buffers", "options", "memory", "shared-strings"}; return { 0_byte, cursor_pos, complete(prefix, cursor_pos, c) }; } }), - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { if (parser[0] == "info") { @@ -977,7 +977,7 @@ const CommandDesc source_cmd = { CommandFlags::None, CommandHelper{}, filename_completer, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { String file_content = read_file(parse_filename(parser[0]), true); try @@ -1037,7 +1037,7 @@ const CommandDesc set_option_cmd = { } return Completions{}; }, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { Option& opt = get_scope(parser[0], context).options().get_local_option(parser[1]); if (parser.get_switch("add")) @@ -1068,7 +1068,7 @@ const CommandDesc unset_option_cmd = { GlobalScope::instance().option_registry().complete_option_name(params[1], pos_in_token) }; return Completions{}; }, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { if (parser[0] == "global") throw runtime_error("Cannot unset options in global scope"); @@ -1098,7 +1098,7 @@ const CommandDesc declare_option_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { Option* opt = nullptr; @@ -1176,7 +1176,7 @@ const CommandDesc map_key_cmd = { } return {}; }, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { KeymapManager& keymaps = get_scope(parser[0], context).keymaps(); KeymapMode keymap_mode = parse_keymap_mode(parser[1]); @@ -1316,7 +1316,7 @@ const CommandDesc exec_string_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { context_wrap(parser, context, [](const ParametersParser& parser, Context& context) { KeyList keys; @@ -1338,7 +1338,7 @@ const CommandDesc eval_string_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { context_wrap(parser, context, [](const ParametersParser& parser, Context& context) { String command = join(parser, ' ', false); @@ -1359,7 +1359,7 @@ const CommandDesc prompt_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& params, Context& context) + [](const ParametersParser& params, Context& context, const ShellContext&) { if (params[1].length() != 1) throw runtime_error("register name should be a single character"); @@ -1393,7 +1393,7 @@ const CommandDesc menu_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { const bool with_select_cmds = (bool)parser.get_switch("select-cmds"); const bool markup = (bool)parser.get_switch("markup"); @@ -1439,7 +1439,7 @@ const CommandDesc onkey_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { String reg = parser[0]; String command = parser[1]; @@ -1464,7 +1464,7 @@ const CommandDesc info_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { context.ui().info_hide(); if (parser.positional_count() > 0) @@ -1506,7 +1506,7 @@ const CommandDesc try_catch_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext& shell_context) { if (parser.positional_count() == 2) throw wrong_argument_count(); @@ -1518,12 +1518,12 @@ const CommandDesc try_catch_cmd = { CommandManager& command_manager = CommandManager::instance(); try { - command_manager.execute(parser[0], context); + command_manager.execute(parser[0], context, shell_context); } catch (Kakoune::runtime_error& e) { if (do_catch) - command_manager.execute(parser[2], context); + command_manager.execute(parser[2], context, shell_context); } } }; @@ -1549,7 +1549,7 @@ const CommandDesc face_cmd = { CommandFlags::None, CommandHelper{}, PerArgumentCommandCompleter({ complete_face, complete_face }), - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { FaceRegistry::instance().register_alias(parser[0], parser[1], true); @@ -1566,7 +1566,7 @@ const CommandDesc set_client_name_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { if (ClientManager::instance().validate_client_name(parser[0])) context.set_name(parser[0]); @@ -1583,7 +1583,7 @@ const CommandDesc set_register_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { RegisterManager::instance()[parser[0]] = ConstArrayView(parser[1]); } @@ -1597,7 +1597,7 @@ const CommandDesc select_cmd = { CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser& parser, Context& context) + [](const ParametersParser& parser, Context& context, const ShellContext&) { context.selections_write_only() = selection_list_from_string(context.buffer(), parser[0]); } @@ -1611,7 +1611,7 @@ const CommandDesc change_working_directory_cmd = { CommandFlags::None, CommandHelper{}, filename_completer, - [](const ParametersParser& parser, Context&) + [](const ParametersParser& parser, Context&, const ShellContext&) { if (chdir(parse_filename(parser[0]).c_str()) != 0) throw runtime_error(format("cannot change to directory '{}'", parser[0])); @@ -1652,7 +1652,7 @@ void exec_keys(ConstArrayView keys, Context& context) void register_commands() { CommandManager& cm = CommandManager::instance(); - cm.register_command("nop", [](const ParametersParser&, Context&){}, "do nothing", {}); + cm.register_command("nop", [](const ParametersParser&, Context&, const ShellContext&){}, "do nothing", {}); auto register_command = [&](const CommandDesc& c) { From 8f432a2eea1b28909ec7ed2d92573025b92f987b Mon Sep 17 00:00:00 2001 From: Frank LENORMAND Date: Thu, 22 Oct 2015 16:41:19 +0300 Subject: [PATCH 05/10] Introduce `formatter.kak` to handle formatting. The modified files used to handle formatting code with the same code, and a different command, the process is now centralized into a single file. Language support files should set the `formatcmd` string to whatever formatter is the most popular in their respective community, eventually with default options. --- rc/c-family.kak | 15 +-------------- rc/dlang.kak | 15 +-------------- rc/formatter.kak | 14 ++++++++++++++ rc/golang.kak | 14 +------------- 4 files changed, 17 insertions(+), 41 deletions(-) create mode 100644 rc/formatter.kak diff --git a/rc/c-family.kak b/rc/c-family.kak index cbaf3072..1e0bf1c4 100644 --- a/rc/c-family.kak +++ b/rc/c-family.kak @@ -68,17 +68,6 @@ def -hidden _c-family-indent-on-closing-curly-brace %[ try %[ exec -draft "hm;(class|struct|union)\`(class|struct|union)[^{}\n]+(\n)?\s*\{\'ma;" ] ] -decl str c_astyle_options "" -def c-format-astyle -docstring "Format C/C++/Obj-C code using the astyle utility" %{ - %sh{ - readonly x=$((kak_cursor_column - 1)) - readonly y="${kak_cursor_line}" - - echo "exec -draft %{%|astyle${kak_opt_c_astyle_options// /}}" - echo "exec gg ${y}g ${x}l" - } -} - # Regions definition are the same between c++ and objective-c %sh{ for ft in c cpp objc; do @@ -135,7 +124,7 @@ hook global WinSetOption filetype=(c|cpp|objc) %[ alias window comment-selection c-family-comment-selection alias window comment-line c-family-comment-line - alias window format-code c-format-astyle + set window formatcmd "astyle" ] hook global WinSetOption filetype=(?!(c|cpp|objc)$).* %[ @@ -145,8 +134,6 @@ hook global WinSetOption filetype=(?!(c|cpp|objc)$).* %[ unalias window alt c-family-alternative-file unalias window comment-selection c-family-comment-selection unalias window comment-line c-family-comment-line - - unalias window format-code c-format-astyle ] hook global WinSetOption filetype=c %[ addhl ref c ] diff --git a/rc/dlang.kak b/rc/dlang.kak index fc5027c5..d79a4270 100644 --- a/rc/dlang.kak +++ b/rc/dlang.kak @@ -70,17 +70,6 @@ def -hidden _dlang-indent-on-closing-curly-brace %[ try %[ exec -itersel -draft ^\h+\}$hms\`|.\'1 ] ] -decl str dlang_dfmt_options "" -def dlang-format-dfmt -docstring "Format the code using the dfmt utility" %{ - %sh{ - readonly x=$((kak_cursor_column - 1)) - readonly y="${kak_cursor_line}" - - echo "exec -draft %{%|dfmt${kak_opt_dlang_dfmt_options// /}}" - echo "exec gg ${y}g ${x}l" - } -} - # Initialization # ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ @@ -93,7 +82,7 @@ hook global WinSetOption filetype=dlang %{ hook window InsertChar \{ -group dlang-indent _dlang-indent-on-opening-curly-brace hook window InsertChar \} -group dlang-indent _dlang-indent-on-closing-curly-brace - alias window format-code dlang-format-dfmt + set window formatcmd "dfmt" } hook global WinSetOption filetype=(?!dlang).* %{ @@ -101,6 +90,4 @@ hook global WinSetOption filetype=(?!dlang).* %{ rmhooks window dlang-hooks rmhooks window dlang-indent - - unalias window format-code dlang-format-dfmt } diff --git a/rc/formatter.kak b/rc/formatter.kak new file mode 100644 index 00000000..d6075fe6 --- /dev/null +++ b/rc/formatter.kak @@ -0,0 +1,14 @@ +decl str formatcmd "" +def format -docstring "Format the entire buffer with an external utility" %{ + %sh{ + if [ ! -z "${kak_opt_formatcmd}" ]; then + ## Save the current position of the cursor + readonly x=$((kak_cursor_column - 1)) + readonly y="${kak_cursor_line}" + + echo "exec -draft %{%|${kak_opt_formatcmd// /}}" + ## Try to restore the position of the cursor as it was prior to formatting + echo "exec gg ${y}g ${x}l" + fi + } +} diff --git a/rc/golang.kak b/rc/golang.kak index e4d45511..54a01ce2 100644 --- a/rc/golang.kak +++ b/rc/golang.kak @@ -62,16 +62,6 @@ def -hidden _golang-indent-on-closing-curly-brace %[ try %[ exec -itersel -draft ^\h+\}$hms\`|.\'1 ] ] -def golang-format-gofmt -docstring "Format the code using the gofmt utility" %{ - %sh{ - readonly x=$((kak_cursor_column - 1)) - readonly y="${kak_cursor_line}" - - echo "exec -draft %{%|gofmt}" - echo "exec gg ${y}g ${x}l" - } -} - # Initialization # ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ @@ -84,7 +74,7 @@ hook global WinSetOption filetype=golang %{ hook window InsertChar \{ -group golang-indent _golang-indent-on-opening-curly-brace hook window InsertChar \} -group golang-indent _golang-indent-on-closing-curly-brace - alias window format-code golang-format-gofmt + set window formatcmd "gofmt" } hook global WinSetOption filetype=(?!golang).* %{ @@ -92,6 +82,4 @@ hook global WinSetOption filetype=(?!golang).* %{ rmhooks window golang-hooks rmhooks window golang-indent - - unalias window format-code golang-format-gofmt } From 1ba37bacd8cda9c24d074887e2c10a8881f9c861 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 23 Oct 2015 09:49:06 +0100 Subject: [PATCH 06/10] Fix optimized linkage --- src/command_manager.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/command_manager.hh b/src/command_manager.hh index f2d49761..2251e8b7 100644 --- a/src/command_manager.hh +++ b/src/command_manager.hh @@ -65,7 +65,7 @@ class CommandManager : public Singleton { public: void execute(StringView command_line, Context& context, - const ShellContext& shell_context = {}); + const ShellContext& shell_context = ShellContext{}); Completions complete(const Context& context, CompletionFlags flags, StringView command_line, ByteCount cursor_pos); @@ -109,7 +109,7 @@ private: }; String expand(StringView str, const Context& context, - const ShellContext& shell_context = {}); + const ShellContext& shell_context = ShellContext{}); } From e5b8c9f4dcfd2c693b924d9aa46ef0b02558b528 Mon Sep 17 00:00:00 2001 From: Frank LENORMAND Date: Sun, 11 Oct 2015 23:29:03 +0300 Subject: [PATCH 07/10] Add a basic perl highlighting script --- rc/perl.kak | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 rc/perl.kak diff --git a/rc/perl.kak b/rc/perl.kak new file mode 100644 index 00000000..6803a068 --- /dev/null +++ b/rc/perl.kak @@ -0,0 +1,118 @@ +# https://www.perl.org/ +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufSetOption mimetype=text/x-perl %{ + set buffer filetype perl +} + +hook global BufCreate .*\.pl %{ + set buffer filetype perl +} + +# Highlighters +# ‾‾‾‾‾‾‾‾‾‾‾‾ + +addhl -group / regions -default code perl \ + command '(?:[^\$]|^)`' '`' '' \ + command '\ 0:value +addhl -group /perl/code regex \<(ARGV|STDERR|STDOUT|ARGVOUT|STDIN)\> 0:value +addhl -group /perl/code regex (?!\$)-?([0-9]*\.(?!0[xXbB]))?\<([0-9]+|0[xX][0-9a-fA-F]+|0[bb][01_]+)\.?([eE][+-]?[0-9]+)?i?\> 0:value +addhl -group /perl/code regex %{\$!|\$"|\$#|\$\$|\$%|\$&|\$'|\$\(|\$\)|\$\*|\$\+|\$,|\$_|\$-|\$`|\$\.|\$/|\$:|\$;|\$<|\$=|\$>|\$\?|\$@|\$\[|\$\\|\$\]|\$\^|\$\||\$~|%!|@\+|@-|@_} 0:value +addhl -group /perl/code regex (%ENV|%INC|%OVERLOAD|%SIG|@ARGV|@INC|@LAST_MATCH_START) 0:value +addhl -group /perl/code regex %{%\^(H)\>} 0:value +addhl -group /perl/code regex \$\^(S|T|V|W|X|A|C|D|E|F|H|I|L|M|N|O|P|R)\> 0:value +addhl -group /perl/code regex \$\^(RE_TRIE_MAXBUF|TAINT|UNICODE|UTF8LOCALE|WARNING_BITS|WIDE_SYSTEM_CALLS|CHILD_ERROR_NATIVE|ENCODING|OPEN|RE_DEBUG_FLAGS)\> 0:value + +addhl -group /perl/code regex \$[0-9]+ 0:attribute +addhl -group /perl/code regex \<-(B|b|C|c|d|e|f|g|k|l|M|O|o|p|r|R|S|s|T|t|u|w|W|X|x|z)\> 0:attribute +addhl -group /perl/code regex \<(END|AUTOLOAD|BEGIN|CHECK|UNITCHECK|INIT|DESTROY)\> 0:attribute +addhl -group /perl/code regex \<(length|setpgrp|endgrent|link|setpriority|endhostent|listen|setprotoent|endnetent|local|setpwent)\> 0:attribute +addhl -group /perl/code regex \<(endprotoent|localtime|setservent|endpwent|log|setsockopt|endservent|lstat|shift|eof|map|shmctl|eval|mkdir|shmget|exec|msgctl|shmread)\> 0:attribute +addhl -group /perl/code regex \<(exists|msgget|shmwrite|msgrcv|shutdown|fcntl|msgsnd|sin|fileno|sleep|flock|next|socket|fork|socketpair|format|oct|sort)\> 0:attribute +addhl -group /perl/code regex \<(formline|open|splice|getc|opendir|split|getgrent|ord|sprintf|getgrgid|our|sqrt|getgrnam|pack|srand|gethostbyaddr|pipe|stat|gethostbyname)\> 0:attribute +addhl -group /perl/code regex \<(pop|state|gethostent|pos|study|getlogin|print|substr|getnetbyaddr|printf|symlink|abs|getnetbyname|prototype|syscall|accept|getnetent)\> 0:attribute +addhl -group /perl/code regex \<(push|sysopen|alarm|getpeername|quotemeta|sysread|atan2|getpgrp|rand|sysseek|getppid|read|system|getpriority|readdir|syswrite|bind)\> 0:attribute +addhl -group /perl/code regex \<(getprotobyname|readline|tell|binmode|getprotobynumber|readlink|telldir|bless|getprotoent|readpipe|tie|getpwent|recv|tied|caller)\> 0:attribute +addhl -group /perl/code regex \<(getpwnam|redo|time|chdir|getpwuid|ref|times|getservbyname|rename|truncate|chmod|getservbyport|require|uc|chomp|getservent|reset|ucfirst)\> 0:attribute +addhl -group /perl/code regex \<(chop|getsockname|umask|chown|getsockopt|reverse|undef|chr|glob|rewinddir|chroot|gmtime|rindex|unlink|close|rmdir|unpack)\> 0:attribute +addhl -group /perl/code regex \<(closedir|grep|say|unshift|connect|hex|scalar|untie|cos|index|seek|use|crypt|seekdir|utime|dbmclose|int|select|values|dbmopen|ioctl|semctl)\> 0:attribute +addhl -group /perl/code regex \<(vec|defined|join|semget|wait|delete|keys|semop|waitpid|kill|send|wantarray|die|last|setgrent|warn|dump|lc|sethostent|write|each|lcfirst|setnetent)\> 0:attribute + +addhl -group /perl/code regex \<(else|lock|qw|elsif|lt|qx|eq||exp|ne|sub|for|no|my|not|tr|goto|and|foreach|or|break|exit|unless|cmp|ge|package|until|continue|gt|while|if|qq|xor|do|le|qr|return)\> 0:keyword + +addhl -group /perl/code regex %{(?:\<[stqrmwy]+)?/[^\n/]*/([msixpodualngecr]+\>)?} 0:magenta +addhl -group /perl/code regex %{(?:\<[stqrmwy]+)?/[^\n/]+/[^\n/]*/([msixpeodualngcr]+\>)?} 0:magenta + +addhl -group /perl/code regex \$[a-zA-Z_][a-zA-Z0-9_]* 0:blue + +addhl -group /perl/code regex \$(a|b|LAST_REGEXP_CODE_RESULT|LIST_SEPARATOR|MATCH|MULTILINE_MATCHING|NR|OFMT|OFS|ORS|OS_ERROR|OSNAME|OUTPUT_AUTO_FLUSH|OUTPUT_FIELD_SEPARATOR|OUTPUT_RECORD_SEPARATOR)\> 0:value +addhl -group /perl/code regex \$(LAST_REGEXP_CODE_RESULT|LIST_SEPARATOR|MATCH|MULTILINE_MATCHING|NR|OFMT|OFS|ORS|OS_ERROR|OSNAME|OUTPUT_AUTO_FLUSH|OUTPUT_FIELD_SEPARATOR|OUTPUT_RECORD_SEPARATOR|PERL_VERSION|ACCUMULATOR|PERLDB|ARG|PID|ARGV|POSTMATCH|PREMATCH|BASETIME|PROCESS_ID|CHILD_ERROR|PROGRAM_NAME|COMPILING|REAL_GROUP_ID|DEBUGGING|REAL_USER_ID|EFFECTIVE_GROUP_ID|RS|EFFECTIVE_USER_ID|SUBSCRIPT_SEPARATOR|EGID|SUBSEP|ERRNO|SYSTEM_FD_MAX|EUID|UID|EVAL_ERROR|WARNING|EXCEPTIONS_BEING_CAUGHT|EXECUTABLE_NAME|EXTENDED_OS_ERROR|FORMAT_FORMFEED|FORMAT_LINE_BREAK_CHARACTERS|FORMAT_LINES_LEFT|FORMAT_LINES_PER_PAGE|FORMAT_NAME|FORMAT_PAGE_NUMBER|FORMAT_TOP_NAME|GID|INPLACE_EDIT|INPUT_LINE_NUMBER|INPUT_RECORD_SEPARATOR|LAST_MATCH_END|LAST_PAREN_MATCH)\> 0:value + +# Commands +# ‾‾‾‾‾‾‾‾ + +def -hidden _perl-indent-on-new-line %~ + eval -draft -itersel %= + # preserve previous line indent + try %{ exec -draft \;K } + # indent after lines ending with { or ( + try %[ exec -draft k [{(]\h*$ j ] + # cleanup trailing white spaces on the previous line + try %{ exec -draft k s \h+$ d } + # align to opening paren of previous line + try %{ exec -draft [( \`\([^\n]+\n[^\n]*\n?\' s \`\(\h*.|.\' '' & } + # copy // comments prefix + try %{ exec -draft \;k s ^\h*\K/{2,} yP } + # indent after a switch's case/default statements + try %[ exec -draft k ^\h*(case|default).*:$ j ] + # indent after if|else|while|for + try %[ exec -draft \;)MB \`(if|else|while|for)\h*\(.*\)\h*\n\h*\n?\' s \`|.\' 11 ] + = +~ + +def -hidden _perl-indent-on-opening-curly-brace %[ + # align indent with opening paren when { is entered on a new line after the closing paren + try %[ exec -draft -itersel h)M \`\(.*\)\h*\n\h*\{\' s \`|.\' 1 ] +] + +def -hidden _perl-indent-on-closing-curly-brace %[ + # align to opening curly brace when alone on a line + try %[ exec -itersel -draft ^\h+\}$hms\`|.\'1 ] +] + +# Initialization +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +hook global WinSetOption filetype=perl %{ + addhl ref perl + + # cleanup trailing whitespaces when exiting insert mode + hook window InsertEnd .* -group perl-hooks %{ try %{ exec -draft s^\h+$d } } + hook window InsertChar \n -group perl-indent _perl-indent-on-new-line + hook window InsertChar \{ -group perl-indent _perl-indent-on-opening-curly-brace + hook window InsertChar \} -group perl-indent _perl-indent-on-closing-curly-brace + + set window formatcmd "perltidy" +} + +hook global WinSetOption filetype=(?!perl).* %{ + rmhl perl + + rmhooks window perl-hooks + rmhooks window perl-indent +} From e7152bad56906838fb306aee15b04ab778f2c69c Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 23 Oct 2015 13:34:03 +0100 Subject: [PATCH 08/10] Add an exclusive attribute that overrides existing face --- src/face.hh | 20 +++++++++++--------- src/face_registry.cc | 1 + 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/face.hh b/src/face.hh index 2540705e..806089a9 100644 --- a/src/face.hh +++ b/src/face.hh @@ -10,12 +10,13 @@ namespace Kakoune enum class Attribute : int { Normal = 0, - Underline = 1 << 1, - Reverse = 1 << 2, - Blink = 1 << 3, - Bold = 1 << 4, - Dim = 1 << 5, - Italic = 1 << 6, + Exclusive = 1 << 1, + Underline = 1 << 2, + Reverse = 1 << 3, + Blink = 1 << 4, + Bold = 1 << 5, + Dim = 1 << 6, + Italic = 1 << 7, }; template<> struct WithBitOps : std::true_type {}; @@ -45,9 +46,10 @@ constexpr bool operator!=(const Face& lhs, const Face& rhs) constexpr Face merge_faces(const Face& base, const Face& face) { - return { face.fg == Color::Default ? base.fg : face.fg, - face.bg == Color::Default ? base.bg : face.bg, - face.attributes | base.attributes }; + return face.attributes & Attribute::Exclusive ? + face : Face{ face.fg == Color::Default ? base.fg : face.fg, + face.bg == Color::Default ? base.bg : face.bg, + face.attributes | base.attributes }; } } diff --git a/src/face_registry.cc b/src/face_registry.cc index a1a0e582..2f0be21b 100644 --- a/src/face_registry.cc +++ b/src/face_registry.cc @@ -24,6 +24,7 @@ static Face parse_face(StringView facedesc) { switch (*attr_it) { + case 'e': res.attributes |= Attribute::Exclusive; break; case 'u': res.attributes |= Attribute::Underline; break; case 'r': res.attributes |= Attribute::Reverse; break; case 'b': res.attributes |= Attribute::Bold; break; From 5118e13aeef461bbaf2b86cb5d46331b9cacc061 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 23 Oct 2015 13:34:37 +0100 Subject: [PATCH 09/10] Remove useless std::move --- src/command_manager.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command_manager.cc b/src/command_manager.cc index 0c8613f2..03621184 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -310,7 +310,7 @@ TokenList parse(StringView line) if (not str.empty()) result.emplace_back(Token::Type::Raw, start, reader.pos, - coord, std::move(unescape(str, "%", '\\'))); + coord, unescape(str, "%", '\\')); } if (is_command_separator(*reader)) From 40c6edf243312974319e1b272dd20d46c0b0c91e Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 23 Oct 2015 13:48:32 +0100 Subject: [PATCH 10/10] Document exclusive attribute --- README.asciidoc | 1 + src/commands.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.asciidoc b/README.asciidoc index 811f0a76..3a7fe8fb 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -787,6 +787,7 @@ attributes is a string of letters each defining an attributes: * `B`: Blink * `d`: Dim * `i`: Italic + * `e`: Exclusive, override previous faces instead of merging with them Using named faces instead of facespec permits to change the effective faces afterwards. diff --git a/src/commands.cc b/src/commands.cc index f4627bc6..6084f1f4 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -1543,7 +1543,7 @@ const CommandDesc face_cmd = { "facespec format is [,][+]\n" "colors are either a color name, or rgb:###### values.\n" "attributes is a combination of:\n" - " u: underline, r: reverse, b: bold, B: blink, d: dim\n" + " u: underline, r: reverse, b: bold, B: blink, d: dim, e: exclusive\n" "facespec can as well just be the name of another face" , ParameterDesc{{}, ParameterDesc::Flags::None, 2, 2}, CommandFlags::None,