mirror of https://github.com/Textualize/rich.git
tweak for windoze
This commit is contained in:
parent
cce43bd5fa
commit
33361e1d85
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -5,6 +5,17 @@ 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).
|
||||
|
||||
## [0.4.0] - Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- Added Traceback rendering and handler
|
||||
- Added rich.constrain
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed unnecessary padding
|
||||
|
||||
## [0.3.3] - 2020-02-04
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -830,7 +830,7 @@ class Console:
|
|||
if self.record:
|
||||
self._record_buffer.extend(buffer)
|
||||
del self.buffer[:]
|
||||
for line in Segment.split_and_crop_lines(buffer, self.width):
|
||||
for line in Segment.split_and_crop_lines(buffer, self.width, pad=False):
|
||||
for text, style in line:
|
||||
if style:
|
||||
append(style.render(text, color_system=color_system, reset=True))
|
||||
|
|
|
@ -41,14 +41,20 @@ class Segment(NamedTuple):
|
|||
|
||||
@classmethod
|
||||
def split_and_crop_lines(
|
||||
cls, segments: Iterable["Segment"], length: int, style: Style = None
|
||||
cls,
|
||||
segments: Iterable["Segment"],
|
||||
length: int,
|
||||
style: Style = None,
|
||||
pad: bool = True,
|
||||
) -> Iterable[List["Segment"]]:
|
||||
"""Split segments in to lines, and crop lines greater than a given length.
|
||||
|
||||
Args:
|
||||
segments (Iterable[Segment]): An iterable of segments, probably
|
||||
generated from console.render.
|
||||
length (Optional[int]): Desired line length.
|
||||
length (int): Desired line length.
|
||||
style (Style, optional): Style to use for any padding.
|
||||
pad (bool): Enable padding of lines that are less than `length`.
|
||||
|
||||
Returns:
|
||||
Iterable[List[Segment]]: An iterable of lines of segments.
|
||||
|
@ -64,31 +70,37 @@ class Segment(NamedTuple):
|
|||
if _text:
|
||||
append(cls(_text, style))
|
||||
if new_line:
|
||||
yield cls.adjust_line_length(lines[-1], length, style=style)
|
||||
yield cls.adjust_line_length(
|
||||
lines[-1], length, style=style, pad=pad
|
||||
)
|
||||
lines.append([])
|
||||
append = lines[-1].append
|
||||
else:
|
||||
append(segment)
|
||||
if lines[-1]:
|
||||
yield cls.adjust_line_length(lines[-1], length, style=style)
|
||||
yield cls.adjust_line_length(lines[-1], length, style=style, pad=pad)
|
||||
|
||||
@classmethod
|
||||
def adjust_line_length(
|
||||
cls, line: List["Segment"], length: int, style: Style = None
|
||||
cls, line: List["Segment"], length: int, style: Style = None, pad: bool = True
|
||||
) -> List["Segment"]:
|
||||
"""Adjust a line to a given width (cropping or padding as required.
|
||||
"""Adjust a line to a given width (cropping or padding as required).
|
||||
|
||||
Args:
|
||||
segments (Iterable[Segment]): A list of segments in a single line.
|
||||
length (int): The desired width of the line.
|
||||
style (Style, optional): The style of padding if used (space on the end). Defaults to None.
|
||||
pad (bool, optional): Pad lines with spaces if they are shorter than `length`. Defaults to True.
|
||||
|
||||
Returns:
|
||||
List[Segment]: A line of segments with the desired length.
|
||||
"""
|
||||
line_length = sum(len(text) for text, _style in line)
|
||||
if line_length < length:
|
||||
return line + [Segment(" " * (length - line_length), style)]
|
||||
if pad:
|
||||
return line + [cls(" " * (length - line_length), style)]
|
||||
else:
|
||||
return line[:]
|
||||
elif line_length > length:
|
||||
line_length = 0
|
||||
new_line: List[Segment] = []
|
||||
|
@ -100,7 +112,7 @@ class Segment(NamedTuple):
|
|||
line_length += segment_length
|
||||
else:
|
||||
text, style = segment
|
||||
append(Segment(text[: length - line_length], style))
|
||||
append(cls(text[: length - line_length], style))
|
||||
break
|
||||
return new_line
|
||||
return line[:]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import platform
|
||||
import textwrap
|
||||
from typing import Any, Dict, Optional, Set, Tuple, Union
|
||||
|
||||
|
@ -14,7 +15,8 @@ from .style import Style
|
|||
from .text import Text
|
||||
from ._tools import iter_first
|
||||
|
||||
DEFAULT_THEME = "monokai"
|
||||
WINDOWS = platform.system() == "Windows"
|
||||
DEFAULT_THEME = "dark"
|
||||
|
||||
|
||||
class Syntax:
|
||||
|
@ -166,6 +168,24 @@ class Syntax:
|
|||
return len(str(self.start_line + self.code.count("\n"))) + 2
|
||||
return 0
|
||||
|
||||
def _get_number_styles(self, console: Console) -> Tuple[Style, Style, Style]:
|
||||
"""Get background, number, and highlight styles for line numbers."""
|
||||
background_style = Style(bgcolor=self._pygments_style_class.background_color)
|
||||
if console.color_system in ("256", "truecolor"):
|
||||
number_style = Style.chain(
|
||||
background_style,
|
||||
self._get_theme_style(Token.Text),
|
||||
Style(color=self._get_line_numbers_color()),
|
||||
)
|
||||
highlight_number_style = Style.chain(
|
||||
background_style,
|
||||
self._get_theme_style(Token.Text),
|
||||
Style(bold=True, color=self._get_line_numbers_color(0.9)),
|
||||
)
|
||||
else:
|
||||
number_style = highlight_number_style = Style()
|
||||
return background_style, number_style, highlight_number_style
|
||||
|
||||
def __console_width__(self, max_width: int) -> "RenderWidth":
|
||||
if self.code_width is not None:
|
||||
width = self.code_width + self._numbers_column_width
|
||||
|
@ -199,23 +219,20 @@ class Syntax:
|
|||
|
||||
numbers_column_width = self._numbers_column_width
|
||||
render_options = options.update(width=code_width + numbers_column_width)
|
||||
background_style = Style(bgcolor=self._pygments_style_class.background_color)
|
||||
|
||||
number_style = Style.chain(
|
||||
(
|
||||
background_style,
|
||||
self._get_theme_style(Token.Text),
|
||||
Style(color=self._get_line_numbers_color()),
|
||||
)
|
||||
highlight_number_style = Style.chain(
|
||||
background_style,
|
||||
self._get_theme_style(Token.Text),
|
||||
Style(bold=True, color=self._get_line_numbers_color(0.9)),
|
||||
)
|
||||
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 = "->" if WINDOWS else "❱ "
|
||||
|
||||
for line_no, line in enumerate(lines, self.start_line + line_offset):
|
||||
wrapped_lines = console.render_lines(
|
||||
line, render_options, style=background_style
|
||||
|
@ -224,7 +241,7 @@ class Syntax:
|
|||
if first:
|
||||
line_column = str(line_no).rjust(numbers_column_width - 2) + " "
|
||||
if highlight_line(line_no):
|
||||
yield _Segment("❱ ", number_style)
|
||||
yield _Segment(line_pointer, number_style)
|
||||
yield _Segment(
|
||||
line_column, highlight_number_style,
|
||||
)
|
||||
|
@ -252,9 +269,9 @@ def __init__(self):
|
|||
syntax = Syntax(CODE, "python", line_numbers=False, theme="monokai")
|
||||
syntax = Syntax.from_path(
|
||||
"rich/segment.py",
|
||||
theme="monokai",
|
||||
theme="fruity",
|
||||
line_numbers=True,
|
||||
line_range=(190, 300),
|
||||
# line_range=(190, 300),
|
||||
highlight_lines={194},
|
||||
)
|
||||
console = Console(record=True)
|
||||
|
|
|
@ -488,11 +488,13 @@ if __name__ == "__main__": # pragma: no cover
|
|||
expand=True,
|
||||
show_footer=True,
|
||||
show_edge=True,
|
||||
width=100,
|
||||
style="on blue",
|
||||
)
|
||||
# table.columns[0].width = 50
|
||||
# table.columns[1].ratio = 1
|
||||
|
||||
table.add_row("Hello, World! " * 8, "cake" * 10)
|
||||
table.add_row("Hello, World! " * 3, "cake" * 10)
|
||||
from .markdown import Markdown
|
||||
|
||||
table.add_row(Markdown("# This is *Markdown*!"), "More text", "Hello WOrld")
|
||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import absolute_import
|
|||
|
||||
from dataclasses import dataclass, field
|
||||
import sys
|
||||
import platform
|
||||
from traceback import extract_tb
|
||||
from types import TracebackType
|
||||
from typing import Optional, Type, List
|
||||
|
@ -17,6 +18,7 @@ from .constrain import Constrain
|
|||
from .highlighter import RegexHighlighter, ReprHighlighter
|
||||
from .padding import Padding
|
||||
from .panel import Panel
|
||||
from .pygments_themes.base16_dark import base16_default_dark
|
||||
from .rule import Rule
|
||||
from .segment import Segment
|
||||
from .text import Text
|
||||
|
@ -24,6 +26,9 @@ from ._tools import iter_last
|
|||
from .syntax import Syntax
|
||||
|
||||
|
||||
WINDOWS = platform.system() == "Windows"
|
||||
|
||||
|
||||
def install(width: Optional[int] = 100, extra_lines: int = 2) -> None:
|
||||
"""Install a rich traceback handler.
|
||||
|
||||
|
@ -205,6 +210,7 @@ class Traceback:
|
|||
@render_group()
|
||||
def _render_stack(self, stack: Stack) -> RenderResult:
|
||||
path_highlighter = PathHighlighter()
|
||||
theme = "fruity" if WINDOWS else "monokai"
|
||||
for frame in stack.frames:
|
||||
text = Text.assemble(
|
||||
(" File ", "traceback.text"),
|
||||
|
@ -220,6 +226,7 @@ class Traceback:
|
|||
try:
|
||||
syntax = Syntax.from_path(
|
||||
frame.filename,
|
||||
theme=theme,
|
||||
line_numbers=True,
|
||||
line_range=(
|
||||
frame.lineno - self.extra_lines,
|
||||
|
|
Loading…
Reference in New Issue