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.
|
||||
*/
|
||||
|
||||
#define EXTRA_INIT if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||
#include "data-types.h"
|
||||
#include <structmember.h>
|
||||
|
||||
@ -29,7 +30,9 @@ static uint32_t FG_BG_256[256] = {
|
||||
0xffffff, // 15
|
||||
};
|
||||
|
||||
PyObject* create_256_color_table() {
|
||||
static inline void
|
||||
init_FG_BG_table() {
|
||||
if (UNLIKELY(FG_BG_256[255] == 0)) {
|
||||
// colors 16..232: the 6x6x6 color cube
|
||||
const uint8_t valuerange[6] = {0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff};
|
||||
uint8_t i, j=16;
|
||||
@ -42,10 +45,14 @@ PyObject* create_256_color_table() {
|
||||
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();
|
||||
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]);
|
||||
if (temp == NULL) { Py_CLEAR(ans); return NULL; }
|
||||
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);
|
||||
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->orig_color_table, FG_BG_256, sizeof(FG_BG_256));
|
||||
self->dirty = true;
|
||||
@ -80,12 +87,10 @@ alloc_color_profile() {
|
||||
|
||||
static PyObject*
|
||||
update_ansi_color_table(ColorProfile *self, PyObject *val) {
|
||||
#define update_ansi_color_table_doc "Update the 16 basic colors"
|
||||
index_type i;
|
||||
|
||||
#define update_ansi_color_table_doc "Update the 256 basic colors"
|
||||
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; }
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (PyList_GET_SIZE(val) != arraysz(FG_BG_256)) { PyErr_SetString(PyExc_TypeError, "color table must have 256 items"); return NULL; }
|
||||
for (size_t i = 0; i < arraysz(FG_BG_256); i++) {
|
||||
self->color_table[i] = PyLong_AsUnsignedLong(PyList_GET_ITEM(val, 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);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
default_color_table(PyObject *self UNUSED, PyObject *args UNUSED) {
|
||||
return create_256_color_table();
|
||||
}
|
||||
|
||||
// Boilerplate {{{
|
||||
|
||||
@ -236,5 +245,11 @@ PyTypeObject ColorProfile_Type = {
|
||||
.tp_new = new,
|
||||
};
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
METHODB(default_color_table, METH_NOARGS),
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
INIT_TYPE(ColorProfile)
|
||||
// }}}
|
||||
|
||||
@ -20,6 +20,7 @@ from .config_utils import (
|
||||
from .constants import cache_dir, defconf
|
||||
from .fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE
|
||||
from .layout import all_layouts
|
||||
from .rgb import color_from_int
|
||||
from .utils import log_error
|
||||
|
||||
MINIMUM_FONT_SIZE = 4
|
||||
@ -333,8 +334,8 @@ for name in (
|
||||
' selection_foreground selection_background url_color'
|
||||
).split():
|
||||
type_map[name] = to_color
|
||||
for i in range(16):
|
||||
type_map['color%d' % i] = to_color
|
||||
for i in range(256):
|
||||
type_map['color{}'.format(i)] = to_color
|
||||
for a in ('active', 'inactive'):
|
||||
for b in ('foreground', 'background'):
|
||||
type_map['%s_tab_%s' % (a, b)] = to_color
|
||||
@ -376,7 +377,17 @@ def parse_config(lines, check_keys=True):
|
||||
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(
|
||||
'combine send_text goto_tab goto_layout set_font_size new_tab_with_cwd new_window_with_cwd new_os_window_with_cwd'.
|
||||
split()
|
||||
@ -447,7 +458,7 @@ def load_config(*paths, overrides=None) -> Options:
|
||||
if overrides is not None:
|
||||
vals = parse_config(overrides)
|
||||
ans = merge_configs(ans, vals)
|
||||
return Options(**ans)
|
||||
return Options(ans)
|
||||
|
||||
|
||||
def build_ansi_color_table(opts: Options = defaults):
|
||||
@ -458,7 +469,7 @@ def build_ansi_color_table(opts: Options = defaults):
|
||||
def col(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):
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
from collections import namedtuple
|
||||
|
||||
from .rgb import to_color as as_color
|
||||
from .utils import log_error
|
||||
@ -80,9 +79,25 @@ def parse_config_base(
|
||||
_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):
|
||||
with open(defaults_path, encoding='utf-8', errors='replace') as f:
|
||||
defaults = parse_config(f, check_keys=False)
|
||||
Options = namedtuple('Defaults', ','.join(defaults.keys()))
|
||||
defaults = Options(**defaults)
|
||||
Options = create_options_class(defaults.keys())
|
||||
defaults = Options(defaults)
|
||||
return Options, defaults
|
||||
|
||||
@ -247,7 +247,8 @@ selection_foreground #000000
|
||||
selection_background #FFFACD
|
||||
|
||||
# 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
|
||||
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))
|
||||
|
||||
|
||||
def color_from_int(x):
|
||||
return Color((x >> 16) & 255, (x >> 8) & 255, x & 255)
|
||||
|
||||
|
||||
def to_color(raw, validate=False):
|
||||
# See man XParseColor
|
||||
x = raw.strip().lower()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user