mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 08:26:56 +00:00
Dont use negative numbers in multi cursor protocol
There are apparently many parsers out there that cant handle them.
This commit is contained in:
parent
e76f4c630f
commit
44b5d8f656
3 changed files with 30 additions and 28 deletions
|
|
@ -25,7 +25,7 @@ An example, showing how to use the protocol:
|
|||
.. code-block:: sh
|
||||
|
||||
# Show cursors of the same shape as the main cursor at y=4, x=5
|
||||
printf "\e[>-1;2:4:5 q"
|
||||
printf "\e[>29;2:4:5 q"
|
||||
# Show more cursors on the seventh line, of various shapes, the underline shape is shown twice
|
||||
printf "\e[>1;2:7:1 q\e[>2;2:7:3 q\e[>3;2:7:5;2:7:7 q"
|
||||
|
||||
|
|
@ -38,12 +38,14 @@ they are present for readability only)::
|
|||
Here ``CSI`` is the two bytes ESC (``0x1b``) and [ (``0x5b``). ``SHAPE`` can be
|
||||
one of:
|
||||
|
||||
* ``-2``: Used for querying currently set cursors
|
||||
* ``-1``: Follow the shape of the main cursor
|
||||
* ``0``: No cursor
|
||||
* ``1``: Block cursor
|
||||
* ``2``: Beam cursor
|
||||
* ``3``: Underline cursor
|
||||
* ``29``: Follow the shape of the main cursor
|
||||
* ``30``: Change the color of text under extra cursors
|
||||
* ``40``: Change the color of extra cursors
|
||||
* ``100``: Used for querying currently set cursors
|
||||
|
||||
``CO-ORD TYPE`` can be one of:
|
||||
|
||||
|
|
@ -92,7 +94,7 @@ protocol by sending the escape code::
|
|||
|
||||
In this case a supporting terminal must reply with::
|
||||
|
||||
CSI > -2;-1;1;2;3 TRAILER
|
||||
CSI > 1;2;3;29;30;40;100;101 TRAILER
|
||||
|
||||
Here, the list of numbers indicates the cursor shapes and other operations
|
||||
the terminal supports and can be any subset of the above. No numbers
|
||||
|
|
@ -125,18 +127,18 @@ Querying for already set cursors
|
|||
Programs can ask the terminal what extra cursors are currently set, by sending
|
||||
the escape code::
|
||||
|
||||
CSI > -2 TRAILER
|
||||
CSI > 100 TRAILER
|
||||
|
||||
The terminal must respond with **one** escape code::
|
||||
|
||||
CSI > -2; SHAPE:CO-ORDINATE TYPE:CO-ORDINATES ; ... TRAILER
|
||||
CSI > 100; SHAPE:CO-ORDINATE TYPE:CO-ORDINATES ; ... TRAILER
|
||||
|
||||
Here, the ``SHAPE:CO-ORDINATE TYPE:CO-ORDINATES`` block can be repeated any
|
||||
number of times, separated by ``;``. This response gives the set of shapes and
|
||||
positions currently active. If no cursors are currently active, there will be
|
||||
no blocks, just an empty response of the form::
|
||||
|
||||
CSI > -2 TRAILER
|
||||
CSI > 100 TRAILER
|
||||
|
||||
Again, terminals **must** respond in FIFO order so that multiplexers know where
|
||||
to direct the responses.
|
||||
|
|
|
|||
|
|
@ -2868,24 +2868,24 @@ screen_multi_cursor(Screen *self, int queried_shape, int *params, unsigned num_p
|
|||
if (!num_params) {
|
||||
#define pr(...) { int n = snprintf(p, sz - (p - buf), __VA_ARGS__); if (n >= 0 && (unsigned)n <= (sz - (p - buf))) p += n; }
|
||||
if (params == NULL) {
|
||||
write_escape_code_to_child(self, ESC_CSI, ">-5;-4;-3;-2;-1;1;2;3 q");
|
||||
} else if (queried_shape == -2) {
|
||||
write_escape_code_to_child(self, ESC_CSI, ">1;2;3;29;30;40;100;101 q");
|
||||
} else if (queried_shape == 100) {
|
||||
size_t sz = self->extra_cursors.count * 32 + 64;
|
||||
RAII_ALLOC(char, buf, malloc(sz)); sz -= 4;
|
||||
if (buf) {
|
||||
char *p = buf + snprintf(buf, sz, ">-2;");
|
||||
char *p = buf + snprintf(buf, sz, ">100;");
|
||||
for (unsigned i = 0; i < self->extra_cursors.count; i++) {
|
||||
index_type cell = self->extra_cursors.locations[i].cell, shape = self->extra_cursors.locations[i].shape;
|
||||
index_type y = cell / self->columns, x = cell - (y * self->columns);
|
||||
pr("%d:2:%u:%u;", shape > 3 ? -1 : (int)shape, y+1, x+1);
|
||||
pr("%d:2:%u:%u;", shape > 3 ? 29 : (int)shape, y+1, x+1);
|
||||
}
|
||||
if (*(p-1) == ';') p--;
|
||||
*(p++) = ' '; *(p++) = 'q'; *(p++) = 0;
|
||||
write_escape_code_to_child(self, ESC_CSI, buf);
|
||||
}
|
||||
} else if (queried_shape == -5) {
|
||||
} else if (queried_shape == 101) {
|
||||
char buf[64], *p = buf; size_t sz = sizeof(buf);
|
||||
pr(">-5;-3:"); DynamicColor ecc = self->extra_cursors.color.cursor;
|
||||
pr(">101;30:"); DynamicColor ecc = self->extra_cursors.color.text;
|
||||
#define o() switch(ecc.type) { \
|
||||
case COLOR_NOT_SET: pr("0"); break; \
|
||||
case COLOR_IS_SPECIAL: pr("1"); break; \
|
||||
|
|
@ -2893,7 +2893,7 @@ screen_multi_cursor(Screen *self, int queried_shape, int *params, unsigned num_p
|
|||
case COLOR_IS_RGB: pr("2:%u:%u:%u", (ecc.rgb >> 16) & 0xff, (ecc.rgb >> 8) & 0xff, ecc.rgb & 0xff); break; \
|
||||
} \
|
||||
|
||||
o(); pr(";-4:"); ecc = self->extra_cursors.color.text; o();
|
||||
o(); pr(";40:"); ecc = self->extra_cursors.color.cursor; o();
|
||||
#undef o
|
||||
pr(" q");
|
||||
write_escape_code_to_child(self, ESC_CSI, buf);
|
||||
|
|
@ -2901,8 +2901,8 @@ screen_multi_cursor(Screen *self, int queried_shape, int *params, unsigned num_p
|
|||
return;
|
||||
#undef pr
|
||||
}
|
||||
if (queried_shape == -3 || queried_shape == -4) {
|
||||
DynamicColor *ecc = queried_shape == -3 ? &self->extra_cursors.color.cursor : &self->extra_cursors.color.text;
|
||||
if (queried_shape == 30 || queried_shape == 40) {
|
||||
DynamicColor *ecc = queried_shape == 40 ? &self->extra_cursors.color.cursor : &self->extra_cursors.color.text;
|
||||
self->extra_cursors.dirty = true;
|
||||
switch (params[0]) {
|
||||
case 0: ecc->type = COLOR_NOT_SET; break;
|
||||
|
|
@ -2919,10 +2919,10 @@ screen_multi_cursor(Screen *self, int queried_shape, int *params, unsigned num_p
|
|||
return;
|
||||
}
|
||||
uint8_t shape = 0;
|
||||
if (queried_shape < 0) {
|
||||
shape = 4;
|
||||
} else {
|
||||
shape = MIN(queried_shape, 3);
|
||||
switch(queried_shape) {
|
||||
case 29: shape = 4; break;
|
||||
case 0: case 1: case 2: case 3: shape = queried_shape; break;
|
||||
default: return;
|
||||
}
|
||||
self->extra_cursors.dirty = true;
|
||||
int type = params[0]; params++; num_params--;
|
||||
|
|
|
|||
|
|
@ -1597,12 +1597,12 @@ class TestScreen(BaseTest):
|
|||
def ec(payload=''):
|
||||
return f'\x1b[>{payload} q'.encode() # ]
|
||||
parse_bytes(s, ec())
|
||||
self.ae(c.wtcbuf, ec('-5;-4;-3;-2;-1;1;2;3'))
|
||||
self.ae(c.wtcbuf, ec('1;2;3;29;30;40;100;101'))
|
||||
|
||||
def current() -> dict[int, tuple[int, int]]:
|
||||
ans = {}
|
||||
c.clear()
|
||||
parse_bytes(s, ec('-2'))
|
||||
parse_bytes(s, ec('100'))
|
||||
for entry in c.wtcbuf[6:-2].decode().split(';'):
|
||||
if entry:
|
||||
which, _, y, x = map(int, entry.split(':'))
|
||||
|
|
@ -1625,9 +1625,9 @@ class TestScreen(BaseTest):
|
|||
|
||||
self.ae(a(1, region=True), {1:{(x, y) for x in range(s.columns) for y in range(s.lines)}})
|
||||
self.ae(a(0, region=True), {})
|
||||
self.ae(a(-1, region=(1, 2, 2, 3)), {-1: {(1, 2), (2, 2), (1, 3), (2, 3)}})
|
||||
self.ae(a(2, (1, 2), (1, 3)), {-1: {(2, 3), (2, 2)}, 2: {(1, 2), (1, 3)}})
|
||||
self.ae(a(0, (1, 2), (2, 3)), {-1: {(2, 2)}, 2: {(1, 3)}})
|
||||
self.ae(a(29, region=(1, 2, 2, 3)), {29: {(1, 2), (2, 2), (1, 3), (2, 3)}})
|
||||
self.ae(a(2, (1, 2), (1, 3)), {29: {(2, 3), (2, 2)}, 2: {(1, 2), (1, 3)}})
|
||||
self.ae(a(0, (1, 2), (2, 3)), {29: {(2, 2)}, 2: {(1, 3)}})
|
||||
self.ae(a(0, region=True), {})
|
||||
s.cursor.x, s.cursor.y = 1, 2
|
||||
parse_bytes(s, ec('3;0'))
|
||||
|
|
@ -1637,10 +1637,10 @@ class TestScreen(BaseTest):
|
|||
parse_bytes(s, ec('0;4:3:1:4'))
|
||||
self.ae(current(), {})
|
||||
|
||||
def sc(op, r=0, g=0, b=0, slot=-3):
|
||||
def sc(op, r=0, g=0, b=0, slot=40):
|
||||
parse_bytes(s, ec(f'{slot};{op}:{r}:{g}:{b}'))
|
||||
c.clear()
|
||||
parse_bytes(s, ec('-5'))
|
||||
parse_bytes(s, ec('101'))
|
||||
for x in c.wtcbuf[3:-2].decode().split(';')[1:]:
|
||||
parts = x.split(':')
|
||||
if int(parts[0]) == slot:
|
||||
|
|
@ -1651,7 +1651,7 @@ class TestScreen(BaseTest):
|
|||
else:
|
||||
self.ae((op, r), tuple(map(int, parts[1:])))
|
||||
break
|
||||
for slot in (-3, -4):
|
||||
for slot in (40, 30):
|
||||
sc(0, slot=slot)
|
||||
sc(1, slot=slot)
|
||||
sc(2, 1, 2, 3, slot=slot)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue