mirror of https://github.com/Textualize/rich.git
Add Iso8601Highlighter
Add ability to highlight date and time strings according to ISO8601 [1] [1] https://en.wikipedia.org/wiki/ISO_8601
This commit is contained in:
parent
aa7926c143
commit
2707a73435
|
@ -5,6 +5,15 @@ 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).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix text wrapping edge case https://github.com/Textualize/rich/pull/2296
|
||||
- Allow exceptions that are raised while a Live is rendered to be displayed and/or processed https://github.com/Textualize/rich/pull/2305
|
||||
- Fix crashes that can happen with `inspect` when docstrings contain some special control codes https://github.com/Textualize/rich/pull/2294
|
||||
- Fix edges used in first row of tables when `show_header=False` https://github.com/Textualize/rich/pull/2330
|
||||
|
||||
## [12.4.4] - 2022-05-24
|
||||
|
||||
### Changed
|
||||
|
|
|
@ -40,3 +40,6 @@ The following people have contributed to the development of Rich:
|
|||
- [Gabriele N. Tornetta](https://github.com/p403n1x87)
|
||||
- [Arian Mollik Wasi](https://github.com/wasi-master)
|
||||
- [Handhika Yanuar Pratama](https://github.com/theDreamer911)
|
||||
- [za](https://github.com/za)
|
||||
- [Motahhar Mokfi](https://github.com/motahhar)
|
||||
- [Tomer Shalev](https://github.com/tomers)
|
|
@ -4,6 +4,7 @@ Highlighting
|
|||
============
|
||||
|
||||
Rich can apply styles to patterns in text which you :meth:`~rich.console.Console.print` or :meth:`~rich.console.Console.log`. With the default settings, Rich will highlight things such as numbers, strings, collections, booleans, None, and a few more exotic patterns such as file paths, URLs and UUIDs.
|
||||
Additional non-default highlighter are available, such as :class:`~rich.highlighter.ISO8601Highlighter` to highlight date and time.
|
||||
|
||||
You can disable highlighting either by setting ``highlight=False`` on :meth:`~rich.console.Console.print` or :meth:`~rich.console.Console.log`, or by setting ``highlight=False`` on the :class:`~rich.console.Console` constructor which disables it everywhere. If you disable highlighting on the constructor, you can still selectively *enable* highlighting with ``highlight=True`` on print/log.
|
||||
|
||||
|
|
|
@ -157,6 +157,9 @@ DEFAULT_STYLES: Dict[str, Style] = {
|
|||
"markdown.h7": Style(italic=True, dim=True),
|
||||
"markdown.link": Style(color="bright_blue"),
|
||||
"markdown.link_url": Style(color="blue"),
|
||||
"iso8601.date": Style(color="blue"),
|
||||
"iso8601.time": Style(color="magenta"),
|
||||
"iso8601.timezone": Style(color="yellow"),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -140,6 +140,64 @@ class JSONHighlighter(RegexHighlighter):
|
|||
break
|
||||
|
||||
|
||||
class ISO8601Highlighter(RegexHighlighter):
|
||||
"""Highlights the ISO8601 date time strings.
|
||||
Regex reference: https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s07.html
|
||||
"""
|
||||
|
||||
base_style = "iso8601."
|
||||
highlights = [
|
||||
#
|
||||
# Dates
|
||||
#
|
||||
# Calendar month (e.g. 2008-08). The hyphen is required
|
||||
r"^(?P<year>[0-9]{4})-(?P<month>1[0-2]|0[1-9])$",
|
||||
# Calendar date w/o hyphens (e.g. 20080830)
|
||||
r"^(?P<date>(?P<year>[0-9]{4})(?P<month>1[0-2]|0[1-9])(?P<day>3[01]|0[1-9]|[12][0-9]))$",
|
||||
# Ordinal date (e.g. 2008-243). The hyphen is optional
|
||||
r"^(?P<date>(?P<year>[0-9]{4})-?(?P<day>36[0-6]|3[0-5][0-9]|[12][0-9]{2}|0[1-9][0-9]|00[1-9]))$",
|
||||
#
|
||||
# Weeks
|
||||
#
|
||||
# Week of the year (e.g., 2008-W35). The hyphen is optional
|
||||
r"^(?P<date>(?P<year>[0-9]{4})-?W(?P<week>5[0-3]|[1-4][0-9]|0[1-9]))$",
|
||||
# Week date (e.g., 2008-W35-6). The hyphens are optional
|
||||
r"^(?P<date>(?P<year>[0-9]{4})-?W(?P<week>5[0-3]|[1-4][0-9]|0[1-9])-?(?P<day>[1-7]))$",
|
||||
#
|
||||
# Times
|
||||
#
|
||||
# Hours and minutes (e.g., 17:21). The colon is optional
|
||||
r"^(?P<time>(?P<hour>2[0-3]|[01][0-9]):?(?P<minute>[0-5][0-9]))$",
|
||||
# Hours, minutes, and seconds w/o colons (e.g., 172159)
|
||||
r"^(?P<time>(?P<hour>2[0-3]|[01][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9]))$",
|
||||
# Time zone designator (e.g., Z, +07 or +07:00). The colons and the minutes are optional
|
||||
r"^(?P<timezone>(Z|[+-](?:2[0-3]|[01][0-9])(?::?(?:[0-5][0-9]))?))$",
|
||||
# Hours, minutes, and seconds with time zone designator (e.g., 17:21:59+07:00).
|
||||
# All the colons are optional. The minutes in the time zone designator are also optional
|
||||
r"^(?P<time>(?P<hour>2[0-3]|[01][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9]))(?P<timezone>Z|[+-](?:2[0-3]|[01][0-9])(?::?(?:[0-5][0-9]))?)$",
|
||||
#
|
||||
# Date and Time
|
||||
#
|
||||
# Calendar date with hours, minutes, and seconds (e.g., 2008-08-30 17:21:59 or 20080830 172159).
|
||||
# A space is required between the date and the time. The hyphens and colons are optional.
|
||||
# This regex matches dates and times that specify some hyphens or colons but omit others.
|
||||
# This does not follow ISO 8601
|
||||
r"^(?P<date>(?P<year>[0-9]{4})(?P<hyphen>-)?(?P<month>1[0-2]|0[1-9])(?(hyphen)-)(?P<day>3[01]|0[1-9]|[12][0-9])) (?P<time>(?P<hour>2[0-3]|[01][0-9])(?(hyphen):)(?P<minute>[0-5][0-9])(?(hyphen):)(?P<second>[0-5][0-9]))$",
|
||||
#
|
||||
# XML Schema dates and times
|
||||
#
|
||||
# Date, with optional time zone (e.g., 2008-08-30 or 2008-08-30+07:00).
|
||||
# Hyphens are required. This is the XML Schema 'date' type
|
||||
r"^(?P<date>(?P<year>-?(?:[1-9][0-9]*)?[0-9]{4})-(?P<month>1[0-2]|0[1-9])-(?P<day>3[01]|0[1-9]|[12][0-9]))(?P<timezone>Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$",
|
||||
# Time, with optional fractional seconds and time zone (e.g., 01:45:36 or 01:45:36.123+07:00).
|
||||
# There is no limit on the number of digits for the fractional seconds. This is the XML Schema 'time' type
|
||||
r"^(?P<time>(?P<hour>2[0-3]|[01][0-9]):(?P<minute>[0-5][0-9]):(?P<second>[0-5][0-9])(?P<frac>\.[0-9]+)?)(?P<timezone>Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$",
|
||||
# Date and time, with optional fractional seconds and time zone (e.g., 2008-08-30T01:45:36 or 2008-08-30T01:45:36.123Z).
|
||||
# This is the XML Schema 'dateTime' type
|
||||
r"^(?P<date>(?P<year>-?(?:[1-9][0-9]*)?[0-9]{4})-(?P<month>1[0-2]|0[1-9])-(?P<day>3[01]|0[1-9]|[12][0-9]))T(?P<time>(?P<hour>2[0-3]|[01][0-9]):(?P<minute>[0-5][0-9]):(?P<second>[0-5][0-9])(?P<ms>\.[0-9]+)?)(?P<timezone>Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$",
|
||||
]
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
from .console import Console
|
||||
|
||||
|
|
|
@ -4,7 +4,12 @@ from typing import List
|
|||
|
||||
import pytest
|
||||
|
||||
from rich.highlighter import JSONHighlighter, NullHighlighter, ReprHighlighter
|
||||
from rich.highlighter import (
|
||||
JSONHighlighter,
|
||||
NullHighlighter,
|
||||
ReprHighlighter,
|
||||
ISO8601Highlighter,
|
||||
)
|
||||
from rich.text import Span, Text
|
||||
|
||||
|
||||
|
@ -179,3 +184,249 @@ def test_highlight_json_no_indent():
|
|||
Span(1, 7, "json.key"),
|
||||
Span(18, 25, "json.key"),
|
||||
]
|
||||
|
||||
|
||||
iso8601_highlight_tests = [
|
||||
("2008-08", [Span(0, 4, "iso8601.year"), Span(5, 7, "iso8601.month")]),
|
||||
(
|
||||
"2008-08-30",
|
||||
[
|
||||
Span(0, 10, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(5, 7, "iso8601.month"),
|
||||
Span(8, 10, "iso8601.day"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"20080830",
|
||||
[
|
||||
Span(0, 8, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(4, 6, "iso8601.month"),
|
||||
Span(6, 8, "iso8601.day"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008-243",
|
||||
[
|
||||
Span(0, 8, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(5, 8, "iso8601.day"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008243",
|
||||
[
|
||||
Span(0, 7, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(4, 7, "iso8601.day"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008-W35",
|
||||
[
|
||||
Span(0, 8, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(6, 8, "iso8601.week"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008W35",
|
||||
[
|
||||
Span(0, 7, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(5, 7, "iso8601.week"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008-W35-6",
|
||||
[
|
||||
Span(0, 10, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(6, 8, "iso8601.week"),
|
||||
Span(9, 10, "iso8601.day"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008W356",
|
||||
[
|
||||
Span(0, 8, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(5, 7, "iso8601.week"),
|
||||
Span(7, 8, "iso8601.day"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"17:21",
|
||||
[
|
||||
Span(0, 5, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(3, 5, "iso8601.minute"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"1721",
|
||||
[
|
||||
Span(0, 4, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(2, 4, "iso8601.minute"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"172159",
|
||||
[
|
||||
Span(0, 6, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(2, 4, "iso8601.minute"),
|
||||
Span(4, 6, "iso8601.second"),
|
||||
],
|
||||
),
|
||||
("Z", [Span(0, 1, "iso8601.timezone")]),
|
||||
("+07", [Span(0, 3, "iso8601.timezone")]),
|
||||
("+07:00", [Span(0, 6, "iso8601.timezone")]),
|
||||
(
|
||||
"17:21:59+07:00",
|
||||
[
|
||||
Span(0, 8, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(3, 5, "iso8601.minute"),
|
||||
Span(6, 8, "iso8601.second"),
|
||||
Span(8, 14, "iso8601.timezone"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"172159+0700",
|
||||
[
|
||||
Span(0, 6, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(2, 4, "iso8601.minute"),
|
||||
Span(4, 6, "iso8601.second"),
|
||||
Span(6, 11, "iso8601.timezone"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"172159+07",
|
||||
[
|
||||
Span(0, 6, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(2, 4, "iso8601.minute"),
|
||||
Span(4, 6, "iso8601.second"),
|
||||
Span(6, 9, "iso8601.timezone"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008-08-30 17:21:59",
|
||||
[
|
||||
Span(0, 10, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(4, 5, "iso8601.hyphen"),
|
||||
Span(5, 7, "iso8601.month"),
|
||||
Span(8, 10, "iso8601.day"),
|
||||
Span(11, 19, "iso8601.time"),
|
||||
Span(11, 13, "iso8601.hour"),
|
||||
Span(14, 16, "iso8601.minute"),
|
||||
Span(17, 19, "iso8601.second"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"20080830 172159",
|
||||
[
|
||||
Span(0, 8, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(4, 6, "iso8601.month"),
|
||||
Span(6, 8, "iso8601.day"),
|
||||
Span(9, 15, "iso8601.time"),
|
||||
Span(9, 11, "iso8601.hour"),
|
||||
Span(11, 13, "iso8601.minute"),
|
||||
Span(13, 15, "iso8601.second"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008-08-30",
|
||||
[
|
||||
Span(0, 10, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(5, 7, "iso8601.month"),
|
||||
Span(8, 10, "iso8601.day"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008-08-30+07:00",
|
||||
[
|
||||
Span(0, 10, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(5, 7, "iso8601.month"),
|
||||
Span(8, 10, "iso8601.day"),
|
||||
Span(10, 16, "iso8601.timezone"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"01:45:36",
|
||||
[
|
||||
Span(0, 8, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(3, 5, "iso8601.minute"),
|
||||
Span(6, 8, "iso8601.second"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"01:45:36.123+07:00",
|
||||
[
|
||||
Span(0, 12, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(3, 5, "iso8601.minute"),
|
||||
Span(6, 8, "iso8601.second"),
|
||||
Span(8, 12, "iso8601.frac"),
|
||||
Span(12, 18, "iso8601.timezone"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"01:45:36.123+07:00",
|
||||
[
|
||||
Span(0, 12, "iso8601.time"),
|
||||
Span(0, 2, "iso8601.hour"),
|
||||
Span(3, 5, "iso8601.minute"),
|
||||
Span(6, 8, "iso8601.second"),
|
||||
Span(8, 12, "iso8601.frac"),
|
||||
Span(12, 18, "iso8601.timezone"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008-08-30T01:45:36",
|
||||
[
|
||||
Span(0, 10, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(5, 7, "iso8601.month"),
|
||||
Span(8, 10, "iso8601.day"),
|
||||
Span(11, 19, "iso8601.time"),
|
||||
Span(11, 13, "iso8601.hour"),
|
||||
Span(14, 16, "iso8601.minute"),
|
||||
Span(17, 19, "iso8601.second"),
|
||||
],
|
||||
),
|
||||
(
|
||||
"2008-08-30T01:45:36.123Z",
|
||||
[
|
||||
Span(0, 10, "iso8601.date"),
|
||||
Span(0, 4, "iso8601.year"),
|
||||
Span(5, 7, "iso8601.month"),
|
||||
Span(8, 10, "iso8601.day"),
|
||||
Span(11, 23, "iso8601.time"),
|
||||
Span(11, 13, "iso8601.hour"),
|
||||
Span(14, 16, "iso8601.minute"),
|
||||
Span(17, 19, "iso8601.second"),
|
||||
Span(19, 23, "iso8601.ms"),
|
||||
Span(23, 24, "iso8601.timezone"),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test, spans", iso8601_highlight_tests)
|
||||
def test_highlight_iso8601_regex(test: str, spans: List[Span]):
|
||||
"""Tests for the regular expressions used in ISO8601Highlighter."""
|
||||
text = Text(test)
|
||||
highlighter = ISO8601Highlighter()
|
||||
highlighter.highlight(text)
|
||||
print(text.spans)
|
||||
assert text.spans == spans
|
||||
|
|
Loading…
Reference in New Issue