Skip to content

Commit c660840

Browse files
committed
When encountering errors in kitty.conf report them to the user instead of failing to start.
1 parent c6d3ede commit c660840

File tree

6 files changed

+44
-17
lines changed

6 files changed

+44
-17
lines changed

docs/changelog.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
114114
- Use negative values for :opt:`mouse_hide_wait` to hide the mouse cursor
115115
immediately when pressing a key (:iss:`1534`)
116116

117+
- When encountering errors in :file:`kitty.conf` report them to the user
118+
instead of failing to start.
119+
117120

118121
0.13.3 [2019-01-19]
119122
------------------------------

kitty/boss.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ def set_tab_title(self):
742742
self._run_kitten('ask', args)
743743

744744
def show_error(self, title, msg):
745-
self._run_kitten('show_error', ['--title', title], input_data=msg)
745+
self._run_kitten('show_error', args=['--title', title], input_data=msg)
746746

747747
def do_set_tab_title(self, title, tab_id):
748748
tm = self.active_tab_manager
@@ -1068,3 +1068,11 @@ def dbus_notification_callback(self, activated, *args):
10681068
dbus_notification_activated(*args)
10691069
else:
10701070
dbus_notification_created(*args)
1071+
1072+
def show_bad_config_lines(self, bad_lines):
1073+
1074+
def format_bad_line(bad_line):
1075+
return '{}:{} in line: {}\n'.format(bad_line.number, bad_line.exception, bad_line.line)
1076+
1077+
msg = '\n'.join(map(format_bad_line, bad_lines)).rstrip()
1078+
self.show_error(_('Errors in kitty.conf'), msg)

kitty/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ def compare_opts(opts):
710710
compare_keymaps(final, initial)
711711

712712

713-
def create_opts(args, debug_config=False):
713+
def create_opts(args, debug_config=False, accumulate_bad_lines=None):
714714
from .config import load_config
715715
config = tuple(resolve_config(SYSTEM_CONF, defconf, args.config))
716716
if debug_config:
@@ -729,7 +729,7 @@ def create_opts(args, debug_config=False):
729729
if config:
730730
print(green('Loaded config files:'), ', '.join(config))
731731
overrides = (a.replace('=', ' ', 1) for a in args.override or ())
732-
opts = load_config(*config, overrides=overrides)
732+
opts = load_config(*config, overrides=overrides, accumulate_bad_lines=accumulate_bad_lines)
733733
if debug_config:
734734
compare_opts(opts)
735735
return opts

kitty/conf/utils.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import os
66
import re
77
import shlex
8+
from collections import namedtuple
89

910
from ..rgb import to_color as as_color
1011
from ..utils import log_error
1112

1213
key_pat = re.compile(r'([a-zA-Z][a-zA-Z0-9_-]*)\s+(.+)$')
14+
BadLine = namedtuple('BadLine', 'number line exception')
1315

1416

