summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2015-10-27 13:33:15 +0000
committerMaxime Coste <frrrwww@gmail.com>2015-10-27 13:33:15 +0000
commit2eba789610c71b23dc7a32107ee6350cd810a9cf (patch)
tree775be815bf0fd67557d833f64fb65d44d1bbb2b9 /src
parentc77cb7c777ffc6f23ad53003d3531c1957fcdd0b (diff)
parent8f7c2ac636369f1f012fe1685ce9c0220fa81645 (diff)
Merge branch 'master' into ranked-word-completion
Diffstat (limited to 'src')
-rw-r--r--src/command_manager.cc35
-rw-r--r--src/command_manager.hh16
-rw-r--r--src/commands.cc139
-rw-r--r--src/face.hh20
-rw-r--r--src/face_registry.cc1
-rw-r--r--src/highlighters.cc4
-rw-r--r--src/normal.cc14
-rw-r--r--src/option_types.hh1
-rw-r--r--src/shell_manager.cc8
-rw-r--r--src/shell_manager.hh9
10 files changed, 128 insertions, 119 deletions
diff --git a/src/command_manager.cc b/src/command_manager.cc
index a554d35d..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))
@@ -323,8 +323,7 @@ TokenList parse(StringView line)
}
String expand_token(const Token& token, const Context& context,
- ConstArrayView<String> 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<String> 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<true>(reader);
- res += expand_token(token, context, shell_params, env_vars);
+ res += expand_token(token, context, shell_context);
beg = (++reader).pos;
}
else
@@ -407,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())
@@ -421,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)
{
@@ -431,9 +430,7 @@ void CommandManager::execute_single_command(CommandParameters params,
}
void CommandManager::execute(StringView command_line,
- Context& context,
- ConstArrayView<String> shell_params,
- const EnvVarMap& env_vars)
+ Context& context, const ShellContext& shell_context)
{
TokenList tokens = parse<true>(command_line);
if (tokens.empty())
@@ -448,15 +445,14 @@ 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
else if (it->type() == Token::Type::ShellExpand)
{
auto shell_tokens = parse<true>(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,10 +463,9 @@ 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);
+ 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 9592bce6..2251e8b7 100644
--- a/src/command_manager.hh
+++ b/src/command_manager.hh
@@ -19,11 +19,15 @@ namespace Kakoune
class Context;
using CommandParameters = ConstArrayView<String>;
-using Command = std::function<void (const ParametersParser& parser, Context& context)>;
+using Command = std::function<void (const ParametersParser& parser,
+ Context& context,
+ const ShellContext& shell_context)>;
+
using CommandCompleter = std::function<Completions (const Context& context,
CompletionFlags,
CommandParameters,
size_t, ByteCount)>;
+
using CommandHelper = std::function<String (const Context& context, CommandParameters)>;
enum class CommandFlags
@@ -61,8 +65,7 @@ class CommandManager : public Singleton<CommandManager>
{
public:
void execute(StringView command_line, Context& context,
- ConstArrayView<String> shell_params = {},
- const EnvVarMap& env_vars = EnvVarMap{});
+ const ShellContext& shell_context = ShellContext{});
Completions complete(const Context& context, CompletionFlags flags,
StringView command_line, ByteCount cursor_pos);
@@ -85,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
{
@@ -104,8 +109,7 @@ private:
};
String expand(StringView str, const Context& context,
- ConstArrayView<String> shell_params = {},
- const EnvVarMap& env_vars = EnvVarMap{});
+ const ShellContext& shell_context = ShellContext{});
}
diff --git a/src/commands.cc b/src/commands.cc
index 311520c8..6084f1f4 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<bool force_reload>
-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<true>
};
-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<bool force>
@@ -307,7 +307,7 @@ const CommandDesc quit_cmd = {
CommandFlags::None,
CommandHelper{},
CommandCompleter{},
- [](const ParametersParser&, Context&){ quit<false>(); }
+ [](const ParametersParser&, Context&, const ShellContext&){ quit<false>(); }
};
const CommandDesc force_quit_cmd = {
@@ -320,7 +320,7 @@ const CommandDesc force_quit_cmd = {
CommandFlags::None,
CommandHelper{},
CommandCompleter{},
- [](const ParametersParser&, Context&){ quit<true>(); }
+ [](const ParametersParser&, Context&, const ShellContext&){ quit<true>(); }
};
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<false>();
}
};
@@ -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<true>();
}
};
@@ -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<false>();
@@ -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<bool next>
-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<bool force>
-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);
@@ -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);
@@ -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<String> 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) {
- CommandManager::instance().execute(commands, context, params_to_shell(parser));
+ 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);
};
}
@@ -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) };
};
}
@@ -852,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]));
@@ -871,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
@@ -894,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"))
@@ -924,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")
{
@@ -975,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
@@ -1016,23 +1018,26 @@ 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{};
},
- [](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"))
@@ -1063,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");
@@ -1093,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;
@@ -1171,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]);
@@ -1311,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;
@@ -1333,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);
@@ -1354,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");
@@ -1388,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");
@@ -1434,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];
@@ -1459,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)
@@ -1501,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();
@@ -1513,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);
}
}
};
@@ -1538,13 +1543,13 @@ const CommandDesc face_cmd = {
"facespec format is <fg color>[,<bg color>][+<attributes>]\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,
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);
@@ -1561,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]);
@@ -1578,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<String>(parser[1]);
}
@@ -1592,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]);
}
@@ -1606,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]));
@@ -1647,7 +1652,7 @@ void exec_keys(ConstArrayView<Key> 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)
{
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<Attribute> : 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;
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/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); }
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<String> params, ConstArra
std::pair<String, int> ShellManager::eval(
StringView cmdline, const Context& context, StringView input,
- Flags flags, ConstArrayView<String> 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<String, int> 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<String, int> 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<String (StringView name, const Context&)>;
+struct ShellContext
+{
+ ConstArrayView<String> params;
+ EnvVarMap env_vars;
+};
+
class ShellManager : public Singleton<ShellManager>
{
public:
@@ -28,8 +34,7 @@ public:
std::pair<String, int> eval(StringView cmdline, const Context& context,
StringView input = {},
Flags flags = Flags::WaitForStdout,
- ConstArrayView<String> 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;