mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-12 11:39:33 +02:00
Move word selection code into C, avoiding the need for the python regex module
This commit is contained in:
@@ -3,12 +3,11 @@
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import re
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
from ctypes import sizeof
|
||||
from enum import Enum
|
||||
|
||||
from .config import build_ansi_color_table, defaults
|
||||
from .config import build_ansi_color_table
|
||||
from .constants import (
|
||||
GLfloat, GLuint, ScreenGeometry, cell_size, viewport_size
|
||||
)
|
||||
@@ -22,7 +21,7 @@ from .fast_data_types import (
|
||||
from .rgb import to_color
|
||||
from .shaders import ShaderProgram, load_shaders
|
||||
from .utils import (
|
||||
color_as_int, color_from_int, get_logical_dpi, open_url, safe_print,
|
||||
color_as_int, color_from_int, get_logical_dpi, open_url,
|
||||
set_primary_selection
|
||||
)
|
||||
|
||||
@@ -143,15 +142,6 @@ class CharGrid:
|
||||
self.default_cursor = self.current_cursor = Cursor(0, 0, opts.cursor_shape, opts.cursor_blink_interval > 0)
|
||||
self.opts = opts
|
||||
|
||||
def escape(chars):
|
||||
return ''.join(frozenset(chars)).replace('\\', r'\\').replace(']', r'\]').replace('-', r'\-')
|
||||
|
||||
try:
|
||||
self.word_pat = re.compile(r'[\w{}]'.format(escape(self.opts.select_by_word_characters)), re.UNICODE)
|
||||
except Exception:
|
||||
safe_print('Invalid characters in select_by_word_characters, ignoring', file=sys.stderr)
|
||||
self.word_pat = re.compile(r'[\w{}]'.format(escape(defaults.select_by_word_characters)), re.UNICODE)
|
||||
|
||||
def destroy(self, cell_program):
|
||||
if self.vao_id is not None:
|
||||
cell_program.remove_vertex_array(self.vao_id)
|
||||
@@ -282,14 +272,8 @@ class CharGrid:
|
||||
s.start_y = s.end_y = y
|
||||
s.in_progress = False
|
||||
if count == 2:
|
||||
i = x
|
||||
while i >= 0 and self.word_pat.match(line[i]) is not None:
|
||||
i -= 1
|
||||
s.start_x = i if i == x else i + 1
|
||||
i = x
|
||||
while i < self.screen.columns and self.word_pat.match(line[i]) is not None:
|
||||
i += 1
|
||||
s.end_x = i if i == x else i - 1
|
||||
s.start_x, xlimit = self.screen.selection_range_for_word(x, y, self.scrolled_by, self.opts.select_by_word_characters)
|
||||
s.end_x = max(s.start_x, xlimit - 1)
|
||||
elif count == 3:
|
||||
s.start_x, xlimit = self.screen.selection_range_for_line(y, self.scrolled_by)
|
||||
s.end_x = max(s.start_x, xlimit - 1)
|
||||
|
||||
@@ -1288,6 +1288,32 @@ selection_range_for_line(Screen *self, PyObject *args) {
|
||||
return Py_BuildValue("II", (unsigned int)xstart, (unsigned int)xlimit);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
has_char(int kind, void *data, Py_ssize_t sz, char_type ch) {
|
||||
for (Py_ssize_t i = 0; i < sz; i++) {
|
||||
if (PyUnicode_READ(kind, data, i) == ch) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
selection_range_for_word(Screen *self, PyObject *args) {
|
||||
unsigned int x, y, scrolled_by;
|
||||
PyObject *extra_chars;
|
||||
if (!PyArg_ParseTuple(args, "IIIU", &x, &y, &scrolled_by, &extra_chars)) return NULL;
|
||||
if (PyUnicode_READY(extra_chars) != 0) return NULL;
|
||||
if (y >= self->lines) { PyErr_SetString(PyExc_ValueError, "y larger than lines"); return NULL; }
|
||||
if (x >= self->columns) { PyErr_SetString(PyExc_ValueError, "x larger than columns"); return NULL; }
|
||||
Line *line = visual_line_(self, y, scrolled_by);
|
||||
#define is_ok(x) (is_word_char((line->cells[x].ch) & CHAR_MASK) || has_char(PyUnicode_KIND(extra_chars), PyUnicode_DATA(extra_chars), PyUnicode_GET_LENGTH(extra_chars), (line->cells[x].ch) & CHAR_MASK))
|
||||
if (!is_ok(x)) Py_BuildValue("II", x, x + 1);
|
||||
unsigned int start = x, end = x;
|
||||
while(start > 0 && is_ok(start - 1)) start--;
|
||||
while(end < self->columns - 1 && is_ok(end + 1)) end++;
|
||||
return Py_BuildValue("II", start, end + 1);
|
||||
#undef is_ok
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
PyObject* mark_as_dirty(Screen *self) {
|
||||
@@ -1375,6 +1401,7 @@ static PyMethodDef methods[] = {
|
||||
MND(set_margins, METH_VARARGS)
|
||||
MND(apply_selection, METH_VARARGS)
|
||||
MND(selection_range_for_line, METH_VARARGS)
|
||||
MND(selection_range_for_word, METH_VARARGS)
|
||||
MND(text_for_selection, METH_VARARGS)
|
||||
MND(toggle_alt_screen, METH_NOARGS)
|
||||
MND(reset_callbacks, METH_NOARGS)
|
||||
|
||||
Reference in New Issue
Block a user