summaryrefslogtreecommitdiff
path: root/src/shell_manager.cc
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2024-06-07 18:59:30 +1000
committerMaxime Coste <mawww@kakoune.org>2024-06-07 18:59:30 +1000
commit1bdae3f9c4e554c62100560d48957d42f5ae17e0 (patch)
treefc82d30be7e0c5fa45ac01dc361280cc2fcb460f /src/shell_manager.cc
parent688e87d6689aac60423c20195005ef12858787d1 (diff)
Also check shell parameters for kak_* references
This makes it easier to pass shell fragments as arguments so that %sh{ eval "$@" } just works even if arguments refer to Kakoune's vars.
Diffstat (limited to 'src/shell_manager.cc')
-rw-r--r--src/shell_manager.cc47
1 files changed, 26 insertions, 21 deletions
diff --git a/src/shell_manager.cc b/src/shell_manager.cc
index e505fdef..47432df5 100644
--- a/src/shell_manager.cc
+++ b/src/shell_manager.cc
@@ -141,30 +141,35 @@ Shell spawn_shell(const char* shell, StringView cmdline,
}
template<typename GetValue>
-Vector<String> generate_env(StringView cmdline, const Context& context, GetValue&& get_value)
+Vector<String> generate_env(StringView cmdline, ConstArrayView<String> params, const Context& context, GetValue&& get_value)
{
static const Regex re(R"(\bkak_(quoted_)?(\w+)\b)");
Vector<String> env;
- for (auto&& match : RegexIterator{cmdline.begin(), cmdline.end(), re})
- {
- StringView name{match[2].first, match[2].second};
- StringView shell_name{match[0].first, match[0].second};
+ auto add_matches = [&](StringView s) {
+ for (auto&& match : RegexIterator{s.begin(), s.end(), re})
+ {
+ StringView name{match[2].first, match[2].second};
+ StringView shell_name{match[0].first, match[0].second};
- auto match_name = [&](const String& s) {
- return s.substr(0_byte, shell_name.length()) == shell_name and
- s.substr(shell_name.length(), 1_byte) == "=";
- };
- if (any_of(env, match_name))
- continue;
+ auto match_name = [&](const String& s) {
+ return s.substr(0_byte, shell_name.length()) == shell_name and
+ s.substr(shell_name.length(), 1_byte) == "=";
+ };
+ if (any_of(env, match_name))
+ continue;
- try
- {
- StringView quoted{match[1].first, match[1].second};
- Quoting quoting = match[1].matched ? Quoting::Shell : Quoting::Raw;
- env.push_back(format("kak_{}{}={}", quoted, name, get_value(name, quoting)));
- } catch (runtime_error&) {}
- }
+ try
+ {
+ StringView quoted{match[1].first, match[1].second};
+ Quoting quoting = match[1].matched ? Quoting::Shell : Quoting::Raw;
+ env.push_back(format("kak_{}{}={}", quoted, name, get_value(name, quoting)));
+ } catch (runtime_error&) {}
+ }
+ };
+ add_matches(cmdline);
+ for (auto&& param : params)
+ add_matches(param);
return env;
}
@@ -265,13 +270,13 @@ std::pair<String, int> ShellManager::eval(
const DebugFlags debug_flags = context.options()["debug"].get<DebugFlags>();
const bool profile = debug_flags & DebugFlags::Profile;
if (debug_flags & DebugFlags::Shell)
- write_to_debug_buffer(format("shell:\n{}\n----\n", cmdline));
+ write_to_debug_buffer(format("shell:\n{}\n----\nargs: {}\n----\n", cmdline, join(shell_context.params | transform(shell_quote), ' ')));
auto start_time = profile ? Clock::now() : Clock::time_point{};
Optional<CommandFifos> command_fifos;
- auto kak_env = generate_env(cmdline, context, [&](StringView name, Quoting quoting) {
+ auto kak_env = generate_env(cmdline, shell_context.params, context, [&](StringView name, Quoting quoting) {
if (name == "command_fifo" or name == "response_fifo")
{
if (not command_fifos)
@@ -377,7 +382,7 @@ std::pair<String, int> ShellManager::eval(
Shell ShellManager::spawn(StringView cmdline, const Context& context,
bool open_stdin, const ShellContext& shell_context)
{
- auto kak_env = generate_env(cmdline, context, [&](StringView name, Quoting quoting) {
+ auto kak_env = generate_env(cmdline, shell_context.params, context, [&](StringView name, Quoting quoting) {
if (auto it = shell_context.env_vars.find(name); it != shell_context.env_vars.end())
return it->value;
return join(get_val(name, context) | transform(quoter(quoting)), ' ', false);