Allow setting all 256 colors in the config file
This commit is contained in:
parent
1c78633d1a
commit
910cebeeb5
@ -5,6 +5,7 @@
|
|||||||
* Distributed under terms of the GPL3 license.
|
* Distributed under terms of the GPL3 license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define EXTRA_INIT if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
#include <structmember.h>
|
#include <structmember.h>
|
||||||
|
|
||||||
@ -29,23 +30,29 @@ static uint32_t FG_BG_256[256] = {
|
|||||||
0xffffff, // 15
|
0xffffff, // 15
|
||||||
};
|
};
|
||||||
|
|
||||||
PyObject* create_256_color_table() {
|
static inline void
|
||||||
// colors 16..232: the 6x6x6 color cube
|
init_FG_BG_table() {
|
||||||
const uint8_t valuerange[6] = {0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff};
|
if (UNLIKELY(FG_BG_256[255] == 0)) {
|
||||||
uint8_t i, j=16;
|
// colors 16..232: the 6x6x6 color cube
|
||||||
for(i = 0; i < 217; i++, j++) {
|
const uint8_t valuerange[6] = {0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff};
|
||||||
uint8_t r = valuerange[(i / 36) % 6], g = valuerange[(i / 6) % 6], b = valuerange[i % 6];
|
uint8_t i, j=16;
|
||||||
FG_BG_256[j] = (r << 16) | (g << 8) | b;
|
for(i = 0; i < 217; i++, j++) {
|
||||||
}
|
uint8_t r = valuerange[(i / 36) % 6], g = valuerange[(i / 6) % 6], b = valuerange[i % 6];
|
||||||
// colors 233..255: grayscale
|
FG_BG_256[j] = (r << 16) | (g << 8) | b;
|
||||||
for(i = 1; i < 24; i++, j++) {
|
}
|
||||||
uint8_t v = 8 + i * 10;
|
// colors 233..255: grayscale
|
||||||
FG_BG_256[j] = (v << 16) | (v << 8) | v;
|
for(i = 1; i < 24; i++, j++) {
|
||||||
|
uint8_t v = 8 + i * 10;
|
||||||
|
FG_BG_256[j] = (v << 16) | (v << 8) | v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *ans = PyTuple_New(255);
|
PyObject* create_256_color_table() {
|
||||||
|
init_FG_BG_table();
|
||||||
|
PyObject *ans = PyTuple_New(arraysz(FG_BG_256));
|
||||||
if (ans == NULL) return PyErr_NoMemory();
|
if (ans == NULL) return PyErr_NoMemory();
|
||||||
for (i=0; i < 255; i++) {
|
for (size_t i=0; i < arraysz(FG_BG_256); i++) {
|
||||||
PyObject *temp = PyLong_FromUnsignedLong(FG_BG_256[i]);
|
PyObject *temp = PyLong_FromUnsignedLong(FG_BG_256[i]);
|
||||||
if (temp == NULL) { Py_CLEAR(ans); return NULL; }
|
if (temp == NULL) { Py_CLEAR(ans); return NULL; }
|
||||||
PyTuple_SET_ITEM(ans, i, temp);
|
PyTuple_SET_ITEM(ans, i, temp);
|
||||||
@ -59,7 +66,7 @@ new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) {
|
|||||||
|
|
||||||
self = (ColorProfile *)type->tp_alloc(type, 0);
|
self = (ColorProfile *)type->tp_alloc(type, 0);
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
if (FG_BG_256[255] == 0) create_256_color_table();
|
init_FG_BG_table();
|
||||||
memcpy(self->color_table, FG_BG_256, sizeof(FG_BG_256));
|
memcpy(self->color_table, FG_BG_256, sizeof(FG_BG_256));
|
||||||
memcpy(self->orig_color_table, FG_BG_256, sizeof(FG_BG_256));
|
memcpy(self->orig_color_table, FG_BG_256, sizeof(FG_BG_256));
|
||||||
self->dirty = true;
|
self->dirty = true;
|
||||||
@ -80,12 +87,10 @@ alloc_color_profile() {
|
|||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
update_ansi_color_table(ColorProfile *self, PyObject *val) {
|
update_ansi_color_table(ColorProfile *self, PyObject *val) {
|
||||||
#define update_ansi_color_table_doc "Update the 16 basic colors"
|
#define update_ansi_color_table_doc "Update the 256 basic colors"
|
||||||
index_type i;
|
|
||||||
|
|
||||||
if (!PyList_Check(val)) { PyErr_SetString(PyExc_TypeError, "color table must be a list"); return NULL; }
|
if (!PyList_Check(val)) { PyErr_SetString(PyExc_TypeError, "color table must be a list"); return NULL; }
|
||||||
if (PyList_GET_SIZE(val) != 16) { PyErr_SetString(PyExc_TypeError, "color table must have 16 items"); return NULL; }
|
if (PyList_GET_SIZE(val) != arraysz(FG_BG_256)) { PyErr_SetString(PyExc_TypeError, "color table must have 256 items"); return NULL; }
|
||||||
for (i = 0; i < 16; i++) {
|
for (size_t i = 0; i < arraysz(FG_BG_256); i++) {
|
||||||
self->color_table[i] = PyLong_AsUnsignedLong(PyList_GET_ITEM(val, i));
|
self->color_table[i] = PyLong_AsUnsignedLong(PyList_GET_ITEM(val, i));
|
||||||
self->orig_color_table[i] = self->color_table[i];
|
self->orig_color_table[i] = self->color_table[i];
|
||||||
}
|
}
|
||||||
@ -184,6 +189,10 @@ color_table_address(ColorProfile *self, PyObject *a UNUSED) {
|
|||||||
return PyLong_FromVoidPtr((void*)self->color_table);
|
return PyLong_FromVoidPtr((void*)self->color_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
default_color_table(PyObject *self UNUSED, PyObject *args UNUSED) {
|
||||||
|
return create_256_color_table();
|
||||||
|
}
|
||||||
|
|
||||||
// Boilerplate {{{
|
// Boilerplate {{{
|
||||||
|
|
||||||
@ -236,5 +245,11 @@ PyTypeObject ColorProfile_Type = {
|
|||||||
.tp_new = new,
|
.tp_new = new,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyMethodDef module_methods[] = {
|
||||||
|
METHODB(default_color_table, METH_NOARGS),
|
||||||
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
INIT_TYPE(ColorProfile)
|
INIT_TYPE(ColorProfile)
|
||||||
// }}}
|
// }}}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ from .config_utils import (
|
|||||||
from .constants import cache_dir, defconf
|
from .constants import cache_dir, defconf
|
||||||
from .fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE
|
from .fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE
|
||||||
from .layout import all_layouts
|
from .layout import all_layouts
|
||||||
|
from .rgb import color_from_int
|
||||||
from .utils import log_error
|
from .utils import log_error
|
||||||
|
|
||||||
MINIMUM_FONT_SIZE = 4
|
MINIMUM_FONT_SIZE = 4
|
||||||
@ -333,8 +334,8 @@ for name in (
|
|||||||
' selection_foreground selection_background url_color'
|
' selection_foreground selection_background url_color'
|
||||||
).split():
|
).split():
|
||||||
type_map[name] = to_color
|
type_map[name] = to_color
|
||||||
for i in range(16):
|
for i in range(256):
|
||||||
type_map['color%d' % i] = to_color
|
type_map['color{}'.format(i)] = to_color
|
||||||
for a in ('active', 'inactive'):
|
for a in ('active', 'inactive'):
|
||||||
for b in ('foreground', 'background'):
|
for b in ('foreground', 'background'):
|
||||||
type_map['%s_tab_%s' % (a, b)] = to_color
|
type_map['%s_tab_%s' % (a, b)] = to_color
|
||||||
@ -376,7 +377,17 @@ def parse_config(lines, check_keys=True):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
Options, defaults = init_config(default_config_path, parse_config)
|
def parse_defaults(lines, check_keys=False):
|
||||||
|
ans = parse_config(lines, check_keys)
|
||||||
|
dfctl = defines.default_color_table()
|
||||||
|
|
||||||
|
for i in range(16, 256):
|
||||||
|
k = 'color{}'.format(i)
|
||||||
|
ans.setdefault(k, color_from_int(dfctl[i]))
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
Options, defaults = init_config(default_config_path, parse_defaults)
|
||||||
actions = frozenset(all_key_actions) | frozenset(
|
actions = frozenset(all_key_actions) | frozenset(
|
||||||
'combine send_text goto_tab goto_layout set_font_size new_tab_with_cwd new_window_with_cwd new_os_window_with_cwd'.
|
'combine send_text goto_tab goto_layout set_font_size new_tab_with_cwd new_window_with_cwd new_os_window_with_cwd'.
|
||||||
split()
|
split()
|
||||||
@ -447,7 +458,7 @@ def load_config(*paths, overrides=None) -> Options:
|
|||||||
if overrides is not None:
|
if overrides is not None:
|
||||||
vals = parse_config(overrides)
|
vals = parse_config(overrides)
|
||||||
ans = merge_configs(ans, vals)
|
ans = merge_configs(ans, vals)
|
||||||
return Options(**ans)
|
return Options(ans)
|
||||||
|
|
||||||
|
|
||||||
def build_ansi_color_table(opts: Options = defaults):
|
def build_ansi_color_table(opts: Options = defaults):
|
||||||
@ -458,7 +469,7 @@ def build_ansi_color_table(opts: Options = defaults):
|
|||||||
def col(i):
|
def col(i):
|
||||||
return as_int(getattr(opts, 'color{}'.format(i)))
|
return as_int(getattr(opts, 'color{}'.format(i)))
|
||||||
|
|
||||||
return list(map(col, range(16)))
|
return list(map(col, range(256)))
|
||||||
|
|
||||||
|
|
||||||
def atomic_save(data, path):
|
def atomic_save(data, path):
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
from .rgb import to_color as as_color
|
from .rgb import to_color as as_color
|
||||||
from .utils import log_error
|
from .utils import log_error
|
||||||
@ -80,9 +79,25 @@ def parse_config_base(
|
|||||||
_parse(lines, type_map, special_handling, ans, all_keys)
|
_parse(lines, type_map, special_handling, ans, all_keys)
|
||||||
|
|
||||||
|
|
||||||
|
def create_options_class(keys):
|
||||||
|
keys = tuple(sorted(keys))
|
||||||
|
slots = keys + ('_fields',)
|
||||||
|
|
||||||
|
def __init__(self, kw):
|
||||||
|
for k, v in kw.items():
|
||||||
|
setattr(self, k, v)
|
||||||
|
|
||||||
|
def _asdict(self):
|
||||||
|
return {k: getattr(self, k) for k in self._fields}
|
||||||
|
|
||||||
|
ans = type('Options', (), {'__slots__': slots, '__init__': __init__, '_asdict': _asdict})
|
||||||
|
ans._fields = keys
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def init_config(defaults_path, parse_config):
|
def init_config(defaults_path, parse_config):
|
||||||
with open(defaults_path, encoding='utf-8', errors='replace') as f:
|
with open(defaults_path, encoding='utf-8', errors='replace') as f:
|
||||||
defaults = parse_config(f, check_keys=False)
|
defaults = parse_config(f, check_keys=False)
|
||||||
Options = namedtuple('Defaults', ','.join(defaults.keys()))
|
Options = create_options_class(defaults.keys())
|
||||||
defaults = Options(**defaults)
|
defaults = Options(defaults)
|
||||||
return Options, defaults
|
return Options, defaults
|
||||||
|
|||||||
@ -247,7 +247,8 @@ selection_foreground #000000
|
|||||||
selection_background #FFFACD
|
selection_background #FFFACD
|
||||||
|
|
||||||
# The 16 terminal colors. There are 8 basic colors, each color has a dull and
|
# The 16 terminal colors. There are 8 basic colors, each color has a dull and
|
||||||
# bright version.
|
# bright version. You can also set the remaining colors from the 256 color table
|
||||||
|
# as color16 to color256.
|
||||||
|
|
||||||
# black
|
# black
|
||||||
color0 #000000
|
color0 #000000
|
||||||
|
|||||||
4
kitty/rgb.py
generated
4
kitty/rgb.py
generated
@ -27,6 +27,10 @@ def parse_rgb(spec):
|
|||||||
return Color(*map(parse_single_color, colors))
|
return Color(*map(parse_single_color, colors))
|
||||||
|
|
||||||
|
|
||||||
|
def color_from_int(x):
|
||||||
|
return Color((x >> 16) & 255, (x >> 8) & 255, x & 255)
|
||||||
|
|
||||||
|
|
||||||
def to_color(raw, validate=False):
|
def to_color(raw, validate=False):
|
||||||
# See man XParseColor
|
# See man XParseColor
|
||||||
x = raw.strip().lower()
|
x = raw.strip().lower()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user