def test_styled_text_render_and_animate_special_marks(): sc, sh, text_plane = styled_text() msg = "Hello World!" # Special mark callable index uses dependency injection, like TM.Transformers. m = SpecialMark(index=lambda tick, length: tick % length, attributes={"color": TM.Color("red")}) m1 = SpecialMark(index=lambda tick, length: (tick + 1) % length, pop_attributes={"color": None}) text_plane.marks.special.update([m, m1]) text_plane[0, 5] = msg sc.update() yield None assert sc.data[0, 5].foreground == TM.Color("red") assert sc.data[1, 5].foreground == TM.values.DEFAULT_FG for i, char in enumerate(msg[:-1], 1): text_plane.update() sc.update() yield None assert sc.data[i - 1, 5].foreground == TM.values.DEFAULT_FG assert sc.data[i, 5].foreground == TM.Color("red") assert sc.data[i + 1, 5].foreground == TM.values.DEFAULT_FG assert sc.data[i + 2, 5].foreground == TM.values.DEFAULT_FG
def test_transformers_can_be_stacked(): sh = TM.shape((1, 1)) green = Color((0, 255, 0)) sh.context.color = "red" sh.context.background = green sh.context.effects = TM.Effects.underline sh[0, 0] = "*" res = tuple(sh[0, 0]) # in SVG land, from where we get the color names, 'green' is 0, 128, 0. green = Color((0, 255, 0)) assert res == ("*", Color("red"), green, TM.Effects.underline) sh.context.transformers.append(TM.Transformer(char=lambda value: ".")) res = tuple(sh[0, 0]) assert res == (".", Color("red"), green, TM.Effects.underline) sh.context.transformers.append( TM.Transformer(foreground=lambda value: TM.Color( (value.green, value.blue, value.red)))) res = tuple(sh[0, 0]) assert res == (".", Color("blue"), green, TM.Effects.underline) sh.context.transformers.append( TM.Transformer(background=lambda value: TM.Color( (value.green, value.blue, value.red)))) res = tuple(sh[0, 0]) assert res == (".", Color("blue"), Color("red"), TM.Effects.underline) sh.context.transformers.append( TM.Transformer(effects=lambda value: value | TM.Effects.blink)) res = tuple(sh[0, 0]) assert res == (".", Color("blue"), Color("red"), TM.Effects.underline | TM.Effects.blink)
def test_transform_pixel_channel_works(): sh = TM.shape((1,1)) def new_pixel(value): return "*", TM.Color("red"), TM.Color("blue"), TM.Effects.underline sh.context.transformers.append(TM.Transformer(pixel=new_pixel, background=TM.Color("green"))) assert tuple(sh[0,0]) == ("*", TM.Color("red"), TM.Color("green"), TM.Effects.underline)
def test_styled_text_on_replaying_skipped_cell_mark_should_place_it_first_than_inline_mark_on_next_char( ): sc, sh, text_plane = styled_text() sh.text[1].marks[5, 0] = TM.Mark(attributes={"foreground": "red"}) sh.text[1][4, 0] = "[effect: encircled]A[color: yellow]B[/color]C" sc.update() yield None assert sh[6, 0].foreground == TM.Color("yellow") assert sh[8, 0].foreground == TM.Color("red")
def test_mltokenizer_generates_mark_sequences_with_markups_at_same_place(): x = MLTokenizer("[color: blue][background: white]Hello World!") x.parse() assert x.parsed_text == "Hello World!" assert isinstance(x.mark_sequence[0], Sequence) assert len(x.mark_sequence[0]) == 2 assert x.mark_sequence[0][0].attributes == {"color": TM.Color("blue")} assert x.mark_sequence[0][1].attributes == { "background": TM.Color("white") }
def test_richtext_rendering_respects_existing_context(): sc, sh, text_plane = styled_text() msg = "H[color: yellow]ell[/color]o World!" sh.context.color = "red" text_plane[0, 0] = msg sc.update() yield None assert sc.data[0, 0].foreground == TM.Color("red") assert sc.data[1, 0].foreground == TM.Color("yellow") assert sc.data[4, 0].foreground == TM.Color("red")
def test_styled_sequence_retrives_marks_from_text_plane(): sc, sh, text_plane = styled_text() text_plane.marks[1, 0] = Mark(attributes={"color": TM.Color("yellow")}) msg = "Hello World!" aa = StyledSequence(msg, {}, text_plane) aa.render() sc.update() yield None assert sc.data[0, 0].foreground == TM.DEFAULT_FG for i, letter in enumerate(msg[1:], 1): assert sc.data[i, 0].foreground == TM.Color("yellow")
def test_styled_text_marks_can_be_built_with_keywords_and_strings(): x = TM.Mark(color="green", effects="Blink", direction="Left") assert x.attributes["foreground"] == TM.Color("green") assert x.attributes["effects"] == TM.Effects.blink assert x.attributes["direction"] == TM.Directions.LEFT x = TM.Mark(background="green", effects="Blink, bold") assert x.attributes["background"] == TM.Color("green") assert x.attributes["effects"] == TM.Effects.blink | TM.Effects.bold x = TM.Mark(effects="Blink | bold") assert x.attributes["effects"] == TM.Effects.blink | TM.Effects.bold x = TM.Mark(effects="Blink bold") assert x.attributes["effects"] == TM.Effects.blink | TM.Effects.bold
def test_styled_text_doesnot_skip_positional_mark_placed_at_continuation_of_double_character( direction): sc, sh, text_plane = styled_text() sh.text[1].marks[5, 0] = TM.Mark(attributes={"foreground": "red"}) if direction == "right": start = (4, 0) check_point = (6, 0) else: start = (6, 0) check_point = (3, 0) sh.text[1][start] = f"[direction: {direction}][effect: encircled]ABC" sc.update() yield None # the next assert is covered by other tests - but it ensures at once # that directions, effects, and double-width printing are working in a consistent way assert sh[check_point].value == "B" # TODO: nowadays, the constant "TM.values.CONTINUATION is retrieved at the adjacent # cell - this should be changed so that the value that is "continued" is retrieved, # and a "raw" way should be provided to find the "CONTINUATION" indication # (The backend rendering needs it) # - so, the assert works now, but is commented out, as this behavior is # subject to change: # assert sh[check_point + V2(1, 0)].value == TM.values.CONTINUATION # This assert is the object of the current test: assert sh[check_point].foreground == TM.Color("red")
def test_styled_text_push_context_attribute(): seq = StyledSequence("", {}) seq._enter_iteration() color = TM.Color("red") color2 = TM.Color("yellow") assert seq.context.color != color original = seq.context.color seq._context_push({"color": color}, {}, "sequence", 0) assert seq.context.color == color seq._context_push({"color": color2}, {}, "sequence", 0) assert seq.context.color == color2 seq._context_push({}, {"color": None}, "sequence", 0) assert seq.context.color == color seq._context_push({}, {"color": None}, "sequence", 0) assert seq.context.color == original
def draw(event): colors = "red green blue white yellow".split() tr.current_color = TM.Color(colors[event.tick // 5 % len(colors)]) sc.sprites[0].pos = 10, 10 if event.tick == 100: sh = sc.sprites[0].shape sh.clear() sh.text[4].at((0, 0), "terminedia")
class FocusTransformer(terminedia.Transformer): bg_color = terminedia.Color((.3, .3, .3)) def background(self, source, background, pos): if not (pos[0] in (0, source.size[0] - 1) or pos[1] in (0, source.size[1] - 1)): return background return self.bg_color
def test_square_fullcolor_set_half_pixel_to_different_color_preserves_other_half(): color = TM.Color("blue") color2 = TM.Color("red") sc = TM.Screen(size=(3, 3)) sc.data.context.color = color sc.data.square.set_at((0,0)) sc.data.context.color = color2 sc.data.square.set_at((0,1)) sc.update((0, 0)) yield None assert sc.data.square.get_at((0,0)) == color assert sc.data.square.get_at((0,1)) == color2 assert sc.data[0,0].background == color assert sc.data[0,0].foreground == color2 assert sc.data[0,0].value == TM.subpixels.HalfChars.LOWER_HALF_BLOCK
def test_transformer_background_channel_works(): sh = TM.shape((1,1)) sh.context.background = "red" sh[0,0] = "*" assert sh[0,0].background == Color("red") sh.context.transformers.append(TM.Transformer(background=lambda value: TM.Color((value.green, value.blue, value.red)))) assert sh[0,0].value == "*" assert sh[0,0].background == Color("blue")
def test_styled_text_marks_inline_end_markup_dont_turn_off_location_based_mark( ): sc, sh, text_plane = styled_text() sc.text[1].marks[3, 0] = TM.Mark(attributes={"color": "green"}) sc.text[1].marks[4, 0] = TM.Mark(pop_attributes={"color": None}) sc.text[1].marks[5, 0] = TM.Mark(attributes={"color": "green"}) sc.text[1].marks[7, 0] = TM.Mark(pop_attributes={"color": None}) sc.text[1][0, 0] = "[color: purple]012345[/color]6789" sc.update() yield None assert sc.data[0, 0].foreground == TM.Color("purple") assert sc.data[3, 0].foreground == TM.Color("green") assert sc.data[4, 0].foreground == TM.Color("purple") assert sc.data[6, 0].foreground == TM.Color("green") assert sc.data[7, 0].foreground == TM.values.DEFAULT_FG
def test_text_plane_clear(): sh = TM.shape((10, 10)) sh.text[1].marks[1, 0] = TM.Mark(attributes={"color": TM.Color("yellow")}) sh.text[1][0, 0] = "qazwsx" assert isinstance(sh.text[1].marks[10, 0], TM.Mark) assert sh.text[1].plane[1, 0] == "a" sh.text[1].clear() assert isinstance(sh.text[1].marks[10, 0], TM.Mark) assert sh.text[1].plane[1, 0] == " " assert sh.text[1].marks.get((1, 0), None) is None
def test_styled_text_transformers_spam_based_index_attribute_and_deactivation( ): sc, sh, text_plane = styled_text() sc.text.transformers_map["red"] = TM.Transformer( foreground=lambda: TM.Color("red")) sc.text.transformers_map["deg1"] = TM.Transformer( background=lambda sequence_index: TM.Color( (0, 25 * sequence_index, 255 - 25 * sequence_index))) sc.text[1][ 0, 0] = "[transformer: red 5]abc[transformer: deg1 10]defghijklmnopqrstyz" sc.update() yield None for i in range(0, 20): assert sc.data[i, 0].foreground == (TM.Color("red") if i < 5 else TM.values.DEFAULT_FG) if i < 3 or 13 <= i: assert sc.data[i, 0].background == TM.values.DEFAULT_BG else: assert sc.data[i, 0].background == TM.Color( (0, 25 * (i - 3), 255 - 25 * (i - 3)))
def test_square_fullcolor_set_half_pixel_to_other_color_than_default_preserves_other_half(): color = TM.Color("blue") sc = TM.Screen(size=(3, 3)) sc.data.square.set_at((0,0)) sc.data.context.color = color sc.data.square.set_at((0,1)) sc.update((0, 0)) yield None assert sc.data.square.get_at((0,0)) is TM.DEFAULT_FG assert sc.data.square.get_at((0,1)) == color assert sc.data[0,0].background == color assert sc.data[0,0].value == TM.subpixels.HalfChars.UPPER_HALF_BLOCK
def selector(): global sc, selector options = [ (TM.Color(option)) for option in "red green blue white yellow black #0ff #f0f".split() ] selector = W.Selector(sc, pos=(30, 10), options=options, callback=done, border=True, min_height=3, max_height=5, text_plane=1, min_width=10)
def test_styled_sequence_can_handle_pretransformers(): sc, sh, text_plane = styled_text() msg = "0123456789" tt = TM.Transformer( foreground=lambda pos: TM.Color((pos[0] * 25 % 256, 0, 0)), background=lambda pos: TM.Color((0, 0, (255 - pos[0] * 25) % 256)), ) aa = StyledSequence(msg, {0: TM.Mark(attributes={"pretransformer": tt})}, text_plane) aa.render() sc.update() yield None assert sc.data[0, 0].foreground == TM.Color((0, 0, 0)) assert sc.data[0, 0].background == TM.Color((0, 0, 255)) assert sc.data[9, 0].foreground == TM.Color((225, 0, 0)) assert sc.data[9, 0].background == TM.Color((0, 0, 30))
def test_styled_text_anotates_writtings(): sc, sh, text_plane = styled_text() msg = "Hello World!" # Special mark callable index uses dependency injection, like TM.Transformers. m = SpecialMark(index=lambda tick, length: tick % length, attributes={"color": TM.Color("red")}) m1 = SpecialMark(index=lambda tick, length: (tick + 1) % length, pop_attributes={"color": None}) # text_plane.marks.special.update(m, m1) mm = {"special": [m, m1]} aa = StyledSequence(msg, mark_sequence=mm, text_plane=text_plane, starting_point=(0, 5)) text_plane.render_styled_sequence(aa) # text_plane[0, 5] = msg assert text_plane.writtings assert next(iter(text_plane.writtings)) is aa
def test_styled_text_transformers_inline_end_markup_dont_turn_off_location_based_mark_when_both_are_defined_as_string( ): sc, sh, text_plane = styled_text() sc.text.transformers_map["red"] = TM.Transformer( foreground=lambda: TM.Color("red")) sc.text.transformers_map["blue"] = TM.Transformer( background=lambda: TM.Color("blue")) sc.text[1].marks[3, 0] = TM.Mark(attributes={"pretransformer": "blue"}) sc.text[1][0, 0] = "[transformer: red]012345[/transformer]6789" sc.update() yield None assert sc.data[0, 0].foreground == TM.Color("red") assert sc.data[3, 0].foreground == TM.Color("red") assert sc.data[3, 0].background == TM.Color("blue") assert sc.data[6, 0].foreground == TM.values.DEFAULT_FG assert sc.data[6, 0].background == TM.Color("blue")
def test_styled_text_transformers_inline_end_markup_turn_off_just_last_transformer( ): sc, sh, text_plane = styled_text() sc.text.transformers_map["red"] = TM.Transformer( foreground=lambda: TM.Color("red")) sc.text.transformers_map["blue"] = TM.Transformer( background=lambda: TM.Color("blue")) sc.text[1][ 0, 0] = "[transformer: red]012[transformer: blue]345[/transformer]67[/transformer]89" sc.update() yield None assert sc.data[0, 0].foreground == TM.Color("red") assert sc.data[3, 0].foreground == TM.Color("red") assert sc.data[3, 0].background == TM.Color("blue") assert sc.data[6, 0].foreground == TM.Color("red") assert sc.data[6, 0].background == TM.values.DEFAULT_BG assert sc.data[8, 0].foreground == TM.values.DEFAULT_FG assert sc.data[8, 0].background == TM.values.DEFAULT_BG
def cycle_color(foreground, tick): if foreground != TM.DEFAULT_FG: return foreground return TM.Color(["red", "blue", "yellow", "lime"][tick % 4])
def pixel(pixel): fg = TM.Color(pixel.foreground) char = "#*o. "[int((1 - fg.value) * 5)] fg.value = 1 return char, fg, pixel.background, pixel.effects
class Tr(TM.Transformer): current_color = TM.Color("yellow") def foreground(self): return self.current_color
def new_pixel(value): return "*", TM.Color("red"), TM.Color("blue"), TM.Effects.underline
@rendering_test def test_styled_sequence_is_rendered(): sc, sh, text_plane = styled_text() msg = "Hello World!" aa = StyledSequence(msg, {}, text_plane) aa.render() sc.update() yield None for i, char in enumerate(msg): assert sc.data[i, 0].value == char @pytest.mark.parametrize(("attrname", "value"), [ ( "color", TM.Color("red"), ), ( "background", TM.Color("green"), ), ("effects", TM.Effects.blink), ]) @pytest.mark.parametrize(*fast_render_mark) @rendering_test def test_styled_sequence_is_rendered_with_attribute(attrname, value): sc, sh, text_plane = styled_text() msg = "Hello World!" aa = StyledSequence(msg, {0: Mark(attributes={attrname: value})}, text_plane) aa.render()
def test_mltokenizer_generates_marks(): x = MLTokenizer("[color: blue]Hello World!") x.parse() assert x.parsed_text == "Hello World!" assert len(x.mark_sequence) == 1 assert x.mark_sequence[0].attributes == {"color": TM.Color("blue")}