API to set text in Line efficiently
This commit is contained in:
parent
b02dc836fb
commit
44e8238eaf
@ -112,6 +112,10 @@ class Line:
|
|||||||
to.bg[dest] = self.bg[src]
|
to.bg[dest] = self.bg[src]
|
||||||
to.decoration_fg[dest] = self.decoration_fg[src]
|
to.decoration_fg[dest] = self.decoration_fg[src]
|
||||||
|
|
||||||
|
def cursor_to_attrs(self, c: Cursor) -> int:
|
||||||
|
return ((c.decoration & 0b11) << DECORATION_SHIFT) | ((c.bold & 0b1) << BOLD_SHIFT) | \
|
||||||
|
((c.italic & 0b1) << ITALIC_SHIFT) | ((c.reverse & 0b1) << REVERSE_SHIFT) | ((c.strikethrough & 0b1) << STRIKE_SHIFT)
|
||||||
|
|
||||||
def apply_cursor(self, c: Cursor, at: int=0, num: int=1, clear_char=False, char=' ') -> None:
|
def apply_cursor(self, c: Cursor, at: int=0, num: int=1, clear_char=False, char=' ') -> None:
|
||||||
for i in range(at, at + num):
|
for i in range(at, at + num):
|
||||||
self.fg[i] = c.fg
|
self.fg[i] = c.fg
|
||||||
@ -121,8 +125,7 @@ class Line:
|
|||||||
ch = ord(char) if clear_char else sc & CHAR_MASK
|
ch = ord(char) if clear_char else sc & CHAR_MASK
|
||||||
sattrs = sc >> ATTRS_SHIFT
|
sattrs = sc >> ATTRS_SHIFT
|
||||||
w = 1 if clear_char else sattrs & WIDTH_MASK
|
w = 1 if clear_char else sattrs & WIDTH_MASK
|
||||||
attrs = w | ((c.decoration & 0b11) << DECORATION_SHIFT) | ((c.bold & 0b1) << BOLD_SHIFT) | \
|
attrs = w | self.cursor_to_attrs(c)
|
||||||
((c.italic & 0b1) << ITALIC_SHIFT) | ((c.reverse & 0b1) << REVERSE_SHIFT) | ((c.strikethrough & 0b1) << STRIKE_SHIFT)
|
|
||||||
self.char[i] = (ch & CHAR_MASK) | (attrs << ATTRS_SHIFT)
|
self.char[i] = (ch & CHAR_MASK) | (attrs << ATTRS_SHIFT)
|
||||||
|
|
||||||
def cursor_from(self, x: int, ypos: int=0) -> Cursor:
|
def cursor_from(self, x: int, ypos: int=0) -> Cursor:
|
||||||
@ -136,6 +139,17 @@ class Line:
|
|||||||
c.strikethrough = bool((attrs >> STRIKE_SHIFT) & 0b1)
|
c.strikethrough = bool((attrs >> STRIKE_SHIFT) & 0b1)
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
def set_text(self, text: str, offset_in_text: int, sz: int, cursor: Cursor) -> None:
|
||||||
|
' Set the specified text in this line, with attributes taken from the cursor '
|
||||||
|
attrs = self.cursor_to_attrs(cursor) | 1
|
||||||
|
fg, bg, dfg = cursor.fg, cursor.bg, cursor.decoration_fg
|
||||||
|
dx = cursor.x
|
||||||
|
for cpos in range(offset_in_text, offset_in_text + sz):
|
||||||
|
ch = ord(text[cpos]) & CHAR_MASK
|
||||||
|
self.char[dx] = ch | (attrs << ATTRS_SHIFT)
|
||||||
|
self.fg[dx], self.bg[dx], self.decoration_fg[dx] = fg, bg, dfg
|
||||||
|
dx += 1
|
||||||
|
|
||||||
def copy_slice(self, src, dest, num):
|
def copy_slice(self, src, dest, num):
|
||||||
src, dest = slice(src, src + num), slice(dest, dest + num)
|
src, dest = slice(src, src + num), slice(dest, dest + num)
|
||||||
for a in (self.char, self.fg, self.bg, self.decoration_fg):
|
for a in (self.char, self.fg, self.bg, self.decoration_fg):
|
||||||
@ -164,10 +178,14 @@ class Line:
|
|||||||
def width(self, i):
|
def width(self, i):
|
||||||
return (self.char[i] >> ATTRS_SHIFT) & 0b11
|
return (self.char[i] >> ATTRS_SHIFT) & 0b11
|
||||||
|
|
||||||
def set_char(self, i, ch, width=1):
|
def set_char(self, i: int, ch: str, width: int=1, cursor: Cursor=None) -> None:
|
||||||
c = self.char[i]
|
if cursor is None:
|
||||||
a = c >> ATTRS_SHIFT
|
c = self.char[i]
|
||||||
a = (a & ~WIDTH_MASK) | (width & WIDTH_MASK)
|
a = (c >> ATTRS_SHIFT) & ~WIDTH_MASK
|
||||||
|
else:
|
||||||
|
a = self.cursor_to_attrs(cursor)
|
||||||
|
self.fg[i], self.bg[i], self.decoration_fg[i] = cursor.fg, cursor.bg, cursor.decoration_fg
|
||||||
|
a |= width & WIDTH_MASK
|
||||||
self.char[i] = (a << ATTRS_SHIFT) | (ord(ch) & CHAR_MASK)
|
self.char[i] = (a << ATTRS_SHIFT) | (ord(ch) & CHAR_MASK)
|
||||||
|
|
||||||
def set_bold(self, i, val):
|
def set_bold(self, i, val):
|
||||||
|
|||||||
@ -8,12 +8,3 @@ from unittest import TestCase
|
|||||||
class BaseTest(TestCase):
|
class BaseTest(TestCase):
|
||||||
|
|
||||||
ae = TestCase.assertEqual
|
ae = TestCase.assertEqual
|
||||||
|
|
||||||
|
|
||||||
def set_text_in_line(line, text, offset=0):
|
|
||||||
pos = offset
|
|
||||||
for ch in text:
|
|
||||||
line.set_char(pos, ch)
|
|
||||||
pos += 1
|
|
||||||
if pos >= len(line):
|
|
||||||
break
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import codecs
|
import codecs
|
||||||
|
|
||||||
from . import BaseTest, set_text_in_line
|
from . import BaseTest
|
||||||
|
|
||||||
from kitty.data_types import Line, Cursor
|
from kitty.data_types import Line, Cursor
|
||||||
from kitty.utils import is_simple_string, wcwidth
|
from kitty.utils import is_simple_string, wcwidth
|
||||||
@ -15,7 +15,7 @@ class TestDataTypes(BaseTest):
|
|||||||
def test_line_ops(self):
|
def test_line_ops(self):
|
||||||
t = 'Testing with simple text'
|
t = 'Testing with simple text'
|
||||||
l = Line(len(t))
|
l = Line(len(t))
|
||||||
set_text_in_line(l, t)
|
l.set_text(t, 0, len(t), Cursor())
|
||||||
self.ae(l, l)
|
self.ae(l, l)
|
||||||
self.ae(str(l), t)
|
self.ae(str(l), t)
|
||||||
self.ae(str(l.copy()), t)
|
self.ae(str(l.copy()), t)
|
||||||
@ -49,7 +49,7 @@ class TestDataTypes(BaseTest):
|
|||||||
|
|
||||||
t = '0123456789'
|
t = '0123456789'
|
||||||
lo = Line(len(t))
|
lo = Line(len(t))
|
||||||
set_text_in_line(lo, t)
|
lo.set_text(t, 0, len(t), Cursor())
|
||||||
l = lo.copy()
|
l = lo.copy()
|
||||||
l.right_shift(4, 2)
|
l.right_shift(4, 2)
|
||||||
self.ae(str(l), '0123454567')
|
self.ae(str(l), '0123454567')
|
||||||
@ -75,6 +75,14 @@ class TestDataTypes(BaseTest):
|
|||||||
l.set_decoration(0, q.decoration)
|
l.set_decoration(0, q.decoration)
|
||||||
c = l.cursor_from(0)
|
c = l.cursor_from(0)
|
||||||
self.ae(c, q)
|
self.ae(c, q)
|
||||||
|
l = Line(len(t))
|
||||||
|
l.set_text(t, 0, len(t), q)
|
||||||
|
self.ae(l.cursor_from(0), q)
|
||||||
|
l.set_text('axyb', 1, 2, Cursor(3))
|
||||||
|
self.ae(str(l), '012xy56789')
|
||||||
|
l = Line(1)
|
||||||
|
l.set_char(0, 'x', cursor=q)
|
||||||
|
self.ae(l.cursor_from(0), q)
|
||||||
|
|
||||||
def test_utils(self):
|
def test_utils(self):
|
||||||
d = codecs.getincrementaldecoder('utf-8')('strict').decode
|
d = codecs.getincrementaldecoder('utf-8')('strict').decode
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user