def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult: if not self._lines: self.render(console, options) style = console.get_style(self.style) width = self._render_width or console.width height = options.height or console.height x, y = self.offset window_lines = self._lines[y:y + height] if x: def width_view(line: list[Segment]) -> list[Segment]: _, line = Segment.divide(line, [x, x + width]) return line window_lines = [width_view(line) for line in window_lines] missing_lines = len(window_lines) - height if missing_lines: blank_line = [Segment(" " * width, style), Segment.line()] window_lines.extend(blank_line for _ in range(missing_lines)) new_line = Segment.line() for line in window_lines: yield from line yield new_line
def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: width = options.max_width height = options.height or console.height style = console.get_style(self.style) blank_segment = Segment(" " * width, style) lines = SegmentLines([[blank_segment]] * height, new_lines=True) yield lines
def render(self, console: Console, options: ConsoleOptions) -> None: width = self.width or options.max_width or console.width options = options.update_dimensions(width, None) style = console.get_style(self.style) renderable = self.renderable if self.padding: renderable = Padding(renderable, self.padding) self._lines[:] = console.render_lines(renderable, options, style=style) self.size = Size(width, len(self._lines)) self.page.emit_no_wait(PageUpdate(self.page))
def render_bullet(self, console: Console, options: ConsoleOptions) -> RenderResult: render_options = options.update(width=options.max_width - 3) lines = console.render_lines(self.elements, render_options, style=self.style) bullet_style = console.get_style("markdown.item.bullet", default="none") bullet = Segment(" • ", bullet_style) padding = Segment(" " * 3, bullet_style) new_line = Segment("\n") for first, line in loop_first(lines): yield bullet if first else padding yield from line yield new_line
def render_number( self, console: Console, options: ConsoleOptions, number: int, last_number: int ) -> RenderResult: number_width = len(str(last_number)) + 2 render_options = options.update(width=options.max_width - number_width) lines = console.render_lines(self.elements, render_options, style=self.style) number_style = console.get_style("markdown.item.number", default="none") new_line = Segment("\n") padding = Segment(" " * number_width, number_style) numeral = Segment(f"{number}".rjust(number_width - 1) + " ", number_style) for first, line in loop_first(lines): yield numeral if first else padding yield from line yield new_line
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult: size = ((options.height or console.height) if self.vertical else (options.max_width or console.width)) thickness = ((options.max_width or console.width) if self.vertical else (options.height or console.height)) _style = console.get_style(self.style) bar = self.render_bar( size=size, window_size=self.window_size, virtual_size=self.virtual_size, position=self.position, vertical=self.vertical, thickness=thickness, back_color=_style.bgcolor or Color.parse("#555555"), bar_color=_style.color or Color.parse("bright_magenta"), ) yield bar
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult: """Render markdown to the console.""" style = console.get_style(self.style, default="none") context = MarkdownContext( console, options, style, inline_code_lexer=self.inline_code_lexer, inline_code_theme=self.inline_code_theme, ) nodes = self.parsed.walker() inlines = self.inlines new_line = False for current, entering in nodes: node_type = current.t if node_type in ("html_inline", "html_block", "text"): context.on_text(current.literal.replace("\n", " "), node_type) elif node_type == "linebreak": if entering: context.on_text("\n", node_type) elif node_type == "softbreak": if entering: context.on_text(" ", node_type) elif node_type == "link": if entering: link_style = console.get_style("markdown.link", default="none") if self.hyperlinks: link_style += Style(link=current.destination) context.enter_style(link_style) else: context.leave_style() if not self.hyperlinks: context.on_text(" (", node_type) style = Style(underline=True) + console.get_style( "markdown.link_url", default="none") context.enter_style(style) context.on_text(current.destination, node_type) context.leave_style() context.on_text(")", node_type) elif node_type in inlines: if current.is_container(): if entering: context.enter_style(f"markdown.{node_type}") else: context.leave_style() else: context.enter_style(f"markdown.{node_type}") if current.literal: context.on_text(current.literal, node_type) context.leave_style() else: element_class = self.elements.get(node_type) or UnknownElement if current.is_container(): if entering: element = element_class.create(self, current) context.stack.push(element) element.on_enter(context) else: element = context.stack.pop() if context.stack: if context.stack.top.on_child_close( context, element): if new_line: yield Segment("\n") yield from console.render( element, context.options) element.on_leave(context) else: element.on_leave(context) else: element.on_leave(context) yield from console.render(element, context.options) new_line = element.new_line else: element = element_class.create(self, current) context.stack.push(element) element.on_enter(context) if current.literal: element.on_text(context, current.literal.rstrip()) context.stack.pop() if context.stack.top.on_child_close(context, element): if new_line: yield Segment("\n") yield from console.render(element, context.options) element.on_leave(context) else: element.on_leave(context) new_line = element.new_line
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult: style = console.get_style("markdown.hr", default="none") yield Rule(style=style)
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult: yield Segment(self._char, console.get_style(self.style))
def test_get_style_error(): console = Console() with pytest.raises(errors.MissingStyle): console.get_style("nosuchstyle") with pytest.raises(errors.MissingStyle): console.get_style("foo bar")
def test_get_style_default(): console = Console() console.get_style("foobar", default="red") == Style(color="red")
def test_get_style(): console = Console() console.get_style("repr.brace") == Style(bold=True)
def render( self, console: Console, *, crop: Region = None, ) -> SegmentLines: """Render a layout. Args: console (Console): Console instance. clip (Optional[Region]): Region to clip to. Returns: SegmentLines: A renderable """ width = self.width height = self.height screen = Region(0, 0, width, height) crop_region = crop.intersection(screen) if crop else screen _Segment = Segment divide = _Segment.divide # Maps each cut on to a list of segments cuts = self.cuts chops: list[dict[int, list[Segment] | None]] = [{cut: None for cut in cut_set} for cut_set in cuts] # TODO: Provide an option to update the background background_style = console.get_style(self.background) background_render = [[_Segment(" " * width, background_style)] for _ in range(height)] # Go through all the renders in reverse order and fill buckets with no render renders = list(self._get_renders(console)) for region, clip, lines in chain( renders, [(screen, screen, background_render)]): render_region = region.intersection(clip) for y, line in zip(render_region.y_range, lines): first_cut, last_cut = render_region.x_extents final_cuts = [ cut for cut in cuts[y] if (last_cut >= cut >= first_cut) ] if len(final_cuts) == 2: cut_segments = [line] else: render_x = render_region.x relative_cuts = [cut - render_x for cut in final_cuts] _, *cut_segments = divide(line, relative_cuts) for cut, segments in zip(final_cuts, cut_segments): if chops[y][cut] is None: chops[y][cut] = segments # Assemble the cut renders in to lists of segments crop_x, crop_y, crop_x2, crop_y2 = crop_region.corners output_lines = self._assemble_chops(chops[crop_y:crop_y2]) def width_view(line: list[Segment]) -> list[Segment]: if line: div_lines = list(divide(line, [crop_x, crop_x2])) line = div_lines[1] if len(div_lines) > 1 else div_lines[0] return line if crop is not None and (crop_x, crop_x2) != (0, self.width): render_lines = [width_view(line) for line in output_lines] else: render_lines = list(output_lines) return SegmentLines(render_lines, new_lines=True)