Add an option :opt:env to set environment variables in child processes from kitty.conf

This commit is contained in:
Kovid Goyal
2018-07-15 12:16:43 +05:30
parent b3e2562c00
commit 9918397190
5 changed files with 93 additions and 17 deletions

View File

@@ -13,6 +13,8 @@ Changelog
- Render the text under the cursor in a fixed color, configurable via
the option :opt:`cursor_text_color` (:iss:`126`)
- Add an option :opt:`env` to set environment variables in child processes
from kitty.conf
0.11.3 [2018-07-10]
------------------------------

View File

@@ -30,6 +30,20 @@ def remove_cloexec(fd):
fcntl.fcntl(fd, fcntl.F_SETFD, fcntl.fcntl(fd, fcntl.F_GETFD) & ~fcntl.FD_CLOEXEC)
def default_env():
try:
return default_env.env
except AttributeError:
return os.environ
def set_default_env(val=None):
env = os.environ.copy()
if val:
env.update(val)
default_env.env = env
class Child:
child_fd = pid = None
@@ -63,7 +77,7 @@ class Child:
remove_cloexec(stdin_read_fd)
else:
stdin_read_fd = stdin_write_fd = -1
env = os.environ.copy()
env = default_env().copy()
env.update(self.env)
env['TERM'] = self.opts.term
env['COLORTERM'] = 'truecolor'

View File

@@ -245,28 +245,68 @@ def parse_send_text(val, key_definitions):
return parse_key(key_str, key_definitions)
special_handlers = {}
def special_handler(func):
special_handlers[func.__name__.partition('_')[2]] = func
@special_handler
def handle_map(key, val, ans):
parse_key(val, ans['key_definitions'])
@special_handler
def handle_symbol_map(key, val, ans):
ans['symbol_map'].update(parse_symbol_map(val))
@special_handler
def handle_send_text(key, val, ans):
# For legacy compatibility
parse_send_text(val, ans['key_definitions'])
@special_handler
def handle_clear_all_shortcuts(key, val, ans):
if to_bool(val):
ans['key_definitions'] = [None]
def expandvars(val, env):
def sub(m):
key = m.group(1)
result = env.get(key)
if result is None:
result = os.environ.get(key)
if result is None:
result = m.group()
return result
return re.sub(r'$\{(\S+)\}', sub, val)
@special_handler
def handle_env(key, val, ans):
key, val = val.partition('=')[::2]
key, val = key.strip(), val.strip()
ans['env'][key] = expandvars(val, ans['env'])
def special_handling(key, val, ans):
if key == 'map':
parse_key(val, ans['key_definitions'])
func = special_handlers.get(key)
if func is not None:
func(key, val, ans)
return True
if key == 'symbol_map':
ans['symbol_map'].update(parse_symbol_map(val))
return True
if key == 'send_text':
# For legacy compatibility
parse_send_text(val, ans['key_definitions'])
return True
if key == 'clear_all_shortcuts':
if to_bool(val):
ans['key_definitions'] = [None]
return
defaults = None
def parse_config(lines, check_keys=True):
ans = {'symbol_map': {}, 'keymap': {}, 'sequence_map': {}, 'key_definitions': []}
ans = {'symbol_map': {}, 'keymap': {}, 'sequence_map': {}, 'key_definitions': [], 'env': {}}
parse_config_base(
lines,
defaults,

View File

@@ -646,6 +646,19 @@ opening new windows, closing windows, reading the content of windows, etc.
Note that this even works over ssh connections.
'''))
o(
'+env', '',
add_to_default=False,
long_text=_('''
Specify environment variables to set in all child processes. Note that
environment variables are expanded recursively, so if you use::
env MYVAR1=a
env MYVAR2=${MYVAR}/${HOME}/b
The value of MYVAR2 will be :code:`a/<path to home directory>/b`.
'''))
def startup_session(x):
if x.lower() == 'none':

View File

@@ -9,6 +9,7 @@ from contextlib import contextmanager
from .borders import load_borders_program
from .boss import Boss
from .child import set_default_env
from .cli import create_opts, parse_args
from .config import cached_values_for, initial_window_size_func
from .constants import (
@@ -202,6 +203,13 @@ def macos_cmdline():
return ans
def setup_environment(opts):
extra_env = opts.env.copy()
if opts.editor != '.':
os.environ['EDITOR'] = opts.editor
set_default_env(extra_env)
def _main():
try:
sys.setswitchinterval(1000.0) # we have only a single python thread
@@ -256,8 +264,7 @@ def _main():
return
init_glfw(args.debug_keyboard) # needed for parsing native keysyms
opts = create_opts(args)
if opts.editor != '.':
os.environ['EDITOR'] = opts.editor
setup_environment(opts)
try:
with setup_profiling(args):
# Avoid needing to launch threads to reap zombies