diff --git a/kitty/boss.py b/kitty/boss.py index 9dc237578..3e3855e4d 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -24,6 +24,7 @@ from .utils import sanitize_title from .fast_data_types import ( BRACKETED_PASTE_START, BRACKETED_PASTE_END, Screen, read_bytes_dump, read_bytes ) +from .terminfo import get_capabilities def handle_unix_signals(): @@ -246,7 +247,9 @@ class Boss(Thread): def set_dynamic_color(self, code, value): wmap = {10: 'fg', 11: 'bg', 110: 'fg', 111: 'bg'} - for val in value.decode('utf-8').split(';'): + if isinstance(value, bytes): + value = value.decode('utf-8') + for val in value.split(';'): w = wmap.get(code) if w is not None: if code >= 110: @@ -260,6 +263,9 @@ class Boss(Thread): self.pending_color_changes = {} glfw.glfwPostEmptyEvent() + def request_capabilities(self, q): + self.write_to_child(get_capabilities(q)) + # actions {{{ def paste(self, text): diff --git a/kitty/data-types.c b/kitty/data-types.c index 55b9870be..deee80b37 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -51,6 +51,7 @@ PyInit_fast_data_types(void) { PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT); PyModule_AddStringMacro(m, BRACKETED_PASTE_START); PyModule_AddStringMacro(m, BRACKETED_PASTE_END); + PyModule_AddStringMacro(m, ERROR_PREFIX); PyModule_AddIntMacro(m, CURSOR_BLOCK); PyModule_AddIntMacro(m, CURSOR_BEAM); PyModule_AddIntMacro(m, CURSOR_UNDERLINE); diff --git a/kitty/data-types.h b/kitty/data-types.h index 523531951..0cc18b456 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -21,6 +21,9 @@ typedef uint64_t color_type; typedef uint32_t decoration_type; typedef uint32_t combining_type; typedef unsigned int index_type; + +#define ERROR_PREFIX "[PARSE ERROR]" + #define CELL_SIZE (sizeof(char_type) + sizeof(color_type) + sizeof(decoration_type) + sizeof(combining_type)) // The data cell size must be a multiple of 3 #define DATA_CELL_SIZE 2 * 3 diff --git a/kitty/parser.c b/kitty/parser.c index 42670cbad..d32f409ac 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -76,7 +76,7 @@ static void _report_error(PyObject *dump_callback, const char *fmt, ...) { #define DUMP_UNUSED UNUSED -#define REPORT_ERROR(...) fprintf(stderr, "[PARSE ERROR] "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); +#define REPORT_ERROR(...) fprintf(stderr, "%s ", ERROR_PREFIX); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); #define REPORT_COMMAND(...) #define REPORT_DRAW(ch) diff --git a/kitty/terminfo.py b/kitty/terminfo.py index b2ae0386c..21579f3fc 100644 --- a/kitty/terminfo.py +++ b/kitty/terminfo.py @@ -2,6 +2,8 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2016, Kovid Goyal +from binascii import unhexlify, hexlify + names = 'xterm-kitty', 'KovIdTTY' termcap_aliases = { @@ -264,7 +266,7 @@ termcap_aliases.update({ 'SF': 'indn', # 'Ic': 'initc', # 'mk': 'invis', - 'bs': 'kbs', + 'kb': 'kbs', 'kl': 'kcub1', 'kd': 'kcud1', 'kr': 'kcuf1', @@ -318,6 +320,8 @@ termcap_aliases.update({ }) +queryable_capabilities = numeric_capabilities.copy() +queryable_capabilities.update(string_capabilities) extra = (bool_capabilities | numeric_capabilities.keys() | string_capabilities.keys()) - set(termcap_aliases.values()) if extra: raise Exception('Termcap aliases not complete, missing: {}'.format(extra)) @@ -335,3 +339,26 @@ def generate_terminfo(): def key_as_bytes(name): ans = string_capabilities[name] return ans.replace(r'\E', '\033').encode('ascii') + + +def get_capabilities(query_string): + from .fast_data_types import ERROR_PREFIX + ans = [] + try: + for q in query_string.split(';'): + name = unhexlify(q).decode('utf-8') + if name == 'TN': + val = names[0] + else: + try: + val = queryable_capabilities[name] + except KeyError: + try: + val = queryable_capabilities[termcap_aliases[name]] + except Exception as e: + print(ERROR_PREFIX, 'Unknown terminfo property:', name) + raise + ans.append(q + '=' + hexlify(str(val))) + return b'\033P1+r' + ';'.join(ans).encode('utf-8') + b'\033\\' + except Exception: + return b'\033P0+r' + query_string.encode('utf-8') + b'\033\\'