mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 22:28:24 +02:00
Merge branch 'pr-unicode-placeholders' of https://github.com/sergei-grechanik/kitty
This commit is contained in:
@@ -114,21 +114,21 @@ def load_helpers(self):
|
||||
return s, g, pl, sl
|
||||
|
||||
|
||||
def put_helpers(self, cw, ch):
|
||||
def put_helpers(self, cw, ch, cols=10, lines=5):
|
||||
iid = 0
|
||||
|
||||
def create_screen():
|
||||
s = self.create_screen(10, 5, cell_width=cw, cell_height=ch)
|
||||
s = self.create_screen(cols, lines, cell_width=cw, cell_height=ch)
|
||||
return s, 2 / s.columns, 2 / s.lines
|
||||
|
||||
def put_cmd(
|
||||
z=0, num_cols=0, num_lines=0, x_off=0, y_off=0, width=0,
|
||||
height=0, cell_x_off=0, cell_y_off=0, placement_id=0,
|
||||
cursor_movement=0
|
||||
cursor_movement=0, unicode_placeholder=0
|
||||
):
|
||||
return 'z=%d,c=%d,r=%d,x=%d,y=%d,w=%d,h=%d,X=%d,Y=%d,p=%d,C=%d' % (
|
||||
return 'z=%d,c=%d,r=%d,x=%d,y=%d,w=%d,h=%d,X=%d,Y=%d,p=%d,C=%d,U=%d' % (
|
||||
z, num_cols, num_lines, x_off, y_off, width, height, cell_x_off,
|
||||
cell_y_off, placement_id, cursor_movement
|
||||
cell_y_off, placement_id, cursor_movement, unicode_placeholder
|
||||
)
|
||||
|
||||
def put_image(screen, w, h, **kw):
|
||||
@@ -515,6 +515,232 @@ class TestGraphics(BaseTest):
|
||||
s.reset()
|
||||
self.assertEqual(s.grman.disk_cache.total_size, 0)
|
||||
|
||||
def test_unicode_placeholders(self):
|
||||
# This test tests basic image placement using using unicode placeholders
|
||||
cw, ch = 10, 20
|
||||
s, dx, dy, put_image, put_ref, layers, rect_eq = put_helpers(self, cw, ch)
|
||||
# Upload two images.
|
||||
put_image(s, 20, 20, num_cols=4, num_lines=2, unicode_placeholder=1, id=42)
|
||||
put_image(s, 10, 20, num_cols=4, num_lines=2, unicode_placeholder=1, id=(42<<16) + (43<<8) + 44)
|
||||
# The references are virtual, so no visible refs yet.
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 0)
|
||||
# A reminder of row/column diacritics meaning (assuming 0-based):
|
||||
# \u0305 -> 0
|
||||
# \u030D -> 1
|
||||
# \u030E -> 2
|
||||
# \u0310 -> 3
|
||||
# Now print the placeholders for the first image.
|
||||
# Encode the id as an 8-bit color.
|
||||
s.apply_sgr("38;5;42")
|
||||
# These two characters will become one 2x1 ref.
|
||||
s.draw("\U0010EEEE\u0305\u0305\U0010EEEE\u0305\u030D")
|
||||
# These two characters will be two separate refs (not contiguous).
|
||||
s.draw("\U0010EEEE\u0305\u0305\U0010EEEE\u0305\u030E")
|
||||
s.cursor_back(4)
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 3)
|
||||
self.ae(refs[0]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 0.5, 'bottom': 0.5})
|
||||
self.ae(refs[1]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 0.25, 'bottom': 0.5})
|
||||
self.ae(refs[2]['src_rect'], {'left': 0.5, 'top': 0.0, 'right': 0.75, 'bottom': 0.5})
|
||||
# Erase the line.
|
||||
s.erase_in_line(2)
|
||||
# There must be 0 refs after the line is erased.
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 0)
|
||||
# Now test encoding IDs with the 24-bit color.
|
||||
# The first image, 1x1
|
||||
s.apply_sgr("38;2;0;0;42")
|
||||
s.draw("\U0010EEEE\u0305\u0305")
|
||||
# The second image, 2x1
|
||||
s.apply_sgr("38;2;42;43;44")
|
||||
s.draw("\U0010EEEE\u0305\u030D\U0010EEEE\u0305\u030E")
|
||||
s.cursor_back(2)
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 2)
|
||||
self.ae(refs[0]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 0.25, 'bottom': 0.5})
|
||||
# The second ref spans the whole widths of the second image because it's
|
||||
# fit to height and centered in a 4x2 box (specified in put_image).
|
||||
self.ae(refs[1]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 0.5})
|
||||
# Erase the line.
|
||||
s.erase_in_line(2)
|
||||
# Now test implicit column numbers.
|
||||
# We will mix implicit and explicit column/row specifications, but they
|
||||
# will be combine into just two references.
|
||||
s.apply_sgr("38;5;42")
|
||||
# full row 0 of the first image
|
||||
s.draw("\U0010EEEE\u0305\u0305\U0010EEEE\u0305\U0010EEEE\U0010EEEE\u0305")
|
||||
# full row 1 of the first image
|
||||
s.draw("\U0010EEEE\u030D\U0010EEEE\U0010EEEE\U0010EEEE\u030D\u0310")
|
||||
s.cursor_back(8)
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 2)
|
||||
self.ae(refs[0]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 0.5})
|
||||
self.ae(refs[1]['src_rect'], {'left': 0.0, 'top': 0.5, 'right': 1.0, 'bottom': 1.0})
|
||||
|
||||
def test_unicode_placeholders_3rd_combining_char(self):
|
||||
# This test tests that we can use the 3rd diacritic for the most
|
||||
# significant byte
|
||||
cw, ch = 10, 20
|
||||
s, dx, dy, put_image, put_ref, layers, rect_eq = put_helpers(self, cw, ch)
|
||||
# Upload two images.
|
||||
put_image(s, 20, 20, num_cols=4, num_lines=2, unicode_placeholder=1, id=42)
|
||||
put_image(s, 20, 10, num_cols=4, num_lines=1, unicode_placeholder=1, id=(42 << 24) + 43)
|
||||
# This one will have id=43, which does not exist.
|
||||
s.apply_sgr("38;2;0;0;43")
|
||||
s.draw("\U0010EEEE\u0305\U0010EEEE\U0010EEEE\U0010EEEE")
|
||||
s.cursor_back(4)
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 0)
|
||||
s.erase_in_line(2)
|
||||
# This one will have id=42. We explicitly specify that the most
|
||||
# significant byte is 0 (third \u305). Specifying the zero byte like
|
||||
# this is not necessary but is correct.
|
||||
s.apply_sgr("38;2;0;0;42")
|
||||
s.draw("\U0010EEEE\u0305\u0305\u0305\U0010EEEE\u0305\u030D\u0305")
|
||||
# This is the second image.
|
||||
# \u059C -> 42
|
||||
s.apply_sgr("38;2;0;0;43")
|
||||
s.draw("\U0010EEEE\u0305\u0305\u059C\U0010EEEE\u0305\u030D\u059C")
|
||||
# Check that we can continue by using implicit row/column specification.
|
||||
s.draw("\U0010EEEE\u0305\U0010EEEE")
|
||||
s.cursor_back(6)
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 2)
|
||||
self.ae(refs[0]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 0.5, 'bottom': 0.5})
|
||||
self.ae(refs[1]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 1.0})
|
||||
s.erase_in_line(2)
|
||||
# Now test the 8-bit color mode. Using the third diacritic, we can
|
||||
# specify 16 bits: the most significant byte and the least significant
|
||||
# byte.
|
||||
s.apply_sgr("38;5;42")
|
||||
s.draw("\U0010EEEE\u0305\u0305\u0305\U0010EEEE")
|
||||
s.apply_sgr("38;5;43")
|
||||
s.draw("\U0010EEEE\u0305\u0305\u059C\U0010EEEE\U0010EEEE\u0305\U0010EEEE")
|
||||
s.cursor_back(6)
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 2)
|
||||
self.ae(refs[0]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 0.5, 'bottom': 0.5})
|
||||
self.ae(refs[1]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 1.0})
|
||||
|
||||
def test_unicode_placeholders_multiple_placements(self):
|
||||
# Here we test placement specification via underline color.
|
||||
cw, ch = 10, 20
|
||||
s, dx, dy, put_image, put_ref, layers, rect_eq = put_helpers(self, cw, ch)
|
||||
put_image(s, 20, 20, num_cols=1, num_lines=1, placement_id=1, unicode_placeholder=1, id=42)
|
||||
put_ref(s, id=42, num_cols=2, num_lines=1, placement_id=22, unicode_placeholder=1)
|
||||
put_ref(s, id=42, num_cols=4, num_lines=2, placement_id=44, unicode_placeholder=1)
|
||||
# The references are virtual, so no visible refs yet.
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 0)
|
||||
# Draw the first row of each placement.
|
||||
s.apply_sgr("38;5;42")
|
||||
s.apply_sgr("58;5;1")
|
||||
s.draw("\U0010EEEE\u0305")
|
||||
s.apply_sgr("58;5;22")
|
||||
s.draw("\U0010EEEE\u0305\U0010EEEE\u0305")
|
||||
s.apply_sgr("58;5;44")
|
||||
s.draw("\U0010EEEE\u0305\U0010EEEE\u0305\U0010EEEE\u0305\U0010EEEE\u0305")
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
self.ae(len(refs), 3)
|
||||
self.ae(refs[0]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 1.5})
|
||||
self.ae(refs[1]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 1.0})
|
||||
self.ae(refs[2]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 0.5})
|
||||
|
||||
def test_unicode_placeholders_scroll(self):
|
||||
# Here we test scrolling of a region. We'll draw an image spanning 8
|
||||
# rows and then scroll only the middle part of this image. Each
|
||||
# reference corresponds to one row.
|
||||
cw, ch = 5, 10
|
||||
s, dx, dy, put_image, put_ref, layers, rect_eq = put_helpers(self, cw, ch, lines=8)
|
||||
put_image(s, 5, 80, num_cols=1, num_lines=8, unicode_placeholder=1, id=42)
|
||||
s.apply_sgr("38;5;42")
|
||||
s.cursor_position(1, 0)
|
||||
s.draw("\U0010EEEE\u0305\n")
|
||||
s.cursor_position(2, 0)
|
||||
s.draw("\U0010EEEE\u030D\n")
|
||||
s.cursor_position(3, 0)
|
||||
s.draw("\U0010EEEE\u030E\n")
|
||||
s.cursor_position(4, 0)
|
||||
s.draw("\U0010EEEE\u0310\n")
|
||||
s.cursor_position(5, 0)
|
||||
s.draw("\U0010EEEE\u0312\n")
|
||||
s.cursor_position(6, 0)
|
||||
s.draw("\U0010EEEE\u033D\n")
|
||||
s.cursor_position(7, 0)
|
||||
s.draw("\U0010EEEE\u033E\n")
|
||||
s.cursor_position(8, 0)
|
||||
s.draw("\U0010EEEE\u033F")
|
||||
# Each line will contain a part of the image.
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
refs = sorted(refs, key=lambda r: r['src_rect']['top'])
|
||||
self.ae(len(refs), 8)
|
||||
for i in range(8):
|
||||
self.ae(refs[i]['src_rect'], {'left': 0.0, 'top': 0.125*i, 'right': 1.0, 'bottom': 0.125*(i + 1)})
|
||||
self.ae(refs[i]['dest_rect']['top'], 1 - 0.25*i)
|
||||
# Now set margins to lines 3 and 6.
|
||||
s.set_margins(3, 6) # 1-based indexing
|
||||
# Scroll two lines down (i.e. move lines 3..6 up).
|
||||
# Lines 3 and 4 will be erased.
|
||||
s.cursor_position(6, 0)
|
||||
s.index()
|
||||
s.index()
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
refs = sorted(refs, key=lambda r: r['src_rect']['top'])
|
||||
self.ae(len(refs), 6)
|
||||
# Lines 1 and 2 are outside of the region, not scrolled.
|
||||
self.ae(refs[0]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 0.125})
|
||||
self.ae(refs[0]['dest_rect']['top'], 1.0)
|
||||
self.ae(refs[1]['src_rect'], {'left': 0.0, 'top': 0.125*1, 'right': 1.0, 'bottom': 0.125*2})
|
||||
self.ae(refs[1]['dest_rect']['top'], 1.0 - 0.25*1)
|
||||
# Lines 3 and 4 are erased.
|
||||
# Lines 5 and 6 are now higher.
|
||||
self.ae(refs[2]['src_rect'], {'left': 0.0, 'top': 0.125*4, 'right': 1.0, 'bottom': 0.125*5})
|
||||
self.ae(refs[2]['dest_rect']['top'], 1.0 - 0.25*2)
|
||||
self.ae(refs[3]['src_rect'], {'left': 0.0, 'top': 0.125*5, 'right': 1.0, 'bottom': 0.125*6})
|
||||
self.ae(refs[3]['dest_rect']['top'], 1.0 - 0.25*3)
|
||||
# Lines 7 and 8 are outside of the region.
|
||||
self.ae(refs[4]['src_rect'], {'left': 0.0, 'top': 0.125*6, 'right': 1.0, 'bottom': 0.125*7})
|
||||
self.ae(refs[4]['dest_rect']['top'], 1.0 - 0.25*6)
|
||||
self.ae(refs[5]['src_rect'], {'left': 0.0, 'top': 0.125*7, 'right': 1.0, 'bottom': 0.125*8})
|
||||
self.ae(refs[5]['dest_rect']['top'], 1.0 - 0.25*7)
|
||||
# Now scroll three lines up (i.e. move lines 5..6 down).
|
||||
# Line 6 will be erased.
|
||||
s.cursor_position(3, 0)
|
||||
s.reverse_index()
|
||||
s.reverse_index()
|
||||
s.reverse_index()
|
||||
s.update_only_line_graphics_data()
|
||||
refs = layers(s)
|
||||
refs = sorted(refs, key=lambda r: r['src_rect']['top'])
|
||||
self.ae(len(refs), 5)
|
||||
# Lines 1 and 2 are outside of the region, not scrolled.
|
||||
self.ae(refs[0]['src_rect'], {'left': 0.0, 'top': 0.0, 'right': 1.0, 'bottom': 0.125})
|
||||
self.ae(refs[0]['dest_rect']['top'], 1.0)
|
||||
self.ae(refs[1]['src_rect'], {'left': 0.0, 'top': 0.125*1, 'right': 1.0, 'bottom': 0.125*2})
|
||||
self.ae(refs[1]['dest_rect']['top'], 1.0 - 0.25*1)
|
||||
# Lines 3, 4 and 6 are erased.
|
||||
# Line 5 is now lower.
|
||||
self.ae(refs[2]['src_rect'], {'left': 0.0, 'top': 0.125*4, 'right': 1.0, 'bottom': 0.125*5})
|
||||
self.ae(refs[2]['dest_rect']['top'], 1.0 - 0.25*5)
|
||||
# Lines 7 and 8 are outside of the region.
|
||||
self.ae(refs[3]['src_rect'], {'left': 0.0, 'top': 0.125*6, 'right': 1.0, 'bottom': 0.125*7})
|
||||
self.ae(refs[3]['dest_rect']['top'], 1.0 - 0.25*6)
|
||||
self.ae(refs[4]['src_rect'], {'left': 0.0, 'top': 0.125*7, 'right': 1.0, 'bottom': 0.125*8})
|
||||
self.ae(refs[4]['dest_rect']['top'], 1.0 - 0.25*7)
|
||||
|
||||
def test_gr_scroll(self):
|
||||
cw, ch = 10, 20
|
||||
s, dx, dy, put_image, put_ref, layers, rect_eq = put_helpers(self, cw, ch)
|
||||
|
||||
@@ -410,7 +410,7 @@ class TestParser(BaseTest):
|
||||
for f in 'action delete_action transmission_type compressed'.split():
|
||||
k.setdefault(f, b'\0')
|
||||
for f in ('format more id data_sz data_offset width height x_offset y_offset data_height data_width cursor_movement'
|
||||
' num_cells num_lines cell_x_offset cell_y_offset z_index placement_id image_number quiet').split():
|
||||
' num_cells num_lines cell_x_offset cell_y_offset z_index placement_id image_number quiet unicode_placement').split():
|
||||
k.setdefault(f, 0)
|
||||
p = k.pop('payload', '').encode('utf-8')
|
||||
k['payload_sz'] = len(p)
|
||||
|
||||
Reference in New Issue
Block a user