From ffa79d731cb7d7bfa75ecbf90473b66e05fa2db0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 5 Mar 2022 12:29:55 +0530 Subject: [PATCH] Allow configuring the ssh kitten via env vars --- docs/conf.rst | 6 +++++- docs/kittens/ssh.rst | 5 +++++ kittens/ssh/main.py | 6 +++++- kitty/conf/utils.py | 19 ++++++++++++++++++- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/docs/conf.rst b/docs/conf.rst index 4d90920fd..2f6086552 100644 --- a/docs/conf.rst +++ b/docs/conf.rst @@ -29,10 +29,14 @@ you use a relative path for :code:`include`, it is resolved with respect to the location of the current config file. Note that environment variables are expanded, so :code:`${USER}.conf` becomes :file:`name.conf` if :code:`USER=name`. Also, you can use :code:`globinclude` to include files -matching a shell glob pattern. For example:: +matching a shell glob pattern and :code:`envinclude` to include configuration +from environment variables. For example:: include other.conf + # Include *.conf files from all subdirs of kitty.d inside the kitty config dir globinclude kitty.d/**/*.conf + # Include the *contents* of all env vars starting with KITTY_CONF_ + envinclude KITTY_CONF_* .. note:: Syntax highlighting for :file:`kitty.conf` in vim is available via diff --git a/docs/kittens/ssh.rst b/docs/kittens/ssh.rst index 6b89d9c66..80548238f 100644 --- a/docs/kittens/ssh.rst +++ b/docs/kittens/ssh.rst @@ -50,6 +50,11 @@ quick example: copy --dest=foo/bar some-file copy --glob some/files.* + # Include some config from environment variables. + # This will read config directives from the contents + # of all environemnt variables starting with SSH_KITTEN_ + envinclude SSH_KITTEN_* + See below for full details on the syntax and options of :file:`ssh.conf`. diff --git a/kittens/ssh/main.py b/kittens/ssh/main.py index d10b69dcb..1a17b89d8 100644 --- a/kittens/ssh/main.py +++ b/kittens/ssh/main.py @@ -107,7 +107,11 @@ def make_tarfile(ssh_opts: SSHOptions, base_env: Dict[str, str]) -> bytes: add_data_as_file(tf, 'data.sh', env_script) if ksi: arcname = 'home/' + rd + '/shell-integration' - tf.add(shell_integration_dir, arcname=arcname, filter=filter_from_globs(f'{arcname}/ssh/bootstrap.*')) + tf.add(shell_integration_dir, arcname=arcname, filter=filter_from_globs( + f'{arcname}/ssh/bootstrap.*', # bootstrap files are sent as command line args + f'{arcname}/zsh/kitty.zsh', # present for legacy compat not needed by ssh kitten + '*/.DS_Store', + )) tf.add(terminfo_dir, arcname='home/.terminfo', filter=normalize_tarinfo) return buf.getvalue() diff --git a/kitty/conf/utils.py b/kitty/conf/utils.py index 8026a0ce7..769ce5306 100644 --- a/kitty/conf/utils.py +++ b/kitty/conf/utils.py @@ -156,6 +156,16 @@ class CurrentlyParsing: currently_parsing = CurrentlyParsing() +class NamedLineIterator: + + def __init__(self, name: str, lines: Iterator[str]): + self.lines = lines + self.name = name + + def __iter__(self) -> Iterator[str]: + return self.lines + + def parse_line( line: str, parse_conf_item: ItemParser, @@ -171,11 +181,18 @@ def parse_line( log_error(f'Ignoring invalid config line: {line}') return key, val = m.groups() - if key in ('include', 'globinclude'): + if key in ('include', 'globinclude', 'envinclude'): val = os.path.expandvars(os.path.expanduser(val.strip())) if key == 'globinclude': from pathlib import Path vals = tuple(map(lambda x: str(os.fspath(x)), Path(base_path_for_includes).glob(val))) + elif key == 'envinclude': + from fnmatch import fnmatchcase + for x in os.environ: + if fnmatchcase(x, val): + with currently_parsing.set_file(f''): + _parse(NamedLineIterator(base_path_for_includes, iter(os.environ[x].splitlines())), parse_conf_item, ans, accumulate_bad_lines) + return else: if not os.path.isabs(val): val = os.path.join(base_path_for_includes, val)