Add an option to use a modern wcwidth() instead of the system one
This commit is contained in:
parent
a8408a1ce4
commit
cb5d6547e5
@ -109,6 +109,7 @@ type_map = {
|
||||
'cursor_blink_interval': float,
|
||||
'cursor_stop_blinking_after': float,
|
||||
'enabled_layouts': to_layout_names,
|
||||
'use_system_wcwidth': to_bool,
|
||||
}
|
||||
|
||||
for name in 'foreground background cursor active_border_color inactive_border_color selection_foreground selection_background'.split():
|
||||
|
||||
@ -20,6 +20,17 @@ drain_read(PyObject UNUSED *self, PyObject *fd) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
wcwidth_wrap(PyObject UNUSED *self, PyObject *chr) {
|
||||
return PyLong_FromUnsignedLong(safe_wcwidth(PyLong_AsLong(chr)));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
change_wcwidth_wrap(PyObject UNUSED *self, PyObject *use9) {
|
||||
change_wcwidth(PyObject_IsTrue(use9));
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
GL_METHODS
|
||||
{"drain_read", (PyCFunction)drain_read, METH_O, ""},
|
||||
@ -27,6 +38,8 @@ static PyMethodDef module_methods[] = {
|
||||
{"parse_bytes_dump", (PyCFunction)parse_bytes_dump, METH_VARARGS, ""},
|
||||
{"read_bytes", (PyCFunction)read_bytes, METH_VARARGS, ""},
|
||||
{"read_bytes_dump", (PyCFunction)read_bytes_dump, METH_VARARGS, ""},
|
||||
{"wcwidth", (PyCFunction)wcwidth_wrap, METH_O, ""},
|
||||
{"change_wcwidth", (PyCFunction)change_wcwidth_wrap, METH_O, ""},
|
||||
GLFW_FUNC_WRAPPERS
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
@ -355,6 +355,8 @@ void historybuf_add_line(HistoryBuf *self, const Line *line);
|
||||
void historybuf_rewrap(HistoryBuf *self, HistoryBuf *other);
|
||||
void historybuf_init_line(HistoryBuf *self, index_type num, Line *l);
|
||||
|
||||
unsigned int safe_wcwidth(uint32_t ch);
|
||||
void change_wcwidth(bool use9);
|
||||
void screen_align(Screen*);
|
||||
void screen_restore_cursor(Screen *);
|
||||
void screen_save_cursor(Screen *);
|
||||
|
||||
@ -73,6 +73,15 @@ open_url_modifiers ctrl+shift
|
||||
# use the operating system's default URL handler.
|
||||
open_url_with default
|
||||
|
||||
# Choose whether to use the system implementation of wcwidth() (used to
|
||||
# control how many cells a character is rendered in). If you use the system
|
||||
# implementation, then kitty and any programs running in it will agree. The
|
||||
# problem is that system implementations often are based on outdated unicode
|
||||
# standards and get the width of many characters, such as emoji, wrong. So if
|
||||
# you are using kitty with programs that have their own up-to-date wcwidth()
|
||||
# implementation, set this option to no.
|
||||
use_system_wcwidth yes
|
||||
|
||||
# The value of the TERM environment variable to set
|
||||
term xterm-kitty
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ from .fast_data_types import (
|
||||
GLFW_CONTEXT_VERSION_MINOR, GLFW_OPENGL_PROFILE,
|
||||
GLFW_OPENGL_FORWARD_COMPAT, GLFW_OPENGL_CORE_PROFILE, GLFW_SAMPLES,
|
||||
glfw_set_error_callback, glfw_init, glfw_terminate, glfw_window_hint,
|
||||
glfw_swap_interval, glfw_wait_events, Window
|
||||
glfw_swap_interval, glfw_wait_events, Window, change_wcwidth
|
||||
)
|
||||
from .utils import safe_print
|
||||
|
||||
@ -137,6 +137,7 @@ def main():
|
||||
main(args.replay_commands)
|
||||
return
|
||||
opts = load_config(args.config)
|
||||
change_wcwidth(not opts.use_system_wcwidth)
|
||||
glfw_set_error_callback(on_glfw_error)
|
||||
enable_automatic_opengl_error_checking(False)
|
||||
if not glfw_init():
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "unicode-data.h"
|
||||
#include "tracker.h"
|
||||
#include "modes.h"
|
||||
#include "wcwidth9.h"
|
||||
|
||||
static const ScreenModes empty_modes = {0, .mDECAWM=true, .mDECTCEM=true, .mDECARM=true};
|
||||
|
||||
@ -195,13 +196,21 @@ screen_designate_charset(Screen *self, uint32_t which, uint32_t as) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
static int (*wcwidth_impl)(wchar_t) = wcwidth;
|
||||
|
||||
unsigned int
|
||||
safe_wcwidth(uint32_t ch) {
|
||||
int ans = wcwidth(ch);
|
||||
int ans = wcwidth_impl(ch);
|
||||
if (ans < 0) ans = 1;
|
||||
return MIN(2, ans);
|
||||
}
|
||||
|
||||
void
|
||||
change_wcwidth(bool use9) {
|
||||
wcwidth_impl = (use9) ? wcwidth9 : wcwidth;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
screen_draw(Screen *self, uint32_t och) {
|
||||
if (is_ignored_char(och)) return;
|
||||
|
||||
@ -7,7 +7,6 @@ import os
|
||||
import signal
|
||||
import shlex
|
||||
import subprocess
|
||||
import ctypes
|
||||
import math
|
||||
from collections import namedtuple
|
||||
from contextlib import contextmanager
|
||||
@ -15,13 +14,7 @@ from functools import lru_cache
|
||||
from time import monotonic
|
||||
|
||||
from .constants import isosx
|
||||
from .fast_data_types import glfw_get_physical_dpi
|
||||
|
||||
libc = ctypes.CDLL(None)
|
||||
wcwidth_native = libc.wcwidth
|
||||
del libc
|
||||
wcwidth_native.argtypes = [ctypes.c_wchar]
|
||||
wcwidth_native.restype = ctypes.c_int
|
||||
from .fast_data_types import glfw_get_physical_dpi, wcwidth as wcwidth_impl
|
||||
|
||||
|
||||
def safe_print(*a, **k):
|
||||
@ -37,10 +30,10 @@ def ceil_int(x):
|
||||
|
||||
@lru_cache(maxsize=2**13)
|
||||
def wcwidth(c: str) -> int:
|
||||
ans = min(2, wcwidth_native(c))
|
||||
if ans == -1:
|
||||
ans = 1
|
||||
return ans
|
||||
try:
|
||||
return wcwidth_impl(ord(c))
|
||||
except TypeError:
|
||||
return wcwidth_impl(ord(c[0]))
|
||||
|
||||
|
||||
@contextmanager
|
||||
|
||||
1321
kitty/wcwidth9.h
Normal file
1321
kitty/wcwidth9.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user