1517
def to_color(x):
@@ -90,22 +92,28 @@ def parse_line(line, type_map, special_handling, ans, all_keys, base_path_for_in
9092
ans[key] = val
9193

9294

93-
def _parse(lines, type_map, special_handling, ans, all_keys):
95+
def _parse(lines, type_map, special_handling, ans, all_keys, accumulate_bad_lines=None):
9496
name = getattr(lines, 'name', None)
9597
if name:
9698
base_path_for_includes = os.path.dirname(os.path.abspath(name))
9799
else:
98100
from ..constants import config_dir
99101
base_path_for_includes = config_dir
100-
for line in lines:
101-
parse_line(line, type_map, special_handling, ans, all_keys, base_path_for_includes)
102+
for i, line in enumerate(lines):
103+
try:
104+
parse_line(line, type_map, special_handling, ans, all_keys, base_path_for_includes)
105+
except Exception as e:
106+
if accumulate_bad_lines is None:
107+
raise
108+
accumulate_bad_lines.append(BadLine(i + 1, line.rstrip(), e))
102109

103110

104111
def parse_config_base(
105-
lines, defaults, type_map, special_handling, ans, check_keys=True
112+
lines, defaults, type_map, special_handling, ans, check_keys=True,
113+
accumulate_bad_lines=None
106114
):
107115
all_keys = defaults._asdict() if check_keys else None
108-
_parse(lines, type_map, special_handling, ans, all_keys)
116+
_parse(lines, type_map, special_handling, ans, all_keys, accumulate_bad_lines)
109117

110118

111119
def create_options_class(keys):

kitty/config.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import sys
99
from collections import namedtuple
1010
from contextlib import contextmanager
11+
from functools import partial
1112

1213
from . import fast_data_types as defines
1314
from .conf.definition import as_conf_file, config_lines
@@ -439,15 +440,16 @@ def option_names_for_completion():
439440
yield from special_handlers
440441

441442

442-
def parse_config(lines, check_keys=True):
443+
def parse_config(lines, check_keys=True, accumulate_bad_lines=None):
443444
ans = {'symbol_map': {}, 'keymap': {}, 'sequence_map': {}, 'key_definitions': [], 'env': {}}
444445
parse_config_base(
445446
lines,
446447
defaults,
447448
type_map,
448449
special_handling,
449450
ans,
450-
check_keys=check_keys
451+
check_keys=check_keys,
452+
accumulate_bad_lines=accumulate_bad_lines
451453
)
452454
return ans
453455

@@ -617,8 +619,11 @@ def finalize_keys(opts):
617619
opts.sequence_map = sequence_map
618620

619621

620-
def load_config(*paths, overrides=None):
621-
opts = _load_config(Options, defaults, parse_config, merge_configs, *paths, overrides=overrides)
622+
def load_config(*paths, overrides=None, accumulate_bad_lines=None):
623+
parser = parse_config
624+
if accumulate_bad_lines is not None:
625+
parser = partial(parse_config, accumulate_bad_lines=accumulate_bad_lines)
626+
opts = _load_config(Options, defaults, parser, merge_configs, *paths, overrides=overrides)
622627
finalize_keys(opts)
623628
if opts.background_opacity < 1.0 and opts.macos_titlebar_color:
624629
log_error('Cannot use both macos_titlebar_color and background_opacity')

kitty/main.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def get_new_os_window_trigger(opts):
115115
return new_os_window_trigger
116116

117117

118-
def _run_app(opts, args):
118+
def _run_app(opts, args, bad_lines=()):
119119
new_os_window_trigger = get_new_os_window_trigger(opts)
120120
if is_macos and opts.macos_custom_beam_cursor:
121121
set_custom_ibeam_cursor()
@@ -132,18 +132,20 @@ def _run_app(opts, args):
132132
args.cls or appname, load_all_shaders)
133133
boss = Boss(window_id, opts, args, cached_values, new_os_window_trigger)
134134
boss.start()
135+
if bad_lines:
136+
boss.show_bad_config_lines(bad_lines)
135137
try:
136138
boss.child_monitor.main_loop()
137139
finally:
138140
boss.destroy()
139141

140142

141-
def run_app(opts, args):
143+
def run_app(opts, args, bad_lines=()):
142144
set_scale(opts.box_drawing_scale)
143145
set_options(opts, is_wayland, args.debug_gl, args.debug_font_fallback)
144146
set_font_family(opts, debug_font_matching=args.debug_font_fallback)
145147
try:
146-
_run_app(opts, args)
148+
_run_app(opts, args, bad_lines)
147149
finally:
148150
free_font_data() # must free font data before glfw/freetype/fontconfig/opengl etc are finalized
149151

@@ -262,12 +264,13 @@ def _main():
262264
talk_to_instance(args)
263265
return
264266
init_glfw(args.debug_keyboard) # needed for parsing native keysyms
265-
opts = create_opts(args)
267+
bad_lines = []
268+
opts = create_opts(args, accumulate_bad_lines=bad_lines)
266269
setup_environment(opts, args)
267270
try:
268271
with setup_profiling(args):
269272
# Avoid needing to launch threads to reap zombies
270-
run_app(opts, args)
273+
run_app(opts, args, bad_lines)
271274
finally:
272275
glfw_terminate()
273276

0 commit comments

Comments
 (0)