mirror of
https://github.com/mawww/kakoune.git
synced 2024-08-16 16:20:38 +03:00
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.
This commit is contained in:
parent
688e87d668
commit
1bdae3f9c4
@ -3,6 +3,10 @@
|
||||
This changelog contains major and/or breaking changes to Kakoune between
|
||||
released versions.
|
||||
|
||||
== Development version
|
||||
|
||||
* Expose env vars that are mentionned in the arguments passed to shell expansions
|
||||
|
||||
== Kakoune 2024.05.18
|
||||
|
||||
* Fixed tests on Alpine Linux and *BSD
|
||||
|
@ -146,14 +146,16 @@ and unquote them, then execute the resulting `set` command, which sets
|
||||
the shell's argument variables to the items from `$kak_selections`. The
|
||||
`while` loop with `shift` iterates through the arguments one by one.
|
||||
|
||||
Only variables actually mentioned in the body of the shell expansion will
|
||||
be exported into the shell's environment. For example:
|
||||
Only variables actually mentioned in the body of the shell expansion or
|
||||
in passed arguments will be exported into the shell's environment.
|
||||
|
||||
For example:
|
||||
|
||||
----
|
||||
echo %sh{ env | grep ^kak_ }
|
||||
----
|
||||
|
||||
... will find none of Kakoune's special environment variables, but:
|
||||
... will not find any of Kakoune's special environment variables, but:
|
||||
|
||||
----
|
||||
echo %sh{ env | grep ^kak_ # kak_session }
|
||||
@ -162,6 +164,15 @@ echo %sh{ env | grep ^kak_ # kak_session }
|
||||
... will find the `$kak_session` variable because it was mentioned by name
|
||||
in a comment, even though it wasn't directly used.
|
||||
|
||||
----
|
||||
define-command -params .. eval-shell %{ echo %sh{ eval "$@" } }
|
||||
eval-shell 'echo $kak_session'
|
||||
----
|
||||
|
||||
... will also find the `$kak_session` variable because it was mentioned by name
|
||||
in the command arguments, which are automatically made available to shell blocks
|
||||
as "$@"
|
||||
|
||||
TIP: These environment variables are also available in other contexts where
|
||||
Kakoune uses a shell command, such as the `|`, `!` or `$` normal mode commands
|
||||
(See <<keys#,`:doc keys`>>).
|
||||
|
@ -45,6 +45,9 @@ struct {
|
||||
unsigned int version;
|
||||
StringView notes;
|
||||
} constexpr version_notes[] = { {
|
||||
0,
|
||||
"» kak_* appearing in shell arguments will be added to the environment\n"
|
||||
}, {
|
||||
20240518,
|
||||
"» Fix tests failing on some platforms\n"
|
||||
}, {
|
||||
|
@ -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 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
|
||||
auto add_matches = [&](StringView s) {
|
||||
for (auto&& match : RegexIterator{s.begin(), s.end(), re})
|
||||
{
|
||||
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&) {}
|
||||
}
|
||||
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;
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user