From 8a1a46a3b0c2e312af9a4cc0d7c24011d8fbab11 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sat, 16 Dec 2023 11:23:21 +0100 Subject: [PATCH] Option to override environment variables in child processes Today I have to restart Kakoune in order to set environment variables in shell expansions globally. For example KAK_LSP_FORCE_PROJECT_ROOT. When running ":git" commands, there is an ambiguity on whether to use the $PWD or the buffer's worktree. We use $PWD but it should be possible to override this behavior. An obvious way to do this is to override Git environment variables: set-option -add global env GIT_WORK_TREE=/path/to/my/repo GIT_DIR=/path/to/my/repo.git (another in-flight patch adds the obvious default to GIT_DIR so we don't need to set that). --- There are some minor issues left - If a user sets PATH, this will stomp the one we setenv()'d. - Today both key and value require escaping for = and \. This is not intuitive. Since neither environment variables nor ui_options ever need a = in the key name, we can get rid of the escaping. Alternative approach: The str-to-str-map can be somewhat clunky. We could instead export any option named like env_FOO. Not yet sure which approach is better. Closes #4482 That issues asks for a separate client-specific env as well but we don't have a client scope so I'm not sure. --- doc/pages/options.asciidoc | 6 ++++++ src/main.cc | 3 +++ src/shell_manager.cc | 2 ++ 3 files changed, 11 insertions(+) diff --git a/doc/pages/options.asciidoc b/doc/pages/options.asciidoc index 4f69cbfb7e..9f7b241d7b 100644 --- a/doc/pages/options.asciidoc +++ b/doc/pages/options.asciidoc @@ -189,6 +189,9 @@ are exclusively available to built-in options. key is provided it removes that entry regardless of the associated value. + + Any `=` or `\` characters that in `key` and `value` must be escaped as + `\=` or `\\`. + Only `str-to-str-map` options can be created with `declare-option`. == Builtin options @@ -340,6 +343,9 @@ are exclusively available to built-in options. The default value is '%val{bufname} %val{cursor_line}:%val{cursor_char_column} {{context_info}} {{mode_info}} - %val{client}@[%val{session}]' +*env* `str-to-str-map`:: + a list of environment variable overrides to be passed to external processes. + *ui_options* `str-to-str-map`:: a list of `key=value` pairs that are forwarded to the user interface implementation. The NCurses UI supports the following options: diff --git a/src/main.cc b/src/main.cc index 4d14565a63..bca233f361 100644 --- a/src/main.cc +++ b/src/main.cc @@ -574,6 +574,9 @@ void register_options() reg.declare_option( "fs_check_timeout", "timeout, in milliseconds, between file system buffer modification checks", 500); + reg.declare_option("env", + "a list of environment variable overrides to be passed to external processes", + HashMap{}); reg.declare_option("ui_options", "space separated list of = options that are " "passed to and interpreted by the user interface\n" diff --git a/src/shell_manager.cc b/src/shell_manager.cc index e505fdef10..2b8ed013db 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -146,6 +146,8 @@ Vector generate_env(StringView cmdline, const Context& context, GetValue static const Regex re(R"(\bkak_(quoted_)?(\w+)\b)"); Vector env; + for (const auto& [key, value] : context.options()["env"].get>()) + env.push_back(format("{}={}", key, value)); for (auto&& match : RegexIterator{cmdline.begin(), cmdline.end(), re}) { StringView name{match[2].first, match[2].second};