formats['text'] = '48' + color_as_sgr(opts.background) formats['title'] = '38' + color_as_sgr(opts.title_fg) + ';48' + color_as_sgr(opts.title_bg) + ';1' formats['margin'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.margin_bg) formats['added_margin'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.added_margin_bg) formats['removed_margin'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.removed_margin_bg) formats['added'] = '48' + color_as_sgr(opts.added_bg) formats['removed'] = '48' + color_as_sgr(opts.removed_bg) formats['filler'] = '48' + color_as_sgr(opts.filler_bg) formats['margin_filler'] = '48' + color_as_sgr(opts.margin_filler_bg or opts.filler_bg) formats['hunk_margin'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.hunk_margin_bg) formats['hunk'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.hunk_bg) formats['removed_highlight'] = '48' + color_as_sgr(opts.highlight_removed_bg) formats['added_highlight'] = '48' + color_as_sgr(opts.highlight_added_bg) func_with_args, args_funcs = key_func() @func_with_args('scroll_by') def parse_scroll_by(func: str, rest: str) -> Tuple[str, int]: try: return func, int(rest) except Exception: return func, 1 @func_with_args('scroll_to') def parse_scroll_to(func: str, rest: str) -> Tuple[str, str]: rest = rest.lower() if rest not in {'start', 'end', 'next-change', 'prev-change', 'next-page', 'prev-page', 'next-match', 'prev-match'}: rest = 'start'
def parse_opts() -> Options: all_options = {} # type: OptionDefs o, k, g, _all_groups = option_func( all_options, { 'shortcuts': ['Keyboard shortcuts'], 'colors': ['Colors'], 'behavior': ['Behavior'] }) g('shortcuts') k('quit', 'q', 'quit') k('quit', 'esc', 'quit') k('confirm', 'enter', 'confirm') k('left', 'left', 'move left') k('right', 'right', 'move right') k('up', 'up', 'move up') k('down', 'down', 'move down') k('page up', 'page_up', 'move page up') k('page down', 'page_down', 'move page down') k('start of line', 'home', 'move first') k('first non-whitespace', 'a', 'move first nonwhite') k('last non-whitespace', 'end', 'move last nonwhite') k('end of line', 'e', 'move last') k('start of buffer', 'ctrl+home', 'move top') k('end of buffer', 'ctrl+end', 'move bottom') k('word left', 'ctrl+left', 'move word left') k('word right', 'ctrl+right', 'move word right') k('scroll up', 'ctrl+up', 'scroll up') k('scroll down', 'ctrl+down', 'scroll down') k('select left', 'shift+left', 'select stream left') k('select right', 'shift+right', 'select stream right') k('select up', 'shift+up', 'select stream up') k('select down', 'shift+down', 'select stream down') k('select page up', 'shift+page_up', 'select stream page up') k('select page down', 'shift+page_down', 'select stream page down') k('select to start of line', 'shift+home', 'select stream first') k('select to first non-whitespace', 'A', 'select stream first nonwhite') k('select to last non-whitespace', 'shift+end', 'select stream last nonwhite') k('select to end of line', 'E', 'select stream last') k('select to start of buffer', 'shift+ctrl+home', 'select stream top') k('select to end of buffer', 'shift+ctrl+end', 'select stream bottom') k('select word left', 'shift+ctrl+left', 'select stream word left') k('select word right', 'shift+ctrl+right', 'select stream word right') k('column select left', 'alt+left', 'select columnar left') k('column select right', 'alt+right', 'select columnar right') k('column select up', 'alt+up', 'select columnar up') k('column select down', 'alt+down', 'select columnar down') k('column select page up', 'alt+page_up', 'select columnar page up') k('column select page down', 'alt+page_down', 'select columnar page down') k('column select to start of line', 'alt+home', 'select columnar first') k('column select to first non-whitespace', 'alt+A', 'select columnar first nonwhite') k('column select to last non-whitespace', 'alt+end', 'select columnar last nonwhite') k('column select to end of line', 'alt+E', 'select columnar last') k('column select to start of buffer', 'alt+ctrl+home', 'select columnar top') k('column select to end of buffer', 'alt+ctrl+end', 'select columnar bottom') k('column select word left', 'alt+ctrl+left', 'select columnar word left') k('column select word right', 'alt+ctrl+right', 'select columnar word right') g('colors') o('selection_foreground', '#FFFFFF', option_type=to_color) o('selection_background', '#5294E2', option_type=to_color) g('behavior') o('select_by_word_characters', json.loads(os.getenv('KITTY_COMMON_OPTS'))['select_by_word_characters'], option_type=str) type_map = TypeConvert({ o.name: o.option_type for o in all_options.values() if hasattr(o, 'option_type') }) defaults = None # Parsers/validators for key binding directives func_with_args, args_funcs = key_func() def parse_region_type(region_type: str) -> str: result = region_type.lower() assert result in ['stream', 'columnar'] return result def parse_direction(direction: str) -> str: direction_lc = direction.lower() assert direction_lc in [ 'left', 'right', 'up', 'down', 'page up', 'page down', 'first', 'first nonwhite', 'last nonwhite', 'last', 'top', 'bottom', 'word left', 'word right' ] return direction_lc.replace(' ', '_') def parse_scroll_direction(direction: str) -> str: result = direction.lower() assert result in ['up', 'down'] return result @func_with_args('move') def move(func: Callable, direction: str) -> Tuple[Callable, str]: return func, parse_direction(direction) @func_with_args('scroll') def scroll(func: Callable, direction: str) -> Tuple[Callable, str]: return func, parse_scroll_direction(direction) @func_with_args('select') def select(func: Callable, args: str) -> Tuple[Callable, Tuple[str, str]]: region_type, direction = args.split(' ', 1) return func, (parse_region_type(region_type), parse_direction(direction)) def parse_kittens_key( val: str, args_funcs: Dict[str, Callable] ) -> Optional[Tuple[Tuple[ActionName, ActionArgs], KeyName, ShortcutMods, bool]]: parsed_key = _parse_kittens_key(val, args_funcs) if parsed_key is None: return None if len(parsed_key) == 2: # kitty ≥ 0.17.0 action, (key, mods, is_text) = parsed_key else: # kitty < 0.17.0 action, key, mods, is_text = parsed_key return (action, key, mods, is_text and (0 == (mods or 0) & (kk.CTRL | kk.ALT | kk.SUPER))) # Configuration reader helpers def special_handling(key: OptionName, val: str, result: OptionValues) -> bool: if key == 'map': action, *key_def = parse_kittens_key(val, args_funcs) result['key_definitions'][tuple(key_def)] = action return True return False def parse_config(lines: List[str], check_keys: bool = True) -> OptionValues: result = {'key_definitions': {}} # type: OptionValues parse_config_base(lines, defaults, type_map, special_handling, result, check_keys=check_keys) return result def merge_configs(defaults: OptionValues, vals: OptionValues) -> OptionValues: return { k: (merge_dicts(v, vals.get(k, {})) if isinstance(v, dict) else vals.get(k, v)) for k, v in defaults.items() } Options, defaults = init_config(config_lines(all_options), parse_config) configs = list( resolve_config('/etc/xdg/kitty/grab.conf', os.path.join(config_dir, 'grab.conf'), config_files_on_cmd_line=None)) return load_config(Options, defaults, parse_config, merge_configs, *configs)