mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-25 17:52:02 +02:00
Update pending mode escape code parsing to match latest shed color
This commit is contained in:
@@ -795,9 +795,14 @@ dispatch_dcs(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PENDING_MODE_CHAR:
|
case PENDING_MODE_CHAR:
|
||||||
if (screen->parser_buf[1] == 's') {
|
if (screen->parser_buf_pos > 2 && (screen->parser_buf[1] == '1' || screen->parser_buf[2] == '2') && screen->parser_buf[2] == 's') {
|
||||||
screen->pending_mode.activated_at = monotonic();
|
if (screen->parser_buf[1] == '1') {
|
||||||
REPORT_COMMAND(screen_start_pending_mode);
|
screen->pending_mode.activated_at = monotonic();
|
||||||
|
REPORT_COMMAND(screen_start_pending_mode);
|
||||||
|
} else {
|
||||||
|
// ignore stop without matching start
|
||||||
|
REPORT_COMMAND(screen_stop_pending_mode);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
REPORT_ERROR("Unrecognized DCS %c code: 0x%x", (char)screen->parser_buf[0], screen->parser_buf[1]);
|
REPORT_ERROR("Unrecognized DCS %c code: 0x%x", (char)screen->parser_buf[0], screen->parser_buf[1]);
|
||||||
}
|
}
|
||||||
@@ -1094,10 +1099,16 @@ FLUSH_DRAW;
|
|||||||
static inline size_t
|
static inline size_t
|
||||||
_queue_pending_bytes(Screen *screen, const uint8_t *buf, size_t len, PyObject *dump_callback DUMP_UNUSED) {
|
_queue_pending_bytes(Screen *screen, const uint8_t *buf, size_t len, PyObject *dump_callback DUMP_UNUSED) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
enum STATE { NORMAL, MAYBE_DCS, IN_DCS, EXPECTING_START_OR_ESC, EXPECTING_ESC, EXPECTING_SLASH };
|
enum STATE { NORMAL, MAYBE_DCS, IN_DCS, EXPECTING_DATA, EXPECTING_SLASH };
|
||||||
enum STATE state = screen->pending_mode.state;
|
enum STATE state = screen->pending_mode.state;
|
||||||
bool is_end_code = true;
|
|
||||||
#define COPY(what) screen->pending_mode.buf[screen->pending_mode.used++] = what
|
#define COPY(what) screen->pending_mode.buf[screen->pending_mode.used++] = what
|
||||||
|
#define COPY_STOP_BUF { \
|
||||||
|
COPY(0x1b); COPY('P'); COPY(PENDING_MODE_CHAR); \
|
||||||
|
for (size_t i = 0; i < screen->pending_mode.stop_buf_pos; i++) { \
|
||||||
|
COPY(screen->pending_mode.stop_buf[i]); \
|
||||||
|
} \
|
||||||
|
screen->pending_mode.stop_buf_pos = 0;}
|
||||||
|
|
||||||
while (pos < len) {
|
while (pos < len) {
|
||||||
uint8_t ch = buf[pos++];
|
uint8_t ch = buf[pos++];
|
||||||
switch(state) {
|
switch(state) {
|
||||||
@@ -1113,35 +1124,31 @@ _queue_pending_bytes(Screen *screen, const uint8_t *buf, size_t len, PyObject *d
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IN_DCS:
|
case IN_DCS:
|
||||||
if (ch == PENDING_MODE_CHAR) { state = EXPECTING_START_OR_ESC; is_end_code = true; }
|
if (ch == PENDING_MODE_CHAR) { state = EXPECTING_DATA; screen->pending_mode.stop_buf_pos = 0; }
|
||||||
else {
|
else {
|
||||||
state = NORMAL;
|
state = NORMAL;
|
||||||
COPY(0x1b); COPY('P'); COPY(ch);
|
COPY(0x1b); COPY('P'); COPY(ch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EXPECTING_START_OR_ESC:
|
case EXPECTING_DATA:
|
||||||
if (ch == 0x1b) state = EXPECTING_SLASH;
|
|
||||||
else if (ch == 's') {
|
|
||||||
state = EXPECTING_ESC;
|
|
||||||
is_end_code = false;
|
|
||||||
} else {
|
|
||||||
state = NORMAL;
|
|
||||||
COPY(0x1b); COPY('P'); COPY('='); COPY(ch);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EXPECTING_ESC:
|
|
||||||
if (ch == 0x1b) state = EXPECTING_SLASH;
|
if (ch == 0x1b) state = EXPECTING_SLASH;
|
||||||
else {
|
else {
|
||||||
state = NORMAL;
|
screen->pending_mode.stop_buf[screen->pending_mode.stop_buf_pos++] = ch;
|
||||||
COPY(0x1b); COPY('P'); COPY('=');
|
if (screen->pending_mode.stop_buf_pos >= sizeof(screen->pending_mode.stop_buf)) {
|
||||||
if (!is_end_code) COPY('s');
|
state = NORMAL;
|
||||||
COPY(ch);
|
COPY_STOP_BUF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EXPECTING_SLASH:
|
case EXPECTING_SLASH:
|
||||||
if (ch == '\\') {
|
if (
|
||||||
|
ch == '\\' &&
|
||||||
|
screen->pending_mode.stop_buf_pos >= 2 &&
|
||||||
|
(screen->pending_mode.stop_buf[0] == '1' || screen->pending_mode.stop_buf[0] == '2') &&
|
||||||
|
screen->pending_mode.stop_buf[1] == 's'
|
||||||
|
) {
|
||||||
// We found a pending mode sequence
|
// We found a pending mode sequence
|
||||||
if (is_end_code) {
|
if (screen->pending_mode.stop_buf[0] == '2') {
|
||||||
REPORT_COMMAND(screen_stop_pending_mode);
|
REPORT_COMMAND(screen_stop_pending_mode);
|
||||||
screen->pending_mode.activated_at = 0;
|
screen->pending_mode.activated_at = 0;
|
||||||
goto end;
|
goto end;
|
||||||
@@ -1151,9 +1158,7 @@ _queue_pending_bytes(Screen *screen, const uint8_t *buf, size_t len, PyObject *d
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state = NORMAL;
|
state = NORMAL;
|
||||||
COPY(0x1b); COPY('P'); COPY('=');
|
COPY_STOP_BUF; COPY(ch);
|
||||||
if (!is_end_code) { COPY('s'); }
|
|
||||||
COPY(0x1b); COPY(ch);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1162,6 +1167,7 @@ end:
|
|||||||
screen->pending_mode.state = state;
|
screen->pending_mode.state = state;
|
||||||
return pos;
|
return pos;
|
||||||
#undef COPY
|
#undef COPY
|
||||||
|
#undef COPY_STOP_BUF
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@@ -1197,7 +1203,7 @@ do_parse_bytes(Screen *screen, const uint8_t *read_buf, const size_t read_buf_sz
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QUEUE_PENDING: {
|
case QUEUE_PENDING: {
|
||||||
if (screen->pending_mode.capacity - screen->pending_mode.used < read_buf_sz) {
|
if (screen->pending_mode.capacity - screen->pending_mode.used < read_buf_sz + sizeof(screen->pending_mode.stop_buf)) {
|
||||||
if (screen->pending_mode.capacity >= READ_BUF_SZ) {
|
if (screen->pending_mode.capacity >= READ_BUF_SZ) {
|
||||||
// Too much pending data, drain it
|
// Too much pending data, drain it
|
||||||
screen->pending_mode.activated_at = 0;
|
screen->pending_mode.activated_at = 0;
|
||||||
|
|||||||
@@ -98,10 +98,11 @@ typedef struct {
|
|||||||
CursorRenderInfo cursor_render_info;
|
CursorRenderInfo cursor_render_info;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
size_t capacity, used;
|
size_t capacity, used, stop_buf_pos;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
double activated_at, wait_time;
|
double activated_at, wait_time;
|
||||||
int state;
|
int state;
|
||||||
|
uint8_t stop_buf[32];
|
||||||
} pending_mode;
|
} pending_mode;
|
||||||
|
|
||||||
} Screen;
|
} Screen;
|
||||||
|
|||||||
@@ -232,23 +232,24 @@ class TestParser(BaseTest):
|
|||||||
timeout = 0.1
|
timeout = 0.1
|
||||||
s.set_pending_timeout(timeout)
|
s.set_pending_timeout(timeout)
|
||||||
pb = partial(self.parse_bytes_dump, s)
|
pb = partial(self.parse_bytes_dump, s)
|
||||||
pb('\033P=s\033\\', ('screen_start_pending_mode',))
|
pb('\033P=1s\033\\', ('screen_start_pending_mode',))
|
||||||
pb('a')
|
pb('a')
|
||||||
self.ae(str(s.line(0)), '')
|
self.ae(str(s.line(0)), '')
|
||||||
pb('\033P=\033\\', ('screen_stop_pending_mode',), ('draw', 'a'))
|
pb('\033P=2s\033\\', ('screen_stop_pending_mode',), ('draw', 'a'))
|
||||||
self.ae(str(s.line(0)), 'a')
|
self.ae(str(s.line(0)), 'a')
|
||||||
pb('\033P=s\033\\', ('screen_start_pending_mode',))
|
pb('\033P=1s\033\\', ('screen_start_pending_mode',))
|
||||||
pb('b')
|
pb('b')
|
||||||
self.ae(str(s.line(0)), 'a')
|
self.ae(str(s.line(0)), 'a')
|
||||||
time.sleep(timeout)
|
time.sleep(timeout)
|
||||||
pb('c', ('draw', 'bc'))
|
pb('c', ('draw', 'bc'))
|
||||||
self.ae(str(s.line(0)), 'abc')
|
self.ae(str(s.line(0)), 'abc')
|
||||||
pb('\033P=s\033\\d', ('screen_start_pending_mode',))
|
pb('\033P=1s\033\\d', ('screen_start_pending_mode',))
|
||||||
pb('\033P=\033\\', ('screen_stop_pending_mode',), ('draw', 'd'))
|
pb('\033P=2s\033\\', ('screen_stop_pending_mode',), ('draw', 'd'))
|
||||||
pb('\033P=s\033\\e', ('screen_start_pending_mode',))
|
pb('\033P=1s\033\\e', ('screen_start_pending_mode',))
|
||||||
pb('\033P'), pb('=')
|
pb('\033P'), pb('='), pb('2s')
|
||||||
pb('\033\\', ('screen_stop_pending_mode',), ('draw', 'e'))
|
pb('\033\\', ('screen_stop_pending_mode',), ('draw', 'e'))
|
||||||
pb('\033P=s\033\\f\033P=s\033\\', ('screen_start_pending_mode',), ('screen_start_pending_mode',))
|
pb('\033P=1sxyz;.;\033\\''\033P=2skjf".,><?_+)98\033\\', ('screen_start_pending_mode',), ('screen_stop_pending_mode',))
|
||||||
|
pb('\033P=1s\033\\f\033P=1s\033\\', ('screen_start_pending_mode',), ('screen_start_pending_mode',))
|
||||||
|
|
||||||
def test_oth_codes(self):
|
def test_oth_codes(self):
|
||||||
s = self.create_screen()
|
s = self.create_screen()
|
||||||
|
|||||||
Reference in New Issue
Block a user