diff --git a/kittens/diff/config.py b/kittens/diff/config.py index 1d4f16e6f..de5b678a6 100644 --- a/kittens/diff/config.py +++ b/kittens/diff/config.py @@ -2,8 +2,78 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2018, Kovid Goyal +import os + +from kitty.config_utils import ( + init_config, load_config as _load_config, merge_dicts, parse_config_base, + resolve_config, to_color +) +from kitty.constants import config_dir + +defaults = None +default_config_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), 'diff.conf' +) + formats = { 'title': '', 'margin': '', 'text': '', } + +type_map = {} + +for name in ( + 'foreground background' +).split(): + type_map[name] = to_color + + +def special_handling(*a): + pass + + +def parse_config(lines, check_keys=True): + ans = {} + parse_config_base( + lines, + defaults, + type_map, + special_handling, + ans, + check_keys=check_keys + ) + return ans + + +def merge_configs(defaults, vals): + ans = {} + for k, v in defaults.items(): + if isinstance(v, dict): + newvals = vals.get(k, {}) + ans[k] = merge_dicts(v, newvals) + else: + ans[k] = vals.get(k, v) + return ans + + +def parse_defaults(lines, check_keys=False): + return parse_config(lines, check_keys) + + +Options, defaults = init_config(default_config_path, parse_defaults) + + +def load_config(*paths, overrides=None): + return _load_config(Options, defaults, parse_config, merge_configs, *paths, overrides=overrides) + + +SYSTEM_CONF = '/etc/xdg/kitty/diff.conf' +defconf = os.path.join(config_dir, 'diff.conf') + + +def init_config(args): + config = tuple(resolve_config(SYSTEM_CONF, defconf, args.config)) + overrides = (a.replace('=', ' ', 1) for a in args.override or ()) + opts = load_config(*config, overrides=overrides) + return opts diff --git a/kittens/diff/diff.conf b/kittens/diff/diff.conf new file mode 100644 index 000000000..0a83c564a --- /dev/null +++ b/kittens/diff/diff.conf @@ -0,0 +1,2 @@ +foreground black +background #eeeeee diff --git a/kittens/diff/main.py b/kittens/diff/main.py index 2d0af910b..100f41a2b 100644 --- a/kittens/diff/main.py +++ b/kittens/diff/main.py @@ -7,13 +7,14 @@ import sys from functools import partial from gettext import gettext as _ -from kitty.cli import parse_args +from kitty.cli import CONFIG_HELP, appname, parse_args from kitty.key_encoding import ESCAPE from ..tui.handler import Handler from ..tui.loop import Loop from ..tui.operations import clear_screen, set_line_wrapping, set_window_title from .collect import create_collection, data_for_path +from .config import init_config from .git import Differ from .render import render_diff @@ -59,6 +60,9 @@ class DiffHandler(Handler): self.draw_screen() self.create_collection() + def finalize(self): + pass + def draw_screen(self): if self.state < DIFFED: self.write(clear_screen()) @@ -117,7 +121,19 @@ OPTIONS = partial('''\ type=int default=3 Number of lines of context to show between changes. -'''.format, ) + + +--config +type=list +{config_help} + + +--override -o +type=list +Override individual configuration options, can be specified multiple times. +Syntax: |_ name=value|. For example: |_ -o background=gray| + +'''.format, config_help=CONFIG_HELP.format(conf_name='diff', appname=appname)) def main(args): @@ -128,6 +144,7 @@ def main(args): left, right = items if os.path.isdir(left) != os.path.isdir(right): raise SystemExit('The items to be diffed should both be either directories or files. Comparing a directory to a file is not valid.') + init_config(args) loop = Loop() handler = DiffHandler(args, left, right) diff --git a/kittens/tui/operations.py b/kittens/tui/operations.py index caf6cb528..c6cd0a6f1 100644 --- a/kittens/tui/operations.py +++ b/kittens/tui/operations.py @@ -5,6 +5,7 @@ import sys from contextlib import contextmanager +from kitty.rgb import color_as_sharp, to_color from kitty.terminfo import string_capabilities S7C1T = '\033 F' @@ -160,3 +161,16 @@ def alternate_screen(f=None): print(set_mode('ALTERNATE_SCREEN'), end='', file=f) yield print(reset_mode('ALTERNATE_SCREEN'), end='', file=f) + + +def set_default_colors(fg=None, bg=None): + ans = '' + if fg is None: + ans += '\x1b]110\x1b\\' + else: + ans += '\x1b]10;{}\x1b\\'.format(color_as_sharp(to_color(fg))) + if bg is None: + ans += '\x1b]111\x1b\\' + else: + ans += '\x1b]11;{}\x1b\\'.format(color_as_sharp(to_color(bg))) + return ans diff --git a/kitty/cli.py b/kitty/cli.py index 0f103ecc0..023d07dbc 100644 --- a/kitty/cli.py +++ b/kitty/cli.py @@ -9,9 +9,30 @@ import sys from collections import deque from .config import defaults, load_config +from .config_utils import resolve_config from .constants import appname, defconf, is_macos, is_wayland, str_version from .layout import all_layouts +CONFIG_HELP = '''\ +Specify a path to the configuration file(s) to use. All configuration files are +merged onto the builtin {conf_name}.conf, overriding the builtin values. This option +can be specified multiple times to read multiple configuration files in +sequence, which are merged. Use the special value NONE to not load a config +file. + +If this option is not specified, config files are searched for in the order: +"$XDG_CONFIG_HOME/{appname}/{conf_name}.conf", "~/.config/{appname}/{conf_name}.conf", {macos_confpath} +"$XDG_CONFIG_DIRS/{appname}/{conf_name}.conf". The first one that exists is used as the +config file. + +If the environment variable "KITTY_CONFIG_DIRECTORY" is specified, that +directory is always used and the above searching does not happen. + +If "/etc/xdg/{appname}/{conf_name}.conf" exists it is merged before (i.e. with lower +priority) than any user config files. It can be used to specify system-wide +defaults for all users. +'''.replace('{macos_confpath}', '~/Library/Preferences/{appname}/{conf_name}.conf, ' if is_macos else '') + OPTIONS = ''' --class dest=cls @@ -32,24 +53,7 @@ only use this if you are running a program that does not set titles. --config type=list -Specify a path to the configuration file(s) to use. All configuration files are -merged onto the builtin kitty.conf, overriding the builtin values. This option -can be specified multiple times to read multiple configuration files in -sequence, which are merged. Use the special value NONE to not load a config -file. - -If this option is not specified, config files are searched for in the order: -"$XDG_CONFIG_HOME/kitty/kitty.conf", "~/.config/kitty/kitty.conf", {macos_confpath} -"$XDG_CONFIG_DIRS/kitty/kitty.conf". The first one that exists is used as the -config file. - -If the environment variable "KITTY_CONFIG_DIRECTORY" is specified, that -directory is always used and the above searching does not happen. - -If "/etc/xdg/kitty/kitty.conf" exists it is merged before (i.e. with lower -priority) than any user config files. It can be used to specify system-wide -defaults for all users. - +{config_help} --override -o type=list @@ -480,7 +484,7 @@ def parse_cmdline(oc, disabled, args=None): def options_spec(): if not hasattr(options_spec, 'ans'): options_spec.ans = OPTIONS.format( - appname=appname, macos_confpath='~/Library/Preferences/kitty/kitty.conf, ' if is_macos else '', + appname=appname, config_help=CONFIG_HELP.format(conf_name=appname), window_layout_choices=', '.join(all_layouts) ) return options_spec.ans @@ -496,17 +500,6 @@ def parse_args(args=None, ospec=options_spec, usage=None, message=None, appname= SYSTEM_CONF = '/etc/xdg/kitty/kitty.conf' -def resolve_config(config_files_on_cmd_line): - if config_files_on_cmd_line: - if 'NONE' not in config_files_on_cmd_line: - yield SYSTEM_CONF - for cf in config_files_on_cmd_line: - yield cf - else: - yield SYSTEM_CONF - yield defconf - - def print_shortcut(key, action): if not getattr(print_shortcut, 'maps', None): from kitty.keys import defines @@ -555,7 +548,7 @@ def compare_opts(opts): def create_opts(args, debug_config=False): - config = tuple(resolve_config(args.config)) + config = tuple(resolve_config(SYSTEM_CONF, defconf, args.config)) if debug_config: print(version(add_rev=True)) print(' '.join(os.uname())) diff --git a/kitty/config_utils.py b/kitty/config_utils.py index 742151e35..1d5f13aa2 100644 --- a/kitty/config_utils.py +++ b/kitty/config_utils.py @@ -123,6 +123,17 @@ def merge_dicts(defaults, newvals): return ans +def resolve_config(SYSTEM_CONF, defconf, config_files_on_cmd_line): + if config_files_on_cmd_line: + if 'NONE' not in config_files_on_cmd_line: + yield SYSTEM_CONF + for cf in config_files_on_cmd_line: + yield cf + else: + yield SYSTEM_CONF + yield defconf + + def load_config(Options, defaults, parse_config, merge_configs, *paths, overrides=None): ans = defaults._asdict() for path in paths: diff --git a/kitty/rgb.py b/kitty/rgb.py index 1030292e8..92c1bbbc1 100644 --- a/kitty/rgb.py +++ b/kitty/rgb.py @@ -35,6 +35,10 @@ def color_as_int(x): return x.red << 16 | x.green << 8 | x.blue +def color_as_sharp(x): + return '#{:02x}{:02x}{:02x}'.format(*x) + + def to_color(raw, validate=False): # See man XParseColor x = raw.strip().lower()