diff --git a/kitty/config.py b/kitty/config.py index fce0137f0..c6acd5106 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -182,6 +182,7 @@ with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'kitty.conf') defaults = parse_config(f.readlines()) Options = namedtuple('Defaults', ','.join(defaults.keys())) defaults = Options(**defaults) +actions = frozenset(defaults.keymap.values()) def update_dict(a, b): @@ -193,22 +194,27 @@ def merge_dicts(vals, defaults): return {k: update_dict(v, vals.get(k, {})) if isinstance(v, dict) else vals.get(k, v) for k, v in defaults.items()} -def load_config(path: str) -> Options: - if not path: - return defaults - try: - f = open(path) - except FileNotFoundError: - return defaults - ans = defaults._asdict() - actions = frozenset(defaults.keymap.values()) - with f: - vals = parse_config(f) - remove_keys = {k for k, v in vals.get('keymap', {}).items() if v in ('noop', 'no-op', 'no_op')} +def merge_configs(ans, vals): vals['keymap'] = {k: v for k, v in vals.get('keymap', {}).items() if v in actions} + remove_keys = {k for k, v in vals.get('keymap', {}).items() if v in ('noop', 'no-op', 'no_op')} ans = merge_dicts(vals, ans) for k in remove_keys: ans['keymap'].pop(k, None) + return ans + + +def load_config(*paths) -> Options: + ans = defaults._asdict() + for path in paths: + if not path: + continue + try: + f = open(path) + except FileNotFoundError: + continue + with f: + vals = parse_config(f) + ans = merge_configs(ans, vals) return Options(**ans) diff --git a/kitty/main.py b/kitty/main.py index 5cfd60348..7dce730fd 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -30,13 +30,14 @@ from .layout import all_layouts from .shaders import GL_VERSION from .utils import safe_print +defconf = os.path.join(config_dir, 'kitty.conf') + def option_parser(): parser = argparse.ArgumentParser( prog=appname, description=_('The {} terminal emulator').format(appname) ) - defconf = os.path.join(config_dir, 'kitty.conf') a = parser.add_argument a( '--class', @@ -46,9 +47,12 @@ def option_parser(): ) a( '--config', - default=defconf, - help=_('Specify a path to the config file to use. Default: {}') - .format(defconf) + action='append', + help=_( + 'Specify a path to the config file(s) to use.' + ' Can be specified multiple times to read multiple' + ' config files in sequence, which are merged. Default: {}' + ).format(defconf) ) a( '--cmd', @@ -208,7 +212,8 @@ def main(): from kitty.client import main main(args.replay_commands) return - opts = load_config(args.config) + config = args.config or (defconf, ) + opts = load_config(*config) change_wcwidth(not opts.use_system_wcwidth) glfw_set_error_callback(on_glfw_error) enable_automatic_opengl_error_checking(False)