def test_render_error(): console = Console() with pytest.raises(errors.NotRenderableError): list(console.render([], console.options))
def test_render_broken_renderable(): console = Console() broken = BrokenRenderable() with pytest.raises(errors.NotRenderableError): list(console.render(broken, console.options))
def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: code_width = ( (options.max_width - self._numbers_column_width - 1) if self.code_width is None else self.code_width ) code = self.code if self.dedent: code = textwrap.dedent(code) text = self._highlight(self.lexer_name) if not self.line_numbers: if self.code_width is None: yield text else: yield from console.render( text, options=options.update(width=code_width) ) return lines = text.split("\n") line_offset = 0 if self.line_range: start_line, end_line = self.line_range line_offset = max(0, start_line - 1) lines = lines[line_offset:end_line] numbers_column_width = self._numbers_column_width render_options = options.update(width=code_width) ( background_style, number_style, highlight_number_style, ) = self._get_number_styles(console) highlight_line = self.highlight_lines.__contains__ _Segment = Segment padding = _Segment(" " * numbers_column_width + " ", background_style) new_line = _Segment("\n") line_pointer = "❱ " for line_no, line in enumerate(lines, self.start_line + line_offset): if self.word_wrap: wrapped_lines = console.render_lines( line, render_options, style=background_style ) else: segments = list(line.render(console, end="")) wrapped_lines = [ Segment.adjust_line_length( segments, render_options.max_width, style=background_style ) ] for first, wrapped_line in loop_first(wrapped_lines): if first: line_column = str(line_no).rjust(numbers_column_width - 2) + " " if highlight_line(line_no): yield _Segment(line_pointer, number_style) yield _Segment( line_column, highlight_number_style, ) else: yield _Segment(" ", highlight_number_style) yield _Segment( line_column, number_style, ) else: yield padding yield from wrapped_line yield new_line
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult: width = options.max_width height = options.height or 1 yield from console.render(self.renderable, options.update_dimensions(width, height))
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) 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", " ")) elif node_type == "linebreak": if entering: context.on_text("\n") elif node_type == "softbreak": if entering: context.on_text(" ") 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(" (") style = Style(underline=True) + console.get_style( "markdown.link_url", default="none" ) context.enter_style(style) context.on_text(current.destination) context.leave_style() context.on_text(")") 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) 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 new_line: yield Segment("\n") yield from console.render(element, context.options) element.on_leave(context) new_line = element.new_line
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult: transparent_background = self._get_base_style().transparent_background code_width = ((options.max_width - self._numbers_column_width - 1) if self.code_width is None else self.code_width) line_offset = 0 if self.line_range: start_line, end_line = self.line_range line_offset = max(0, start_line - 1) code = textwrap.dedent(self.code) if self.dedent else self.code code = code.expandtabs(self.tab_size) text = self.highlight(code, self.line_range) text.remove_suffix("\n") ( background_style, number_style, highlight_number_style, ) = self._get_number_styles(console) if not self.line_numbers: # Simple case of just rendering text yield from console.render(text, options=options.update(width=code_width)) return lines = text.split("\n") if self.line_range: lines = lines[line_offset:end_line] if self.indent_guides and not options.ascii_only: style = (self._get_base_style() + self._theme.get_style_for_token(Comment) + Style(dim=True)) lines = (Text("\n").join(lines).with_indent_guides( self.tab_size, style=style).split("\n")) numbers_column_width = self._numbers_column_width render_options = options.update(width=code_width) highlight_line = self.highlight_lines.__contains__ _Segment = Segment padding = _Segment(" " * numbers_column_width + " ", background_style) new_line = _Segment("\n") line_pointer = "> " if options.legacy_windows else "❱ " for line_no, line in enumerate(lines, self.start_line + line_offset): if self.word_wrap: wrapped_lines = console.render_lines( line, render_options, style=background_style, pad=not transparent_background, ) else: segments = list(line.render(console, end="")) if options.no_wrap: wrapped_lines = [segments] else: wrapped_lines = [ _Segment.adjust_line_length( segments, render_options.max_width, style=background_style, pad=not transparent_background, ) ] for first, wrapped_line in loop_first(wrapped_lines): if first: line_column = str(line_no).rjust(numbers_column_width - 2) + " " if highlight_line(line_no): yield _Segment(line_pointer, Style(color="red")) yield _Segment(line_column, highlight_number_style) else: yield _Segment(" ", highlight_number_style) yield _Segment(line_column, number_style) else: yield padding yield from wrapped_line yield new_line
def _get_syntax( self, console: Console, options: ConsoleOptions, ) -> Iterable[Segment]: """ Get the Segments for the Syntax object, excluding any vertical/horizontal padding """ transparent_background = self._get_base_style().transparent_background code_width = (((options.max_width - self._numbers_column_width - 1) if self.line_numbers else options.max_width) if self.code_width is None else self.code_width) ends_on_nl, processed_code = self._process_code(self.code) text = self.highlight(processed_code, self.line_range) if not self.line_numbers and not self.word_wrap and not self.line_range: if not ends_on_nl: text.remove_suffix("\n") # Simple case of just rendering text style = (self._get_base_style() + self._theme.get_style_for_token(Comment) + Style(dim=True) + self.background_style) if self.indent_guides and not options.ascii_only: text = text.with_indent_guides(self.tab_size, style=style) text.overflow = "crop" if style.transparent_background: yield from console.render( text, options=options.update(width=code_width)) else: syntax_lines = console.render_lines( text, options.update(width=code_width, height=None, justify="left"), style=self.background_style, pad=True, new_lines=True, ) for syntax_line in syntax_lines: yield from syntax_line return start_line, end_line = self.line_range or (None, None) line_offset = 0 if start_line: line_offset = max(0, start_line - 1) lines: Union[List[Text], Lines] = text.split("\n", allow_blank=ends_on_nl) if self.line_range: lines = lines[line_offset:end_line] if self.indent_guides and not options.ascii_only: style = (self._get_base_style() + self._theme.get_style_for_token(Comment) + Style(dim=True) + self.background_style) lines = (Text("\n").join(lines).with_indent_guides( self.tab_size, style=style).split("\n", allow_blank=True)) numbers_column_width = self._numbers_column_width render_options = options.update(width=code_width) highlight_line = self.highlight_lines.__contains__ _Segment = Segment new_line = _Segment("\n") line_pointer = "> " if options.legacy_windows else "❱ " ( background_style, number_style, highlight_number_style, ) = self._get_number_styles(console) for line_no, line in enumerate(lines, self.start_line + line_offset): if self.word_wrap: wrapped_lines = console.render_lines( line, render_options.update(height=None, justify="left"), style=background_style, pad=not transparent_background, ) else: segments = list(line.render(console, end="")) if options.no_wrap: wrapped_lines = [segments] else: wrapped_lines = [ _Segment.adjust_line_length( segments, render_options.max_width, style=background_style, pad=not transparent_background, ) ] if self.line_numbers: wrapped_line_left_pad = _Segment( " " * numbers_column_width + " ", background_style) for first, wrapped_line in loop_first(wrapped_lines): if first: line_column = str(line_no).rjust(numbers_column_width - 2) + " " if highlight_line(line_no): yield _Segment(line_pointer, Style(color="red")) yield _Segment(line_column, highlight_number_style) else: yield _Segment(" ", highlight_number_style) yield _Segment(line_column, number_style) else: yield wrapped_line_left_pad yield from wrapped_line yield new_line else: for wrapped_line in wrapped_lines: yield from wrapped_line yield new_line
from rich.text import Text from rich.console import Console code = """from rich.console import Console console = Console() text = Text.from_markup("Hello, [bold magenta]World[/]!") console.print(text)""" text = Text.from_markup("Hello, [bold magenta]World[/]!") console = Console() console.rule("rich.Segment") console.print( "A Segment is the last step in the Rich render process before generating text with ANSI codes." ) console.print("\nConsider the following code:\n") console.print(Syntax(code, "python", line_numbers=True)) console.print() console.print( "When you call [b]print()[/b], Rich [i]renders[/i] the object in to the the following:\n" ) fragments = list(console.render(text)) console.print(fragments) console.print() console.print("The Segments are then processed to produce the following output:\n") console.print(text) console.print( "\nYou will only need to know this if you are implementing your own Rich renderables." )