mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Document the new color control protocol
This commit is contained in:
@@ -80,6 +80,8 @@ Detailed list of changes
|
||||
|
||||
- A new option :opt:`second_transparent_bg` to make a second background color semi-transparent via :opt:`background_opacity`. Useful for things like cursor line highlight in editors (:iss:`7646`)
|
||||
|
||||
- A new protocol to allow terminal applications to change colors in the terminal more robustly than with the legacy XTerm protocol (:ref:`color_control`)
|
||||
|
||||
- Sessions: A new command ``focus_matching_window`` to shift focus to a specific window, useful when creating complex layouts with splits (:disc:`7635`)
|
||||
|
||||
- Wayland: Allow fractional scales less than one (:pull:`7549`)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
Color control
|
||||
====================
|
||||
|
||||
Saving and restoring colors
|
||||
==============================
|
||||
------------------------------
|
||||
|
||||
It is often useful for a full screen application with its own color themes to
|
||||
set the default foreground, background, selection and cursor colors and the ANSI
|
||||
@@ -24,3 +27,141 @@ foreground, selection background, selection foreground and cursor color and the
|
||||
promoting interoperability, kitty added support for xterm's escape codes as
|
||||
well, and changed this extension to also save/restore the entire ANSI color
|
||||
table.
|
||||
|
||||
.. _color_control:
|
||||
|
||||
Setting and querying colors
|
||||
-------------------------------
|
||||
|
||||
While there exists a legacy protocol developed by XTerm for querying and
|
||||
setting colors, as with most XTerm protocols it suffers from the usual design
|
||||
limitations of being under specified and in-sufficient. XTerm implements
|
||||
querying of colors using OSC 4,5,6,10-19,104,105,106,110-119. This absurd
|
||||
profusion of numbers is completely unnecessary, redundant and requires adding
|
||||
two new numbers for every new color. Also XTerm's protocol doesn't handle the
|
||||
case of colors that are unknown to the terminal or that are not a set value,
|
||||
for example, many terminals implement selection as a reverse video effect not a
|
||||
fixed color. The XTerm protocol has no way to query for this condition. The
|
||||
protocol also doesn't actually specify the format in which colors are reported,
|
||||
deferring to a man page for X11!
|
||||
|
||||
Instead kitty has developed a single number based protocol that addresses all
|
||||
these shortcomings and is future proof by virtue of using string keys rather
|
||||
than numbers. The syntax of the escape code is::
|
||||
|
||||
<OSC> 21 ; key=value ; key=value ; ... <ST>
|
||||
|
||||
The spaces in the above definition are for reading clarity and should be ignored.
|
||||
Here, ``<OSC>`` is the two bytes ``0x1b (ESC)`` and ``0x5b ([)``. ``ST`` is
|
||||
either `0x7 (BEL)` or the two bytes ``0x1b (ESC)`` and ``0x5c (\\)``.
|
||||
|
||||
``key`` is a number from 0-255 to query or set the color values from the
|
||||
terminals ANSI color table, or one of the strings in the table below for
|
||||
special colors:
|
||||
|
||||
================================= =============================================== ===============================
|
||||
key meaning dynamic
|
||||
================================= =============================================== ===============================
|
||||
foreground The default foreground text color Not applicable
|
||||
background The default background text color Not applicable
|
||||
selection_background The background color of selections Reverse video
|
||||
selection_foreground The foreground color of selections Reverse video
|
||||
cursor The color of the text cursor Foreground color
|
||||
cursor_text The color of text under the cursor Background color
|
||||
visual_bell The color of a visual bell Automatic color selection based on current screen colors
|
||||
second_transparent_background A color that might be rendered semi-transparent No second color is made transparent
|
||||
in addition to the default background color
|
||||
================================= =============================================== ===============================
|
||||
|
||||
In this table the third column shows what effect setting the color to *dynamic*
|
||||
has in kitty and many other terminal emulators. It is advisory only, terminal
|
||||
emulators may not support dynamic colors for these or they may have other
|
||||
effects. Setting the ANSI color table colors to dynamic is not allowed.
|
||||
|
||||
Querying current color values
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To query colors values, the client program sends this escape code with the
|
||||
``value`` field set to ``?`` (the byte ``0x3f``). The terminal then responds
|
||||
with the same escape code, but with the ``?`` replaced by the :ref:`encoded
|
||||
color value <color_control_color_encoding>`. If the queried color is one that
|
||||
does not have a defined value, for example, if the terminal is using a reverse
|
||||
video effect or a gradient or similar, then the value must be empty, that is
|
||||
the response contains only the key and ``=``, no value. For example, if the
|
||||
client sends::
|
||||
|
||||
<OSC> 21 ; foreground=? ; cursor=? <ST>
|
||||
|
||||
The terminal responds::
|
||||
|
||||
<OSC> 21 ; foreground=rgb:ff/00/00 ; cursor= <ST>
|
||||
|
||||
This indicates that the foreground color is red and the cursor color is
|
||||
undefined (typically the cursor takes the color of the text under it and the
|
||||
text takes the color of the background).
|
||||
|
||||
If the terminal does not know a field that a client send to it for a query it
|
||||
must respond back with the ``field=?``, that is, it must send back a question
|
||||
mark as the value.
|
||||
|
||||
|
||||
Setting color values
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To set a color value, the client program sends this escape code with the
|
||||
``value`` field set to either an :ref:`encoded color value
|
||||
<color_control_color_encoding>` or the empty value. The empty value means
|
||||
the terminal should use a dynamic color for example reverse video for
|
||||
selections or similar. To reset a color to its default value (i.e. the value it
|
||||
would have if it was never set) the client program should send just the key
|
||||
name with no ``=`` and no value. For example::
|
||||
|
||||
<OSC> 21 ; foreground=green ; cursor= ; background <ST>
|
||||
|
||||
This sets the foreground to the color green, sets the cursor color to dynamic
|
||||
(usually meaning the cursor takes the color of the text under it) and resets
|
||||
the background color to its default value.
|
||||
|
||||
To check if setting succeeded, the client can simply query the color, in fact
|
||||
the two can be combined into a single escape code, for example::
|
||||
|
||||
<OSC> 21 ; foreground=white ; foreground=? <ST>
|
||||
|
||||
The terminal will change the foreground color and reply with the new foreground
|
||||
color.
|
||||
|
||||
|
||||
.. _color_control_color_encoding:
|
||||
|
||||
Color value encoding
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The color encoding is inherited from the scheme used by XTerm, for
|
||||
compatibility, but a sane, rigorously specified subset is chosen.
|
||||
|
||||
RGB colors are encoded in one of three forms:
|
||||
|
||||
rgb:<red>/<green>/<blue>
|
||||
<red>, <green>, <blue> := h | hh | hhh | hhhh
|
||||
h := single hexadecimal digits (case insignificant)
|
||||
Note that h indicates the value scaled in 4 bits, hh the value scaled in 8 bits, hhh the value scaled in 12 bits, and hhhh the value scaled
|
||||
in 16 bits, respectively.
|
||||
|
||||
#<h...>
|
||||
h := single hexadecimal digits (case insignificant)
|
||||
#RGB (4 bits each)
|
||||
#RRGGBB (8 bits each)
|
||||
#RRRGGGBBB (12 bits each)
|
||||
#RRRRGGGGBBBB (16 bits each)
|
||||
The R, G, and B represent single hexadecimal digits. When fewer than 16 bits each are specified, they represent the most significant bits
|
||||
of the value (unlike the “rgb:” syntax, in which values are scaled). For example, the string ``#3a7`` is the same as ``#3000a0007000``.
|
||||
|
||||
rgbi:<red>/<green>/<blue>
|
||||
red, green, and blue are floating-point values between 0.0 and 1.0, inclusive. The input format for these values is an optional
|
||||
sign, a string of numbers possibly containing a decimal point, and an optional exponent field containing an E or e followed by a possibly
|
||||
signed integer string.
|
||||
|
||||
In addition, the following color names are accepted (case-insensitively) corresponding to the
|
||||
specified RGB values.
|
||||
|
||||
.. include:: generated/color-names.rst
|
||||
|
||||
15
docs/conf.py
15
docs/conf.py
@@ -289,6 +289,20 @@ if you specify a program-to-run you can use the special placeholder
|
||||
# }}}
|
||||
|
||||
|
||||
def write_color_names_table() -> None: # {{{
|
||||
from kitty.rgb import color_names
|
||||
def s(c: Any) -> str:
|
||||
return f'{c.red:02x}/{c.green:02x}/{c.blue:02x}'
|
||||
with open('generated/color-names.rst', 'w') as f:
|
||||
p = partial(print, file=f)
|
||||
p('=' * 50, '=' * 20)
|
||||
p('Name'.ljust(50), 'RGB value')
|
||||
p('=' * 50, '=' * 20)
|
||||
for name, col in color_names.items():
|
||||
p(name.ljust(50), s(col))
|
||||
p('=' * 50, '=' * 20)
|
||||
# }}}
|
||||
|
||||
def write_remote_control_protocol_docs() -> None: # {{{
|
||||
from kitty.rc.base import RemoteCommand, all_command_names, command_for_name
|
||||
field_pat = re.compile(r'\s*([^:]+?)\s*:\s*(.+)')
|
||||
@@ -750,6 +764,7 @@ def setup(app: Any) -> None:
|
||||
kn = all_kitten_names()
|
||||
write_cli_docs(kn)
|
||||
write_remote_control_protocol_docs()
|
||||
write_color_names_table()
|
||||
write_conf_docs(app, kn)
|
||||
app.add_config_value('string_replacements', {}, True)
|
||||
app.connect('source-read', replace_string)
|
||||
|
||||
@@ -1522,6 +1522,8 @@ When the background color matches this color, :opt:`background_opacity` is appli
|
||||
to render it as semi-transparent, just as for colors matching the background color.
|
||||
Useful in more complex UIs like editors where you could want more than a single background color
|
||||
to be rendered as transparent, for instance, for a cursor highlight line background.
|
||||
Terminal applications can set this color using :ref:`The kitty color control <color_control>`
|
||||
escape code.
|
||||
''')
|
||||
|
||||
opt('dynamic_background_opacity', 'no',
|
||||
|
||||
24
kitty/rgb.py
generated
24
kitty/rgb.py
generated
@@ -845,27 +845,3 @@ color_names = {
|
||||
'yellow4': Color(139, 139, 0),
|
||||
'yellowgreen': Color(154, 205, 50)}
|
||||
# END_DATA_SECTION }}}
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Read RGB color table from specified rgb.txt file
|
||||
import pprint
|
||||
import sys
|
||||
data = {}
|
||||
with open(sys.argv[-1]) as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line or line.startswith('!'):
|
||||
continue
|
||||
parts = line.split()
|
||||
r, g, b = map(int, parts[:3])
|
||||
name = ' '.join(parts[3:]).lower()
|
||||
data[name] = data[name.replace(' ', '')] = r, g, b
|
||||
formatted_data = pprint.pformat(data).replace('{', '{\n ').replace('(', 'Color(')
|
||||
with open(__file__, 'r+') as src:
|
||||
raw = src.read()
|
||||
raw = re.sub(
|
||||
r'^# BEGIN_DATA_SECTION {{{$.*^# END_DATA_SECTION }}}',
|
||||
'# BEGIN_DATA_SECTION {{{\ncolor_names = %s\n# END_DATA_SECTION }}}' % formatted_data,
|
||||
raw, flags=re.DOTALL | re.MULTILINE
|
||||
)
|
||||
src.seek(0), src.truncate(), src.write(raw)
|
||||
|
||||
Reference in New Issue
Block a user