diff --git a/kitty/boss.py b/kitty/boss.py index e5b7c4484..3a98a8479 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -5,7 +5,6 @@ import atexit import re import socket -import sys from functools import partial from gettext import gettext as _ from weakref import WeakValueDictionary @@ -27,7 +26,7 @@ from .session import create_session from .tabs import SpecialWindow, SpecialWindowInstance, TabManager from .utils import ( end_startup_notification, get_primary_selection, init_startup_notification, - open_url, parse_address_spec, remove_socket_file, safe_print, + log_error, open_url, parse_address_spec, remove_socket_file, safe_print, set_primary_selection, single_instance ) @@ -214,7 +213,7 @@ class Boss: session = create_session(opts, args) self.add_os_window(session, wclass=args.cls, wname=args.name, size=initial_window_size(opts, self.cached_values), startup_id=startup_id) else: - safe_print('Unknown message received from peer, ignoring', file=sys.stderr) + log_error('Unknown message received from peer, ignoring') def handle_remote_cmd(self, cmd, window=None): response = self._handle_remote_command(cmd, window) diff --git a/kitty/config.py b/kitty/config.py index d93b29b74..5808ccb5f 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -20,7 +20,7 @@ from .config_utils import ( from .constants import cache_dir from .fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE from .layout import all_layouts -from .utils import safe_print +from .utils import log_error MINIMUM_FONT_SIZE = 4 @@ -57,12 +57,8 @@ def parse_mods(parts): try: mods |= getattr(defines, 'GLFW_MOD_' + map_mod(m.upper())) except AttributeError: - safe_print( - 'Shortcut: {} has an unknown modifier, ignoring'.format( - parts.join('+') - ), - file=sys.stderr - ) + log_error('Shortcut: {} has unknown modifier, ignoring'.format( + parts.join('+'))) return return mods @@ -127,18 +123,14 @@ def parse_key(val, keymap): return mods, key = parse_shortcut(sc) if key is None: - safe_print( - 'Shortcut: {} has an unknown key, ignoring'.format(val), - file=sys.stderr - ) + log_error('Shortcut: {} has unknown key, ignoring'.format( + val)) return try: paction = parse_key_action(action) except Exception: - safe_print( - 'Invalid shortcut action: {}. Ignoring.'.format(action), - file=sys.stderr - ) + log_error('Invalid shortcut action: {}. Ignoring.'.format( + action)) else: if paction is not None: keymap[(mods, key)] = paction @@ -149,9 +141,8 @@ def parse_symbol_map(val): symbol_map = {} def abort(): - safe_print( - 'Symbol map: {} is invalid, ignoring'.format(val), file=sys.stderr - ) + log_error('Symbol map: {} is invalid, ignoring'.format( + val)) return {} if len(parts) < 2: @@ -186,10 +177,8 @@ def parse_send_text(val, keymap): parts = val.split(' ') def abort(msg): - safe_print( - 'Send text: {} is invalid ({}), ignoring'.format(val, msg), - file=sys.stderr - ) + log_error('Send text: {} is invalid ({}), ignoring'.format( + val, msg)) return {} if len(parts) < 3: @@ -438,11 +427,8 @@ def atomic_save(data, path): except FileNotFoundError: pass except Exception as err: - safe_print( - 'Failed to delete temp file {} for atomic save with error: {}'. - format(p, err), - file=sys.stderr - ) + log_error('Failed to delete temp file {} for atomic save with error: {}'.format( + p, err)) @contextmanager @@ -455,10 +441,8 @@ def cached_values_for(name): except FileNotFoundError: pass except Exception as err: - safe_print( - 'Failed to load cached in {} values with error: {}'.format(name, err), - file=sys.stderr - ) + log_error('Failed to load cached in {} values with error: {}'.format( + name, err)) yield cached_values @@ -466,10 +450,8 @@ def cached_values_for(name): data = json.dumps(cached_values).encode('utf-8') atomic_save(data, cached_path) except Exception as err: - safe_print( - 'Failed to save cached values with error: {}'.format(err), - file=sys.stderr - ) + log_error('Failed to save cached values with error: {}'.format( + err)) def initial_window_size(opts, cached_values): @@ -479,5 +461,5 @@ def initial_window_size(opts, cached_values): try: w, h = map(int, ws) except Exception: - safe_print('Invalid cached window size, ignoring', file=sys.stderr) + log_error('Invalid cached window size, ignoring') return w, h diff --git a/kitty/config_utils.py b/kitty/config_utils.py index 6d016c1fb..5de7ec1af 100644 --- a/kitty/config_utils.py +++ b/kitty/config_utils.py @@ -3,10 +3,9 @@ # License: GPL v3 Copyright: 2018, Kovid Goyal import re -import sys from collections import namedtuple -from .utils import safe_print +from .utils import log_error from .rgb import to_color as as_color key_pat = re.compile(r'([a-zA-Z][a-zA-Z0-9_-]*)\s+(.+)$') @@ -48,10 +47,7 @@ def parse_config_base( continue if check_keys: if key not in all_keys: - safe_print( - 'Ignoring unknown config key: {}'.format(key), - file=sys.stderr - ) + log_error('Ignoring unknown config key: {}'.format(key)) continue tm = type_map.get(key) if tm is not None: diff --git a/kitty/fonts/core_text.py b/kitty/fonts/core_text.py index 389b6d053..70218b3d7 100644 --- a/kitty/fonts/core_text.py +++ b/kitty/fonts/core_text.py @@ -3,10 +3,9 @@ # License: GPL v3 Copyright: 2017, Kovid Goyal import re -import sys from kitty.fast_data_types import coretext_all_fonts -from kitty.utils import safe_print +from kitty.utils import log_error attr_map = {(False, False): 'font_family', (True, False): 'bold_font', @@ -63,10 +62,7 @@ def find_best_match(family, bold=False, italic=False): # Let CoreText choose the font if the family exists, otherwise # fallback to Menlo if q not in font_map['family_map']: - safe_print( - 'The font {} was not found, falling back to Menlo'.format(family), - file=sys.stderr - ) + log_error('The font {} was not found, falling back to Menlo'.format(family)) family = 'Menlo' return { 'monospace': True, diff --git a/kitty/terminfo.py b/kitty/terminfo.py index b40c92f55..14ab8f60d 100644 --- a/kitty/terminfo.py +++ b/kitty/terminfo.py @@ -3,17 +3,9 @@ # License: GPL v3 Copyright: 2016, Kovid Goyal import re -import sys from binascii import hexlify, unhexlify -def safe_print(*a, **k): - try: - print(*a, **k) - except Exception: - pass - - names = 'xterm-kitty', 'KovIdTTY' termcap_aliases = { @@ -460,7 +452,8 @@ def get_capabilities(query_string): qname = termcap_aliases[name] val = queryable_capabilities[qname] except Exception as e: - safe_print(ERROR_PREFIX, 'Unknown terminfo property:', name, file=sys.stderr) + from .utils import log_error + log_error(ERROR_PREFIX, 'Unknown terminfo property:', name) raise if qname in string_capabilities and '%' not in val: val = key_as_bytes(qname).decode('ascii') diff --git a/kitty/utils.py b/kitty/utils.py index 0657781d0..a7c2d2dcb 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -3,6 +3,7 @@ # License: GPL v3 Copyright: 2016, Kovid Goyal import atexit +import datetime import errno import fcntl import math @@ -19,8 +20,7 @@ from time import monotonic from .constants import appname, is_macos, is_wayland from .fast_data_types import ( - GLSL_VERSION, redirect_std_streams, x11_display, - x11_window_id + GLSL_VERSION, redirect_std_streams, x11_display, x11_window_id ) from .rgb import Color, to_color @@ -40,6 +40,15 @@ def safe_print(*a, **k): pass +def log_error(*a, **k): + try: + msg = k.get('sep', ' ').join(map(str, a)) + k.get('end', '\n') + msg = datetime.datetime.now().strftime('[%j %H:%M:%S.%f] ') + msg + sys.stderr.write(msg) + except Exception: + pass + + def ceil_int(x): return int(math.ceil(x))