def test_transformers_container_bake_method_for_source_consuming_transformers( ): sh = TM.shape((5, 5)) sh.draw.set((2, 2)) reference_shape = TM.shape((5, 5)) # Emulates Dilate filter - for point in [(2, 2), (2, 1), (1, 2), (3, 2), (2, 3)]: reference_shape.draw.set(point) TM.TransformersContainer([TM.transformers.library.Dilate]).bake(sh) joiner = lambda sh: [sh[pos].value for pos in TM.Rect(sh.size)] assert joiner(sh) == joiner(reference_shape)
def test_transformers_container_bake_method_for_source_consuming_transformers(): sh = TM.shape((5,5)) sh.draw.set((2,2)) reference_shape = TM.shape((5,5)) # Emulates Dilate filter - for point in [(2,2), (2, 1), (1, 2), (3, 2), (2, 3)]: reference_shape.draw.set(point) TM.TransformersContainer([TM.transformers.library.Dilate]).bake(sh) #FIXME: compares the internal characters relying on the internal # representation of shape data: joiner = lambda d: '\n'.join(''.join(char for char in d[i: i + 5]) for i in range(0, 5 * 5, 5)) assert joiner(sh.value_data) == joiner(reference_shape.value_data)
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 main(): values = [] total = int(sys.argv[1]) if len(sys.argv) > 1 else 512 include_empties = len(sys.argv) > 3 for i in range(total): new = shape((3, 3)) if i & 1: new[1, 1] = "#" elif not include_empties: continue if i & 0b10: new[1, 0] = "#" if i & 0b100: new[0, 1] = "#" if i & 0b1000: new[2, 1] = "#" if i & 0b10000: new[1, 2] = "#" if i & 0b100000: new[0, 0] = "#" if i & 0b1000000: new[2, 0] = "#" if i & 0b10000000: new[0, 2] = "#" if i & 0b100000000: new[2, 2] = "#" values.append( value_template.format( *["".join(new.value_data[i:i + 3]) for i in range(0, 9, 3)])) return template.format(",\n".join(values))
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_transformer_dependency_injection_pixel_parameter(): sh = TM.shape((1,1)) sh[0,0] = "a" sh.context.transformers.append(TM.Transformer(effects=lambda pixel: TM.Effects.underline if pixel.value.isupper() else TM.Effects.none)) assert sh[0,0].effects == TM.Effects.none sh[0,0] = "A" assert sh[0,0].effects == TM.Effects.underline
def test_markmap_indepent_in_different_resolutions(): sh = TM.shape((10, 10)) assert sh.text[1].marks is not sh.text[4].marks assert sh.text[1].marks is sh.text[1].marks # Line-break marks inserted with text_plane[1] creation assert len(sh.text[1].marks) == 10 assert len(sh.text[1].marks.relative_data) == 10
def test_markmap_prepare_copies_data_instance(): sh = TM.shape((10, 10)) m = TM.Mark() original = mm = sh.text[1].marks mm = mm.prepare("") assert original is not mm assert original.data is not mm.data
def _sprite_from_text_size(self, text_size, text_plane, pos, padding=(0,0)): text_size = V2(text_size) text_plane = plane_names[text_plane] size = text_size * (ceil(1/relative_char_size[text_plane][0]), ceil(1/relative_char_size[text_plane][1])) shape = terminedia.shape(size + padding) sprite =Sprite(shape) sprite.pos = pos return sprite
def test_transformer_effects_channel_works(): sh = TM.shape((1,1)) sh.context.effects = TM.Effects.underline sh[0,0] = "*" assert sh[0,0].effects == TM.Effects.underline sh.context.transformers.append(TM.Transformer(effects=lambda value: value | TM.Effects.blink)) assert sh[0,0].value == "*" assert sh[0,0].effects == TM.Effects.blink | TM.Effects.underline
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_transformers_stacked_are_run_in_order(): sh = TM.shape((1,1)) sh.context.color = "red" sh.context.background = "green" sh.context.effects = TM.Effects.underline sh[0,0] = "*" sh.context.transformers.append(TM.Transformer(char=lambda value: ".")) sh.context.transformers.append(TM.Transformer(char=lambda value: "-" if value == "." else value)) assert sh[0,0].value == "-"
def test_transformers_stack_accepts_insertions(): sh = TM.shape((1,1)) sh.context.color = "red" sh.context.background = "green" sh.context.effects = TM.Effects.underline sh[0,0] = "*" sh.context.transformers.append(TM.Transformer(char=lambda value: "-" if value == "." else "#")) assert sh[0,0].value == "#" sh.context.transformers.insert(0, TM.Transformer(char=lambda value: ".")) assert sh[0,0].value == "-"
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_markmap_mark_retrieved_at_all_possible_positions( input_index, expected_at): sh = TM.shape((10, 10)) m = TM.Mark() mm = sh.text[1].marks mm.relative_data.clear() mm[input_index] = m for index in expected_at: assert mm[index] is m
def main(image_paths, size=None, output="", backend="", resolution=""): """Displays an image, given in a path, on the terminal. """ # TODO add more options to control the output, # including disabling auto-scaling. if not image_paths: image_paths = (default_image, ) context = scr = Screen(backend=backend) if not size: size = size_in_pixels(scr.size, resolution=resolution) else: size = V2(int(comp) for comp in size.lower().split("x")) if output: output_file = open(output, "wt", encoding="utf-8") context = DummyCtx() with context: for img_path in image_paths: if not resolution: img = shape(img_path, size=size) elif resolution == "square": img = shape(img_path, size=size, promote=True, resolution=resolution) else: # For finer than half-block, threshold image prior to rendering preliminar_img = shape(img_path, size=size, promote=True) img = shape(size_in_blocks(size, resolution)) preliminar_img.context.transformers.append( ThresholdTransformer(invert=False)) getattr(img, resolution).draw.blit((0, 0), preliminar_img) if output: img.render(output=output_file, backend=backend) output_file.write("\n") else: scr.clear() with scr.commands: scr.draw.blit((0, 0), img) pause()
def main(image_paths): """Displays an image, given in a path, on the terminal. """ # TODO add more options to control the output, # including disabling auto-scaling. if not image_paths: image_paths = (default_image, ) with Screen() as scr: for img_path in image_paths: img = shape(img_path) with scr.commands: scr.draw.blit((0, 0), img) pause()
def test_markmap_mark_deleted_at_all_possible_positions(input_index, marks_at): sh = TM.shape((10, 10)) mm = sh.text[1].marks mm.relative_data.clear() m = TM.Mark() for index in marks_at: mm[index] = m assert mm[input_index] is m del mm[input_index] assert mm.get(input_index) is None with pytest.raises(KeyError): del mm[input_index]
def test_markmap_works_with_negative_index(): sh = TM.shape((10, 10)) m = TM.Mark() mm = sh.text[1].marks mm.relative_data.clear() mm[-1, 0] = m assert mm[-1, 0] is m assert not mm.data assert len(mm.relative_data) == 1 assert isinstance(first(mm.relative_data.keys())[0], RelativeMarkIndex) assert isinstance(first(mm.relative_data.keys())[1], int)
def test_markmap_several_marks_at_same_position_retrieved_as_list(): sh = TM.shape((10, 10)) m = TM.Mark() mm = sh.text[1].marks mm.relative_data.clear() mm[9, 0] = m mm[-1, 0] = m assert mm[9, 0] == [m, m] mm[-1, -10] = m assert mm[9, 0] == [m, m, m]
def test_markmap_mark_retrieved_as_absolute_mark_when_rendering(): sh = TM.shape((10, 10)) m = TM.Mark() mm = sh.text[1].marks mm.relative_data.clear() mm[-1, 0] = m prepared = mm.prepare("") assert prepared.is_rendering_copy assert len(mm.data) == 0 and len(prepared.data) == 1 assert prepared.data[9, 0] is m mm[-1, -10] = m prepared = mm.prepare("") assert prepared.data[9, 0] == [m, m]
def setup(sc): global tr class Tr(TM.Transformer): current_color = TM.Color("yellow") def foreground(self): return self.current_color tr = Tr() shape = TM.shape((60, 20)) sc.sprites.add(shape) sc.sprites[0].transformers.append(tr) shape.draw.fill(color="red")
def _set_mapping(self, mapping): self.active_mapping = mapping if id(mapping) in self._shape_cache: self.sh, self.active_keys, self.toggle_key = self._shape_cache[id( mapping)] return rows = ceil(len(mapping) // self.columns) + 1 sh = terminedia.shape((self.width, rows + 2)) sh.text[1].add_border(transform=terminedia.borders["DOUBLE"]) col_width = (sh.size.x - 2) // self.columns current_row = 0 if self.custom_context: sh.context = self.custom_context else: sh.context.foreground = terminedia.DEFAULT_FG current_col = 0 actual_width = min(col_width, self.max_col_width) commands = [definition[0] for definition in mapping.values()] if self.bread_crumbs and "back" not in commands: mapping["<ESC>"] = ("back", "back") for shortcut, (callback, text) in mapping.items(): sh.text[1][ current_col * col_width + 1, current_row] = f"[effects: bold|underline]{shortcut}[/effects]{text:>{actual_width - len(shortcut) - 3}s}" current_row += 1 if current_row >= rows: current_col += 1 current_row = 0 self.active_keys = {} for shortcut, definition in mapping.items(): command = definition[0] # support for control-characters as shortcut: if len(shortcut) == 2 and shortcut[0] == "^": shortcut = chr(ord(shortcut[1].upper()) - ord("@")) elif shortcut[0] == "<" and shortcut[-1] == ">" and hasattr( KeyCodes, shortcut[1:-1]): shortcut = getattr(KeyCodes, shortcut[1:-1]) self.active_keys[shortcut] = command if command == "toggle": self.toggle_key = shortcut self._shape_cache[id(mapping)] = sh, self.active_keys, self.toggle_key self.sh = sh
def main(image_paths, output=""): """Displays an image, given in a path, on the terminal. """ # TODO add more options to control the output, # including disabling auto-scaling. if not image_paths: image_paths = (default_image, ) scr = Screen() if output: output_file = open(output, "wt", encoding="utf-8") else: scr.clear() for img_path in image_paths: img = shape(img_path, screen=scr) if output: img.render(output=output_file) output_file.write("\n") else: with scr.commands: scr.draw.blit((0, 0), img) pause()
def styled_text(): sc = TM.Screen((20, 10)) sh = TM.shape((20, 10)) sp1 = sc.data.sprites.add(sh) text_plane = sh.text[1] return sc, sh, text_plane
import terminedia as TM from terminedia.transformers import GradientTransformer sc = TM.Screen() a = TM.shape((40, 4)) a.text[4].at((0, 0), "terminedia") b = TM.Sprite(a) b.active = True sc.data.sprites.append(b) b.pos = (5, 5) a.context.transformers.append( GradientTransformer( TM.Gradient([(0, "blue"), (0.5, "white"), (1, "blue")]), TM.Directions.LEFT)) sc.update()
def main(shape, resolution=None, clear=False, cycle=False): """Quick example to navigate an string-defined shape through the terminal using the arrow keys! Press <ESC> to exit. Usage example: $ terminedia-shapes --custom=" \\n *** \\n * * \\n *** " """ # Work around apparent bug in click: if shape is None: shape = shape1 if "\\n" in shape: shape = shape.replace("\\n", "\n") original_shape = shape shape = TM.shape( original_shape, **({ "color_map": c_map } if original_shape == shape2 else {})) shape = TM.FullShape.promote(shape, resolution=resolution) last_frame = time.time() time_acumulator = 0 counter = 0 def cycle_color(foreground, tick): if foreground != TM.DEFAULT_FG: return foreground return TM.Color(["red", "blue", "yellow", "lime"][tick % 4]) try: with keyboard(), Screen(clear_screen=clear) as scr: # with Screen(clear_screen=True) as scr: x = scr.get_size()[0] // 2 - 6 y = 0 pos = V2(x, y) sprite = scr.data.sprites.add(shape, pos, active=True) if cycle: sprite.transformers.append( TM.Transformer(foreground=cycle_color)) while True: key = inkey() if key in (K.ESC, "q"): break if not clear and key in (K.RIGHT, K.LEFT, K.UP, K.DOWN): scr.data.draw.rect(sprite.rect, erase=True) sprite.pos += ( ((key == K.RIGHT) - (key == K.LEFT)), ((key == K.DOWN) - (key == K.UP)), ) scr.update() current = time.time() ellapsed = current - last_frame time_acumulator += ellapsed counter += 1 pause_time = max(FRAME_DELAY - ellapsed, 0) time.sleep(pause_time) last_frame = time.time() finally: print( f"\nTotal frames: {counter}\nAverage time per frame: {time_acumulator / (counter or 1):.04f}" )
def test_transformer_character_channel_works_with_static_transform(): sh = TM.shape((1, 1)) sh[0, 0] = "*" assert sh[0, 0].value == "*" sh.context.transformers.append(TM.Transformer(char=".")) assert sh[0, 0].value == "."
def screen_shape_sprite(): sc = TM.Screen((26, 10)) sh = TM.shape((26, 10)) sp1 = sc.data.sprites.add(sh) gr = TM.ColorGradient([(0, (0, 0, 0)), (1, (1, 1, 1))]) return sc, sh, sp1, gr
def test_markmap_works(): sh = TM.shape((10, 10)) m = TM.Mark() sh.text[1].marks[5, 5] = m assert sh.text[1].marks[5, 5] is m