diff --git a/.coveragerc b/.coveragerc index 6da34e7b..ff1a046c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,7 @@ [run] omit = rich/jupyter.py rich/_windows.py - rich/_timer + rich/_timer.py [report] exclude_lines = diff --git a/CHANGELOG.md b/CHANGELOG.md index 42f2aea8..adddac8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [9.9.1] - Unreleased +## [9.10.0] - Unreleased ### Changed - Some optimizations for Text +- Table Column header_style and footer_style are now added to Table header/footer style ## [9.9.0] - 2021-01-23 diff --git a/docs/source/console.rst b/docs/source/console.rst index d251abdb..92ddd9c4 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -101,13 +101,13 @@ Rich can display a status message with a 'spinner' animation that won't interfer To display a status message, call :meth:`~rich.console.Console.status` with the status message (which may be a string, Text, or other renderable). The result is a context manager which starts and stop the status display around a block of code. Here's an example:: - with console.status("Working...") + with console.status("Working..."): do_work() You can change the spinner animation via the ``spinner`` parameter:: with console.status("Monkeying around...", spinner="monkey"): - do_work + do_work() Run the following command to see the available choices for ``spinner``:: diff --git a/pyproject.toml b/pyproject.toml index 783cc9ca..90bc0ce0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "9.9.0" +version = "9.10.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/console.py b/rich/console.py index b8518253..72db2d6d 100644 --- a/rich/console.py +++ b/rich/console.py @@ -200,7 +200,7 @@ class Capture: class ThemeContext: - """A context manager to use a temporary theme. See :meth:`~rich.console.Console.theme` for usage.""" + """A context manager to use a temporary theme. See :meth:`~rich.console.Console.use_theme` for usage.""" def __init__(self, console: "Console", theme: Theme, inherit: bool = True) -> None: self.console = console @@ -397,7 +397,7 @@ class Console: force_jupyter (Optional[bool], optional): Enable/disable Jupyter rendering, or None to auto-detect Jupyter. Defaults to None. soft_wrap (Optional[bool], optional): Set soft wrap default on print method. Defaults to False. theme (Theme, optional): An optional style theme object, or ``None`` for default theme. - stderr (bool, optional): Use stderr rather than stdout if ``file `` is not specified. Defaults to False. + stderr (bool, optional): Use stderr rather than stdout if ``file`` is not specified. Defaults to False. file (IO, optional): A file object where the console should write to. Defaults to stdout. width (int, optional): The width of the terminal. Leave as default to auto-detect width. height (int, optional): The height of the terminal. Leave as default to auto-detect height. @@ -1135,7 +1135,7 @@ class Console: Args: sep (str, optional): String to write between print data. Defaults to " ". - end (str, optional): String to write at end of print data. Defaults to "\\n". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". style (Union[str, Style], optional): A style to apply to output. Defaults to None. highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to ``None``. @@ -1174,7 +1174,7 @@ class Console: Args: objects (positional args): Objects to log to the terminal. sep (str, optional): String to write between print data. Defaults to " ". - end (str, optional): String to write at end of print data. Defaults to "\\n". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". style (Union[str, Style], optional): A style to apply to output. Defaults to None. justify (str, optional): Justify method: "default", "left", "right", "center", or "full". Defaults to ``None``. overflow (str, optional): Overflow method: "ignore", "crop", "fold", or "ellipsis". Defaults to None. @@ -1287,7 +1287,7 @@ class Console: Args: objects (positional args): Objects to log to the terminal. sep (str, optional): String to write between print data. Defaults to " ". - end (str, optional): String to write at end of print data. Defaults to "\\n". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". style (Union[str, Style], optional): A style to apply to output. Defaults to None. justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``. overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None. diff --git a/rich/containers.py b/rich/containers.py index d6c82491..c42c8146 100644 --- a/rich/containers.py +++ b/rich/containers.py @@ -99,6 +99,9 @@ class Lines: def extend(self, lines: Iterable["Text"]) -> None: self._lines.extend(lines) + def pop(self, index=-1) -> "Text": + return self._lines.pop(index) + def justify( self, console: "Console", diff --git a/rich/default_styles.py b/rich/default_styles.py index ac0f5bad..6413f8ed 100644 --- a/rich/default_styles.py +++ b/rich/default_styles.py @@ -99,7 +99,7 @@ DEFAULT_STYLES: Dict[str, Style] = { "table.cell": Style.null(), "table.title": Style(italic=True), "table.caption": Style(italic=True, dim=True), - "traceback.error": Style(dim=True, color="red", bold=True), + "traceback.error": Style(color="red", italic=True), "traceback.border.syntax_error": Style(color="bright_red"), "traceback.border": Style(color="red"), "traceback.text": Style.null(), diff --git a/rich/rule.py b/rich/rule.py index dacbea21..d14394f2 100644 --- a/rich/rule.py +++ b/rich/rule.py @@ -15,7 +15,7 @@ class Rule(JupyterMixin): title (Union[str, Text], optional): Text to render in the rule. Defaults to "". characters (str, optional): Character(s) used to draw the line. Defaults to "─". style (StyleType, optional): Style of Rule. Defaults to "rule.line". - end (str, optional): Character at end of Rule. defaults to "\\n" + end (str, optional): Character at end of Rule. defaults to "\\\\n" align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center". """ diff --git a/rich/scope.py b/rich/scope.py index 53f30b03..4ab95252 100644 --- a/rich/scope.py +++ b/rich/scope.py @@ -8,7 +8,7 @@ from .table import Table from .text import Text, TextType if TYPE_CHECKING: - from .console import ConsoleRenderable, RenderableType + from .console import ConsoleRenderable def render_scope( @@ -32,7 +32,7 @@ def render_scope( max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to None. Returns: - RenderableType: A renderable object. + ConsoleRenderable: A renderable object. """ highlighter = ReprHighlighter() items_table = Table.grid(padding=(0, 1), expand=False) diff --git a/rich/segment.py b/rich/segment.py index ab22bb23..9a75aed7 100644 --- a/rich/segment.py +++ b/rich/segment.py @@ -246,7 +246,7 @@ class Segment(NamedTuple): """Get the length of list of segments. Args: - line (List[Segment]): A line encoded as a list of Segments (assumes no '\\n' characters), + line (List[Segment]): A line encoded as a list of Segments (assumes no '\\\\n' characters), Returns: int: The length of the line. @@ -258,7 +258,7 @@ class Segment(NamedTuple): """Get the shape (enclosing rectangle) of a list of lines. Args: - lines (List[List[Segment]]): A list of lines (no '\\n' characters). + lines (List[List[Segment]]): A list of lines (no '\\\\n' characters). Returns: Tuple[int, int]: Width and height in characters. diff --git a/rich/syntax.py b/rich/syntax.py index 25e9f287..2fddc9a5 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -406,9 +406,6 @@ class Syntax(JupyterMixin): line_no += 1 if line_no >= line_end: break - # Exhaust tokens - for token_type, token in tokens: - yield (token, None) text.append_tokens(tokens_to_spans()) diff --git a/rich/table.py b/rich/table.py index 1292ae31..ec565ca3 100644 --- a/rich/table.py +++ b/rich/table.py @@ -122,8 +122,8 @@ class Table(JupyterMixin): leading (bool, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0. style (Union[str, Style], optional): Default style for the table. Defaults to "none". row_styles (List[Union, str], optional): Optional list of row styles, if more that one style is give then the styles will alternate. Defaults to None. - header_style (Union[str, Style], optional): Style of the header. Defaults to None. - footer_style (Union[str, Style], optional): Style of the footer. Defaults to None. + header_style (Union[str, Style], optional): Style of the header. Defaults to "table.header". + footer_style (Union[str, Style], optional): Style of the footer. Defaults to "table.footer". border_style (Union[str, Style], optional): Style of the border. Defaults to None. title_style (Union[str, Style], optional): Style of the title. Defaults to None. caption_style (Union[str, Style], optional): Style of the caption. Defaults to None. @@ -183,8 +183,8 @@ class Table(JupyterMixin): self.leading = leading self.collapse_padding = collapse_padding self.style = style - self.header_style = header_style - self.footer_style = footer_style + self.header_style = header_style or "" + self.footer_style = footer_style or "" self.border_style = border_style self.title_style = title_style self.caption_style = caption_style diff --git a/rich/text.py b/rich/text.py index f748062c..8841be56 100644 --- a/rich/text.py +++ b/rich/text.py @@ -107,7 +107,7 @@ class Text(JupyterMixin): justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None. - end (str, optional): Character to end text with. Defaults to "\\n". + end (str, optional): Character to end text with. Defaults to "\\\\n". tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to 8. spans (List[Span], optional). A list of predefined style spans. Defaults to None. """ @@ -279,7 +279,7 @@ class Text(JupyterMixin): style (Union[str, Style], optional): Base style for text. Defaults to "". justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. - end (str, optional): Character to end text with. Defaults to "\\n". + end (str, optional): Character to end text with. Defaults to "\\\\n". tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to 8. Returns: @@ -865,7 +865,7 @@ class Text(JupyterMixin): """Split rich text in to lines, preserving styles. Args: - separator (str, optional): String to split on. Defaults to "\\n". + separator (str, optional): String to split on. Defaults to "\\\\n". include_separator (bool, optional): Include the separator in the lines. Defaults to False. allow_blank (bool, optional): Return a blank line if the text ends with a separator. Defaults to False. @@ -877,15 +877,25 @@ class Text(JupyterMixin): text = self.plain if separator not in text: return Lines([self.copy()]) + + if include_separator: + lines = self.divide( + match.end() for match in re.finditer(re.escape(separator), text) + ) + else: + + def flatten_spans() -> Iterable[int]: + for match in re.finditer(re.escape(separator), text): + start, end = match.span() + yield start + yield end + + lines = Lines( + line for line in self.divide(flatten_spans()) if line.plain != separator + ) + if not allow_blank and text.endswith(separator): - text = text[: -len(separator)] - offsets = [match.end() for match in re.finditer(re.escape(separator), text)] - lines = self.divide(offsets) - if not include_separator: - separator_length = len(separator) - for line in lines: - if line.plain.endswith(separator): - line.right_crop(separator_length) + lines.pop() return lines @@ -898,12 +908,13 @@ class Text(JupyterMixin): Returns: Lines: New RichText instances between offsets. """ - if not offsets: + _offsets = list(offsets) + if not _offsets: return Lines([self.copy()]) text = self.plain text_length = len(text) - divide_offsets = [0, *offsets, text_length] + divide_offsets = [0, *_offsets, text_length] line_ranges = list(zip(divide_offsets, divide_offsets[1:])) style = self.style diff --git a/rich/traceback.py b/rich/traceback.py index b53a7aff..c1bc9f8e 100644 --- a/rich/traceback.py +++ b/rich/traceback.py @@ -501,7 +501,7 @@ class Traceback: yield "" except Exception as error: yield Text.assemble( - (f"{error.__class__.__name__}: {error}", "traceback.error"), + (f"\n{error}", "traceback.error"), ) else: yield (