kitten @ load-config: Allow (re)loading kitty.conf via remote control

This commit is contained in:
Kovid Goyal
2024-02-07 11:08:55 +05:30
parent bc3c9ce2fa
commit 065b17ddbd
5 changed files with 85 additions and 6 deletions

View File

@@ -46,6 +46,8 @@ Detailed list of changes
0.32.2 [future] 0.32.2 [future]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- kitten @ load-config: Allow (re)loading kitty.conf via remote control
- kitten @ send-text: Add a new option to automatically wrap the sent text in - kitten @ send-text: Add a new option to automatically wrap the sent text in
bracketed paste escape codes if the program in the destination window has bracketed paste escape codes if the program in the destination window has
turned on bracketed paste. turned on bracketed paste.

View File

@@ -2539,14 +2539,17 @@ class Boss:
map f5 load_config_file /path/to/some/kitty.conf map f5 load_config_file /path/to/some/kitty.conf
''') ''')
def load_config_file(self, *paths: str, apply_overrides: bool = True) -> None: def load_config_file(self, *paths: str, apply_overrides: bool = True, overrides: Sequence[str] = ()) -> None:
from .cli import default_config_paths from .cli import default_config_paths
from .config import load_config from .config import load_config
old_opts = get_options() old_opts = get_options()
prev_paths = old_opts.all_config_paths or default_config_paths(self.args.config) prev_paths = old_opts.all_config_paths or default_config_paths(self.args.config)
paths = paths or prev_paths paths = paths or prev_paths
bad_lines: List[BadLine] = [] bad_lines: List[BadLine] = []
opts = load_config(*paths, overrides=old_opts.config_overrides if apply_overrides else None, accumulate_bad_lines=bad_lines) final_overrides = old_opts.config_overrides if apply_overrides else ()
if overrides:
final_overrides += tuple(overrides)
opts = load_config(*paths, overrides=final_overrides or None, accumulate_bad_lines=bad_lines)
if bad_lines: if bad_lines:
self.show_bad_config_lines(bad_lines) self.show_bad_config_lines(bad_lines)
self.apply_new_options(opts) self.apply_new_options(opts)

View File

@@ -1066,12 +1066,20 @@ def default_config_paths(conf_paths: Sequence[str]) -> Tuple[str, ...]:
return tuple(resolve_config(SYSTEM_CONF, defconf, conf_paths)) return tuple(resolve_config(SYSTEM_CONF, defconf, conf_paths))
@run_once
def override_pat() -> 're.Pattern[str]':
return re.compile(r'^([a-zA-Z0-9_]+)[ \t]*=')
def parse_override(x: str) -> str:
# Does not cover the case where `name =` when `=` is the value.
return override_pat().sub(r'\1 ', x.lstrip())
def create_opts(args: CLIOptions, accumulate_bad_lines: Optional[List[BadLineType]] = None) -> KittyOpts: def create_opts(args: CLIOptions, accumulate_bad_lines: Optional[List[BadLineType]] = None) -> KittyOpts:
from .config import load_config from .config import load_config
config = default_config_paths(args.config) config = default_config_paths(args.config)
# Does not cover the case where `name =` when `=` is the value. overrides = map(parse_override, args.override or ())
pat = re.compile(r'^([a-zA-Z0-9_]+)[ \t]*=')
overrides = (pat.sub(r'\1 ', a.lstrip()) for a in args.override or ())
opts = load_config(*config, overrides=overrides, accumulate_bad_lines=accumulate_bad_lines) opts = load_config(*config, overrides=overrides, accumulate_bad_lines=accumulate_bad_lines)
return opts return opts

View File

@@ -13,7 +13,7 @@ LaunchCLIOptions = AskCLIOptions = ClipboardCLIOptions = DiffCLIOptions = CLIOpt
HintsCLIOptions = IcatCLIOptions = PanelCLIOptions = ResizeCLIOptions = CLIOptions HintsCLIOptions = IcatCLIOptions = PanelCLIOptions = ResizeCLIOptions = CLIOptions
ErrorCLIOptions = UnicodeCLIOptions = RCOptions = RemoteFileCLIOptions = CLIOptions ErrorCLIOptions = UnicodeCLIOptions = RCOptions = RemoteFileCLIOptions = CLIOptions
QueryTerminalCLIOptions = BroadcastCLIOptions = ShowKeyCLIOptions = CLIOptions QueryTerminalCLIOptions = BroadcastCLIOptions = ShowKeyCLIOptions = CLIOptions
ThemesCLIOptions = TransferCLIOptions = CLIOptions ThemesCLIOptions = TransferCLIOptions = LoadConfigRCOptions = CLIOptions
def generate_stub() -> None: def generate_stub() -> None:

66
kitty/rc/load_config.py Normal file
View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
from typing import TYPE_CHECKING, Optional
from .base import (
ArgsType,
Boss,
PayloadGetType,
PayloadType,
RCOptions,
RemoteCommand,
ResponseType,
Window,
)
if TYPE_CHECKING:
from kitty.cli_stub import LoadConfigRCOptions as CLIOptions
class LoadConfig(RemoteCommand):
protocol_spec = __doc__ = '''
paths/list.str: List of config file paths to load
override/list.str: List of individual config overrides
ignore_overrides/bool: Whether to apply previous overrides
'''
short_desc = '(Re)load a config file'
desc = (
'(Re)load the specified kitty.conf config files(s). If no files are specified the previously specified config file is reloaded.'
' Note that the specified paths must exist and be readable by the kitty process on the computer that process is running on.'
' Relative paths are resolved with respect to the kitty config directory on the computer running kitty.'
)
options_spec = '''\
--ignore-overrides
type=bool-set
By default, any config overrides previously specified at the kitty invocation command line
or a previous load-config-file command are respected. Use this option to have them ignored instead.
--override -o
type=list
Override individual configuration options, can be specified multiple times.
Syntax: :italic:`name=value`. For example: :option:`{appname} -o` font_size=20
'''
args = RemoteCommand.Args(spec='CONF_FILE ...', json_field='paths',
completion=RemoteCommand.CompletionSpec.from_string('type:file group:"CONF files", ext:conf'))
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
return {'paths': args, 'override': opts.override, 'ignore_overrides': opts.ignore_overrides}
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType:
from kitty.cli import parse_override
from kitty.utils import resolve_abs_or_config_path
paths = tuple(map(resolve_abs_or_config_path, payload_get('paths', missing=())))
boss.load_config_file(
*paths, apply_overrides=not payload_get('ignore_overrides', missing=False),
overrides=tuple(map(parse_override, payload_get('override', missing=())))
)
return None
load_config = LoadConfig()