|
| 1 | +The multiple cursors protocol |
| 2 | +============================================== |
| 3 | + |
| 4 | +.. versionadded:: 0.43.0 |
| 5 | + |
| 6 | +Many editors support something called *multiple cursors* in which you can make |
| 7 | +the same changes at multiple locations in a file and the editor shows you |
| 8 | +cursors at each of the locations. In a terminal context editors typically |
| 9 | +implement this by showing some Unicode glyph at each location instead of the |
| 10 | +actual cursor. This is sub-optimal since actual cursors implemented by the |
| 11 | +terminal have many niceties like smooth animation, auto adjust colors, etc. To |
| 12 | +address this and other use cases, this protocol allows terminal programs to |
| 13 | +request that the terminal display multiple cursors at specific locations on the |
| 14 | +screen. |
| 15 | + |
| 16 | +Quickstart |
| 17 | +---------------- |
| 18 | + |
| 19 | +An example, showing how to use the protocol: |
| 20 | + |
| 21 | +.. code-block:: sh |
| 22 | +
|
| 23 | + # Show cursors of the same shape as the main cursor at y=4, x=5 |
| 24 | + printf "\e[>-1;2:4:5 q" |
| 25 | + # Show more cursors on the seventh line, of various shapes, the underline shape is shown twice |
| 26 | + printf "\e[>1;2:7:1 q\e[>2;2:7:3 q\e[>3;2:7:5;2:7:7 q" |
| 27 | +
|
| 28 | +
|
| 29 | +The escape code to show a cursor has the following structure (ignore spaces |
| 30 | +they are present for readability only):: |
| 31 | + |
| 32 | + CSI > SHAPE;CO-ORD TYPE : CO-ORDINATES ; CO-ORD TYPE : CO-ORDINATES ... TRAILER |
| 33 | + |
| 34 | +Here ``CSI`` is the two bytes ESC (``0x1b``) and [ (``0x5b``). ``SHAPE`` can be |
| 35 | +one of: |
| 36 | + |
| 37 | +* ``-2``: Used for querying currently set cursors |
| 38 | +* ``-1``: Follow the shape of the main cursor |
| 39 | +* ``0``: No cursor |
| 40 | +* ``1``: Block cursor |
| 41 | +* ``2``: Beam cursor |
| 42 | +* ``3``: Underline cursor |
| 43 | + |
| 44 | +``CO-ORD TYPE`` can be one of: |
| 45 | + |
| 46 | +* ``0``: This refers to the position of the main cursor and has no following |
| 47 | + co-ordinates. |
| 48 | + |
| 49 | +* ``2``: In this case the following co-ordinates are pairs of numbers pointing |
| 50 | + to cells in the form ``y:x`` with the origin in the top left corner at |
| 51 | + ``1,1``. There can be any number of pairs, the terminal must treat each pair |
| 52 | + as a new location to set a cursor. |
| 53 | + |
| 54 | +* ``4``: In this case the following co-ordinates are sets of four numbers that |
| 55 | + define a rectangle in the same co-ordinate system as above of the form: |
| 56 | + ``top:left:bottom:right``. The shape is set on every cell in the rectangle |
| 57 | + from the top left cell to the bottom right cell, inclusive. If no numbers |
| 58 | + are provided, the rectangle is the full screen. There can be any number of |
| 59 | + rectangles, the terminal must treat each set of four numbers as a new |
| 60 | + rectangle. |
| 61 | + |
| 62 | +The sequence of ``CO-ORD TYPE : CO-ORDINATES`` can be repeated any number of |
| 63 | +times separated by ``;``. The ``SHAPE`` will be set on the cells indicated by |
| 64 | +each such group. For example: ``-1;2:3:4;4:5:6:7:8`` will set the shape ``-1`` |
| 65 | +at the cell ``(3, 2)`` and in the rectangle ``(6, 5)`` to ``(8, 7)`` inclusive. |
| 66 | + |
| 67 | +Finally, the ``TRAILER`` terminates the sequence and is the bytes SPACE |
| 68 | +(``0x20``) and q (``0x71``). |
| 69 | + |
| 70 | +Terminals **must** ignore cells that fall outside the screen. That means, for |
| 71 | +rectangle co-ordinates only the intersection of the rectangle with the screen |
| 72 | +must be considered, and point co-ordinates that fall outside of the screen are |
| 73 | +simply ignored, with no effect. |
| 74 | + |
| 75 | +Terminals **must** ignore extra co-ordinates, that means if an odd number of |
| 76 | +co-ordinates are specified for type ``2`` the last co-ordinate is ignored. |
| 77 | +Similarly for type ``4`` if the number of co-ordinates is not a multiple of |
| 78 | +four, the last ``1 <= n <= 3`` co-ordinates are ignored, as if they were not |
| 79 | +specified. |
| 80 | + |
| 81 | +Querying for support |
| 82 | +------------------------- |
| 83 | + |
| 84 | +A terminal program can query the terminal emulator for support of this |
| 85 | +protocol by sending the escape code:: |
| 86 | + |
| 87 | + CSI > TRAILER |
| 88 | + |
| 89 | +In this case a supporting terminal must reply with:: |
| 90 | + |
| 91 | + CSI > -1;1;2;3 TRAILER |
| 92 | + |
| 93 | +Here, the list of numbers indicates the cursor shapes the terminal supports and |
| 94 | +can be any subset of the above. No numbers indicates the protocol is not |
| 95 | +supported. To avoid having to wait with a timeout for a response from the |
| 96 | +terminal, the client should send this query code immediately followed by |
| 97 | +a request for the `primary device attributes <https://vt100.net/docs/vt510-rm/DA1.html>`_. |
| 98 | +If the terminal responds with an answer for the device attributes without |
| 99 | +an answer for the *query* the terminal emulator does not support this protocol at all. |
| 100 | + |
| 101 | +Terminals **must** respond to these queries in FIFO order, so that |
| 102 | +multiplexers that split a single screen know which split to send responses too. |
| 103 | + |
| 104 | +Clearing previously set multi-cursors |
| 105 | +------------------------------------------ |
| 106 | + |
| 107 | +The cursor at a cell is cleared by settings its shape to ``0``. |
| 108 | +The most common operation is to clear all previously set multi-cursors. This is |
| 109 | +easily done using the *rectangle* co-ordinate system above, like this:: |
| 110 | + |
| 111 | + CSI > 0;4 TRAILER |
| 112 | + |
| 113 | +For more precise control different co-ordinate types can be used. This is |
| 114 | +particularly important for multiplexers that split up the screen and therefore |
| 115 | +need to re-write these escape codes. |
| 116 | + |
| 117 | +Querying for already set cursors |
| 118 | +-------------------------------------- |
| 119 | + |
| 120 | +Programs can ask the terminal what extra cursors are currently set, by sending |
| 121 | +the escape code:: |
| 122 | + |
| 123 | + CSI > -2 TRAILER |
| 124 | + |
| 125 | +The terminal must respond with **one** escape code:: |
| 126 | + |
| 127 | + CSI > -2; SHAPE:CO-ORDINATE TYPE:CO-ORDINATES ; ... TRAILER |
| 128 | + |
| 129 | +Here, the ``SHAPE:CO-ORDINATE TYPE:CO-ORDINATES`` block can be repeated any |
| 130 | +number of times, separated by ``;``. This response gives the set of shapes and |
| 131 | +positions currently active. If no cursors are currently active, there will be |
| 132 | +no blocks, just an empty response of the form:: |
| 133 | + |
| 134 | + CSI > -2 TRAILER |
| 135 | + |
| 136 | +Again, terminals **must** respond in FIFO order so that multiplexers know where |
| 137 | +to direct the responses. |
| 138 | + |
| 139 | + |
| 140 | +Interaction with other terminal controls and state |
| 141 | +------------------------------------------------------- |
| 142 | + |
| 143 | +**The main cursor** |
| 144 | + The extra cursors must all have the same color and opacity and blink state |
| 145 | + as the main cursor. The main cursor's visibility must not affect the |
| 146 | + visibility of the extra cursors. Their visibility and shape are controlled |
| 147 | + only by this protocol. |
| 148 | + |
| 149 | +**Clearing the screen** |
| 150 | + |
0 commit comments